!==================================================================================
! Класс интерфейса с библиотекой CUrl (командная строка).
! Вячеслав Черников, г.Рязань, 2015г.
!==================================================================================

                     MEMBER

   INCLUDE('FsCUrl.INC')
   INCLUDE('WINEQU.INC')

   MAP
     INCLUDE('BUILTINS.CLW'),ONCE   !функции RTL

     MODULE('WINAPI')
       CreateProcess      (LONG,LONG,LONG,LONG,BOOL,DWORD,LONG,LONG,LONG,LONG),BOOL,RAW,PASCAL,NAME('CreateProcessA')
       GetExitCodeProcess (LONG, LONG),BOOL,RAW,PASCAL
       FormatMessage      (DWORD,ULONG,DWORD,DWORD,*CSTRING,DWORD,long),DWORD,PASCAL,RAW,NAME('FormatMessageA')
       GetLastError       (),LONG,PASCAL 

       GetWindowThreadProcessId(ulong,*ulong),long,pascal,raw
       TerminateProcess(long hProcess, long uExitCode),bool,pascal
       GetExitCodeProcess(long hProcess, *long lpExitCode),bool,pascal,proc
       OpenProcess(ulong dwDesiredAccess, bool bInheritHandle, ulong dwProcessId),ulong,pascal

       CreateFile(*CSTRING,ULONG,ULONG,LONG,ULONG,ULONG,UNSIGNED=0),UNSIGNED,RAW,PASCAL,NAME('CreateFileA')
       GetFileSize(UNSIGNED,*ULONG),ULONG,PASCAL,NAME('GetFileSize')
       ReadFile(UNSIGNED,LONG,ULONG,*ULONG,LONG),BOOL,PASCAL,RAW,NAME('ReadFile')
       WriteFile(UNSIGNED,<*?>,ULONG,*ULONG,<*?>),BOOL,PASCAL,RAW,PROC
       CloseHandle(UNSIGNED),BOOL,PASCAL,PROC,NAME('CloseHandle')

       ShellExecute(UNSIGNED,*CSTRING,*CSTRING,*CSTRING,*CSTRING,SIGNED),UNSIGNED,PASCAL,RAW,PROC,NAME('ShellExecuteA')
     END

     MODULE('Smtp.c')
         md5(*CSTRING _Str,ULONG _Len,long _ResString),RAW,NAME('_MDString')
         hmac_md5(*CSTRING _Str,ULONG _Len,*CSTRING _Key,ULONG _LenKey,long _ResString),RAW,NAME('_hmac_md5')
         str_to_base64(*STRING InBuf, <*STRING OutBuf>),UNSIGNED,NAME('_str_to_base64')
         base64_to_str(*STRING InBuf, <*STRING OutBuf>),UNSIGNED,NAME('_base64_to_str')
     END

     MODULE('Clarion RTL')
         PushTempStr(STRING,LONG),RAW,NAME('Cla$PushTemp')
     END
   END

PROCESS_TERMINATE         equate(01h)
PROCESS_QUERY_INFORMATION equate(0400h)
FILE_ATTRIBUTE_NORMAL     equate(00000080H)

Boundary            STRING('NeXtPaRtFoRmAiL')
                    
Email_ToKoi8Over    STRING('<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50>'&|
                           '<51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100>'&|
                           '<101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150>'&|
                           '<151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,179,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183>Ј<185,186,187,188,189,190,191>'&|
                           'бвчздецъйклмнопртуфхжигюыэящшьасБВЧЗДЕЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАС')
EMail_ToKoi8        BYTE,DIM(SIZE(Email_ToKoi8Over)),OVER(Email_ToKoi8Over)
EMail_FromKoi8      BYTE,DIM(SIZE(Email_ToKoi8Over))

!===================================================================================
! Инициализация класса
!
FsCurl.Init PROCEDURE 
      CODE

   if SELF.Active=1
      return
   end

   SELF.FlagWait  = 1
   SELF.FlagShow  = 0

   SELF.QueueCurl &=  new(QueueCurlType)     !создание буфера
   SELF.QueueInput &=  new(QueueCurlType)

   SELF.BufPoint     =0
   SELF.BufPointMax  = 1024
   SELF.MailPoint    =0
   SELF.MailPointMax = 1024

   SELF.Active=1

!===================================================================================
! Деактивация класса
!
FsCurl.Kill PROCEDURE
      CODE

   if SELF.Active=0
      return
   end

   free(SELF.QueueCurl)
   free(SELF.QueueInput)

   dispose(SELF.QueueCurl)
   dispose(SELF.QueueInput)

   SELF.Active=0

!===================================================================================
!
! Деструктор класса
!
FsCurl.Destruct PROCEDURE
   CODE
      SELF.Kill

!===================================================================================
!
! Запустить процесс
!
FsCurl.StartProcess FUNCTION (STRING pName)

loc:ok       byte
loc:prgName  &cstring
loc:error    ulong  
loc:errorTxt cstring(1024)

loc:Progress  long
Loc:Time      long

Window WINDOW('Выполнение'),AT(,,170,56),FONT(,8,,FONT:regular,CHARSET:ANSI),CENTER,IMM,CENTERED,GRAY, |
         DOUBLE,MASK,MDI
       PROGRESS,USE(loc:Progress),AT(6,8,158,8),RANGE(0,100)
       STRING('Врем<255>, сек:'),AT(6,22),USE(?Time:Prompt),FONT(,8,,FONT:regular,CHARSET:ANSI)
       STRING(@s10),AT(47,22,44,10),USE(Loc:Time),FONT(,8,,FONT:regular,CHARSET:ANSI)
       BUTTON('Прервать'),AT(63,38,45,14),USE(?Close),DISABLE,FONT(,8,,FONT:regular,CHARSET:ANSI)
     END

   CODE
      
   if SELF.Active=0
      return(0)
   end

   if pName=''
      return(0)
   end  

   loc:prgName &= new(cstring(len(clip(pName))+1))

   loc:prgName = clip(pName)
   loc:ok=1

   SELF.StartUpInfo.cb = size(SELF.StartUpInfo)
   SELF.StartUpInfo.dwFlags = STARTF_USESHOWWINDOW
   SELF.StartUpInfo.wShowWindow = SELF.FlagShow
   if CreateProcess(0,address(loc:prgName),0,0,FALSE,0,0,0,address(SELF.StartUpInfo),address(SELF.Process_Information))   
      if SELF.FlagWait>0
         do wait_r
      end  
   else
     loc:error = GetLastError()
     if FormatMessage(00001000H,0,loc:error,0,loc:errorTxt,size(loc:errorTxt),0).
     message(loc:prgName & '|' & loc:error & '-' & loc:errorTxt,'Ошибка')    
     loc:ok=0
   end

   dispose(loc:prgName)
   return(loc:ok)

wait_r routine   !ожидание
   loc:Progress=0
   Loc:Time=0

   OPEN(Window)
   if SELF.WindowTitle<>''
      Window{PROP:TEXT}=SELF.WindowTitle
   end
   Window{PROP:TIMER}=100
   display

   ACCEPT
     CASE EVENT()
       of EVENT:TIMER
          if GetExitCodeProcess(SELF.Process_Information.hProcess, address(loc:error))
             if loc:error<>259 
                loc:time+=1
                loc:Progress=100
                display 
                break
             end

             loc:time+=1
             loc:Progress+=10
             if loc:Progress>100
                loc:Progress=10
             end
             if loc:time>20
                ?Close{PROP:DISABLE}=false
             end
             display
          else
             loc:error = GetLastError()
             loc:ok=0 
             if FormatMessage(00001000H,0,loc:error,0,loc:errorTxt,size(loc:errorTxt),0).
             message(loc:prgName & '|' & loc:error & '-' & loc:errorTxt,'Ошибка')    
             break
          end
       of EVENT:ACCEPTED
          if field()=?Close
             if SELF.KillProcess()=1
                loc:ok=0 
                break
             end
          end
     end
   end

   CLOSE(Window) 

!===================================================================================
!
! Убить процесс
!
FsCurl.KillProcess FUNCTION ()

loc:ProcessId long
loc:hProcess  ulong
loc:ExitCode  long

loc:ok   byte

   CODE
      
   if SELF.Active=0
      return(0)
   end

   loc:ProcessId = SELF.Process_Information.dwProcessId  
   if loc:ProcessId=0
      return(0)
   end

   loc:ok=1

   loc:hProcess=OpenProcess(PROCESS_QUERY_INFORMATION+PROCESS_TERMINATE,False,loc:ProcessId) 
   if loc:hProcess<>0
      if GetExitCodeProcess(loc:hProcess, loc:ExitCode)
        if ~TerminateProcess(loc:hProcess, loc:ExitCode)
           loc:ok=0
        else
           CloseHandle(loc:hProcess)
        end
      else
        loc:ok=0
     end
  else
     loc:ok=0
  end

  return(loc:ok)

!===================================================================================
!
! Запустить процесс для строки из буфера
!
FsCurl.StartProcessExt FUNCTION ()
loc:BufferLength  ULONG
loc:Buffer        &STRING

loc:recs          long
loc:len           long
loc:i             long
loc:ok            byte

   CODE
      
   if SELF.Active=0
      return(0)
   end

   loc:len=len(SELF.QueueCurl)
   loc:recs=records(SELF.QueueCurl)

   if loc:recs=0 and SELF.BufPoint=0
       return(0)
   end

   if SELF.BufPoint<>0
      add(SELF.QueueCurl)
   end

   loc:BufferLength = loc:len*loc:recs+SELF.BufPoint+1

   loc:Buffer &= new(STRING(loc:BufferLength))
   loop loc:i=1 to records(SELF.QueueCurl) 
      get(SELF.QueueCurl,loc:i)
      if loc:i=1
         loc:Buffer=SELF.QueueCurl 
      else
         loc:Buffer=sub(loc:Buffer,1,loc:len*(loc:i-1)) & SELF.QueueCurl
      end
   end

   !setclipboard('curl ' & clip(loc:Buffer))   

   loc:ok=SELF.StartProcess('curl ' & loc:Buffer)

   clear(loc:Buffer)
   dispose(loc:Buffer)     

   return(loc:ok)

!===================================================================================
!
! Очистить буфер 
!
FsCurl.ClearBuffer    PROCEDURE
   CODE

      if SELF.Active = 0
         return
      end    

      free(SELF.QueueCurl)
      clear(SELF.QueueCurl)
      SELF.BufPoint=0

!===================================================================================
!
! Добавить строку в буфер 
!
FsCurl.AddBuffer    PROCEDURE (STRING Str)
loc:dl  long
loc:poz long
   CODE

      if SELF.Active = 0
         return
      end    

      loc:dl = len(clip(str))+2
      loc:poz = 0

      if (SELF.BufPoint+loc:dl)<=SELF.BufPointMax   !вся строка помещается в строку буфера
         if SELF.BufPoint=0
            SELF.QueueCurl = str
         else
            SELF.QueueCurl = sub(SELF.QueueCurl,1,SELF.BufPoint) & ' ' & str
         end
         SELF.BufPoint += loc:dl
         return
      end

      if SELF.BufPoint>0 and (SELF.BufPoint+loc:dl)>=SELF.BufPointMax  !дописываем последнюю строку в кьюшке скрипта
         SELF.QueueCurl = sub(SELF.QueueCurl,1,SELF.BufPoint) & sub(clip(str),1,SELF.BufPointMax-SELF.BufPoint)
         add(SELF.QueueCurl)
         loc:poz=SELF.BufPointMax-SELF.BufPoint
         SELF.BufPoint=0
      end

      loop  !вписываем целые части
         if loc:dl-loc:poz<SELF.BufPointMax
            break
         end 
         SELF.QueueCurl = sub(clip(str),loc:poz+1,SELF.BufPointMax)
         add(SELF.QueueCurl)
         loc:poz+=SELF.BufPointMax
      end

      if loc:dl-loc:poz>0
         SELF.QueueCurl = sub(clip(str),loc:poz+1,loc:dl-loc:poz)
         SELF.BufPoint=loc:dl-loc:poz
      end

!===================================================================================
!
! Очистить буфер файла параметров
!
FsCurl.ClearInput    PROCEDURE
   CODE

      if SELF.Active = 0
         return
      end    

      free(SELF.QueueInput)
      clear(SELF.QueueInput)
      SELF.MailPoint=0

!===================================================================================
!
! Добавить строку к файлу параметров
!
FsCurl.AddInput    PROCEDURE (STRING Str, <BYTE Reg>)
loc:dl  long
loc:poz long
loc:end string(2)
   CODE

      if SELF.Active = 0
         return
      end    

      loc:end=CHR(13) & CHR(10)
      if ~omitted(3)
         if Reg<>0
            loc:end=''
         end
      end 

      loc:dl = len(clip(str))+len(clip(loc:end))
      loc:poz = 0

      if (SELF.MailPoint+loc:dl)<=SELF.MailPointMax   !вся строка помещается в строку буфера
         if SELF.MailPoint=0
            SELF.QueueInput = clip(str) & loc:end
         else
            SELF.QueueInput = sub(SELF.QueueInput,1,SELF.MailPoint) & clip(str) & loc:end
         end
         SELF.MailPoint += loc:dl
         return
      end

      if SELF.MailPoint>0 and (SELF.MailPoint+loc:dl)>=SELF.MailPointMax  !дописываем последнюю строку в кьюшке скрипта
         SELF.QueueInput = sub(SELF.QueueInput,1,SELF.MailPoint) & sub(clip(str) & loc:end,1,SELF.MailPointMax-SELF.MailPoint)
         add(SELF.QueueInput)
         loc:poz=SELF.MailPointMax-SELF.MailPoint
         SELF.MailPoint=0
      end

      loop  !вписываем целые части
         if loc:dl-loc:poz<SELF.MailPointMax
            break
         end 
         SELF.QueueInput = sub(clip(str) & loc:end,loc:poz+1,SELF.MailPointMax)
         add(SELF.QueueInput)
         loc:poz+=SELF.MailPointMax
      end

      if loc:dl-loc:poz>0
         SELF.QueueInput = sub(clip(str) & loc:end,loc:poz+1,loc:dl-loc:poz)
         SELF.MailPoint=loc:dl-loc:poz
      end

!===================================================================================
! Сформировать файл параметров
!
FsCurl.MakeInput PROCEDURE 

loc:LocalFile     CSTRING(255)   !имя локального файла
loc:hLocal        UNSIGNED       !ссылка на локальный файл
loc:BufferLength  ULONG
loc:Buffer        &CSTRING

loc:recs          long
loc:len           long
loc:i             long
loc:err           byte

      CODE

      if SELF.Active=0
         return
      end

      loc:len=len(SELF.QueueInput)
      loc:recs=records(SELF.QueueInput)

      if loc:recs=0 and SELF.MailPoint=0
         return
      end

      if SELF.MailPoint<>0
         add(SELF.QueueInput)
      end

      loc:BufferLength = loc:len*loc:recs+SELF.MailPoint+1
      if SELF.PathTmp='' 
         SELF.FileNameInput = 'mail_tmp.txt'
      else
         if sub(SELF.PathTmp,len(clip(SELF.PathTmp)),1)='\'
            SELF.FileNameInput = clip(SELF.PathTmp) & '\mail_tmp.txt'
         else
            SELF.FileNameInput = clip(SELF.PathTmp) & '\mail_tmp.txt'
         end 
      end 
      
      if exists(SELF.FileNameInput)
         remove(SELF.FileNameInput)
      end

      loc:LocalFile=SELF.FileNameInput
      
      loc:Buffer &= new(CSTRING(loc:BufferLength))
      loop loc:i=1 to records(SELF.QueueInput) 
         get(SELF.QueueInput,loc:i)
         if loc:i=1
            loc:Buffer=SELF.QueueInput 
         else
            loc:Buffer=sub(loc:Buffer,1,loc:len*(loc:i-1)) & SELF.QueueInput
         end
      end         

      loc:hLocal = CreateFile(loc:LocalFile, GENERIC_READ+GENERIC_WRITE, |   !создать ссылку на выходной файл
                            FILE_SHARE_READ + FILE_SHARE_WRITE, 0 ,      |
                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,0)

      if ~WriteFile(loc:hLocal, loc:Buffer, loc:BufferLength, loc:BufferLength)  
         loc:err=1
      else
         loc:err=0 
      end

      CloseHandle(loc:hLocal)  !закрываем выходной файл

      clear(loc:Buffer)
      dispose(loc:Buffer)

      SELF.ClearInput

      if loc:err=1
         message('Ошибка при записи письма в файл ' & clip(SELF.FileNameInput))
         return
      end

!===================================================================================
! Прикрепить файл к файлу параметров
!
FsCurl.AttachFile     PROCEDURE  (STRING pFile)    

szFile                          CSTRING(FILE:MaxFileName)
hFile                           LONG
dwSize                          UNSIGNED
lpFileSizeHigh                  ULONG
pvData                          LONG
dwBytesRead                     ULONG
bRead                           BOOL
tmpline                         STRING(57)

loc:i  long

    CODE

        if SELF.Active = 0
           return
        end    

        szFile=pFile
        hFile = CreateFile(szFile,GENERIC_READ,0,0,OPEN_EXISTING,0)

        if hFile <> INVALID_HANDLE_VALUE
            dwSize = GetFileSize(hFile,lpFileSizeHigh)
            if dwSize > 0
                loop
                    bRead = ReadFile(hFile,address(tmpline),size(tmpline),dwBytesRead,0)
                    if ~dwBytesRead
                        break
                    end
                    SELF.AddInput(SELF.StringToBase64(TmpLine[1 : dwBytesRead],dwBytesRead))
                end
            end
            CloseHandle(hFile)
        end

!===================================================================================
! Приведение строки к base64
!
FsCurl.StringToBase64       FUNCTION  (STRING pString, LONG pLen)
loc:OutputString                    &String,AUTO
loc:Outlen                          Long
loc:n                               Long

    code
        loc:OutLen=(INT((pLen-1)/3)+1)*4
        loc:OutputString &= NEW(STRING(loc:OutLen))
        if loc:OutputString &= NULL 
            return('')
        end
        loc:n=Str_to_Base64(pString,loc:OutputString)        
        PushTempStr(loc:OutputString,loc:OutLen)

!===================================================================================
! Приведение строки к koi8
!
FsCurl.StringToKoi8r FUNCTION  (STRING pStr)
loc:i  long
    CODE
        loop loc:i=1 to len(clip(pStr))
            pStr[loc:i]=chr(EMail_ToKoi8[val(pStr[loc:i])])
        end

        return(pStr)

!===================================================================================
! Установить URL
!
FsCurl.SetUrl PROCEDURE  (STRING pUrl, <STRING pName>, <STRING pPswd>)
    CODE

        if SELF.Active = 0
           return
        end    

        SELF.UrlName = pUrl

        if ~omitted(3)
           SELF.UserName = pName
        end

        if ~omitted(4)
           SELF.UserPswd = pPswd
        end

!===================================================================================
! Установить параметры письма
!
FsCurl.SetMailHeader PROCEDURE  (STRING pFrom, STRING pTo, <STRING pNameFrom>, <STRING pNameTo>)
    CODE

        if SELF.Active = 0
           return
        end    

        SELF.Mail_Param.MailFrom = pFrom
        SELF.Mail_Param.MailTo   = pTo

        if ~omitted(4)
           SELF.Mail_Param.MailNameFrom = pNameFrom
        else
           SELF.Mail_Param.MailNameTo = ''
        end

        if ~omitted(5)
           SELF.Mail_Param.MailNameTo = pNameTo
        else
           SELF.Mail_Param.MailNameTo = ''
        end

!===================================================================================
! Установить текст письма
!
FsCurl.SetMailText PROCEDURE  (STRING pSubject, STRING pBody)
    CODE

        if SELF.Active = 0
           return
        end 


        SELF.Mail_Param.MailSubject = pSubject
        SELF.Mail_Param.MailBody    = pBody

!===================================================================================
!
! Выполнить простой Http-запрос
!
FsCurl.HttpRequestSymple FUNCTION (STRING pRemote, <STRING pLocal>)
loc:ok  byte
   CODE

      if SELF.Active = 0
         return(0)
      end    

      if omitted(3)
         loc:ok=SELF.StartProcess('curl -o ' & pRemote)
      else
         loc:ok=SELF.StartProcess('curl -f -o ' & clip(pLocal) & ' ' & pRemote)
         if loc:ok=1
            if ~exists(pLocal)
               message('Ошибка при выполнении http-запроса!','Ошибка')
               loc:ok=0
            end 
         end
      end

      return(loc:ok)

!===================================================================================
!
! Создать заголовок для письма
!
FsCurl.MailHeaderAdd FUNCTION ()
   CODE

      if SELF.Active = 0
         return(0)
      end   

      if SELF.UrlName=''
         message('Не задан адрес почтового сервера!','Ошибка')      
         return(0)
      end

      if SELF.UserName='' or SELF.UserPswd=''
         message('Не задано имя пользователя или пароль для авторизации на почтовом сервере!','Ошибка')      
         return(0)
      end

      if SELF.Mail_Param.MailFrom=''
         message('Не задан отправитель письма!','Ошибка')      
         return(0)
      end
      if SELF.Mail_Param.MailTo=''
         message('Не задан получатель письма!','Ошибка')      
         return(0)
      end 
      if SELF.Mail_Param.MailSubject=''
         message('Не задана тема письма!','Ошибка')      
         return(0)
      end 

      SELF.ClearInput
      SELF.Mail_Param.MailKolFiles=0

      if SELF.Mail_Param.MailNameFrom=''
         SELF.AddInput('From: ' & clip(SELF.Mail_Param.MailFrom))
      else
         SELF.AddInput('From: "' & clip(SELF.Mail_Param.MailNameFrom) & '" <' & clip(SELF.Mail_Param.MailFrom) & '>')
      end

      if SELF.Mail_Param.MailNameTo=''
         SELF.AddInput('To: ' & clip(SELF.Mail_Param.MailTo))
      else
         SELF.AddInput('To: "' & clip(SELF.Mail_Param.MailNameTo) & '" <' & clip(SELF.Mail_Param.MailTo) & '>')
      end

      SELF.AddInput('Subject: ' & clip(SELF.Mail_Param.MailSubject))

      SELF.AddInput('Content-Type: multipart/mixed;',1)
      SELF.AddInput(' boundary="' & boundary & '"')
      SELF.AddInput('MIME-Version: 1.0')    

      if SELF.Mail_Param.MailBody<>''
         SELF.AddInput('')
         SELF.AddInput('--' & boundary)
         SELF.AddInput('Content-Type: text/plain')
         SELF.AddInput('Content-Transfer-Encoding: quoted-printable')
         SELF.AddInput('')
         SELF.AddInput(clip(SELF.Mail_Param.MailBody))
      end

      return(1)

!===================================================================================
!
! Прикрепить файл к письму
!
FsCurl.MailFileAdd FUNCTION (STRING pFile)
loc:i   long
loc:ni  long
loc:l   long
   CODE

      if SELF.Active = 0
         return(0)
      end    

      if pFile=''
         return(0)
      end

      if ~exists(pFile)
         return(0)
      end

      loc:ni=0
      loc:l=len(clip(pFile))
      loop loc:i=loc:l to 1 by -1
         if pFile[loc:i]='/' or pFile[loc:i]='\' or pFile[loc:i]=':'
            break
         end 
      end
      loc:ni=loc:i      

      SELF.AddInput('')
      SELF.AddInput('--' & boundary)

      case upper(pFile[loc:l-2 : loc:l])
         of 'GIF'
            SELF.AddInput('Content-Type: image/gif;',1)
         of 'JPG'
            SELF.AddInput('Content-Type: image/gif;',1)
         else
            SELF.AddInput('Content-Type: application/octet-stream;',1)
      end

      SELF.AddInput(' name="' & clip(pFile) & '"')
      SELF.AddInput('Content-Transfer-Encoding: base64')
      SELF.AddInput('Content-Description: ' & clip(pFile))
      SELF.AddInput('Content-Disposition: attachment;',1)
      SELF.AddInput(' filename="' & clip(pFile) & '"')
      SELF.AddInput('')
      SELF.AttachFile(pFile)          

      SELF.Mail_Param.MailKolFiles+=1
      return(1)

!===================================================================================
!
! Отправить письмо
!
FsCurl.MailSend FUNCTION 
loc:ok  byte
loc:i   long
loc:ni  long
loc:l   long
   CODE

      if SELF.Active = 0
         return(0)
      end    

      if SELF.Mail_Param.MailKolFiles>0
         SELF.AddInput('--' & boundary & '--')
      end

      SELF.MakeInput   !сохранить файл с письмом

      SELF.ClearBuffer

      if sub(SELF.UrlName,1,8) = 'smtps://'
         SELF.Mail_Param.FlagSSL=1
      else
         SELF.Mail_Param.FlagSSL=0
      end

      SELF.AddBuffer('--url "' & clip(SELF.UrlName) & '"')
      if SELF.Mail_Param.FlagSSL=1
         SELF.AddBuffer('--ssl-reqd')
      end 

      SELF.AddBuffer('--mail-from "' & clip(SELF.Mail_Param.MailFrom) & '" --mail-rcpt "' & clip(SELF.Mail_Param.MailTo) & '"')
      SELF.AddBuffer('--upload-file ' & clip(SELF.FileNameInput))
      SELF.AddBuffer('--user "' & clip(SELF.UserName) & ':' & clip(SELF.UserPswd) & '" --insecure')

      loc:ok=SELF.StartProcessExt()
      return(loc:ok)  
 
