about summary refs log tree commit diff stats
path: root/src
ModeNameSize
-rw-r--r--chat_session.c6732log stats plain blame
-rw-r--r--chat_session.h1904log stats plain blame
d---------command220log stats plain
-rw-r--r--common.c10024log stats plain blame
-rw-r--r--common.h2741log stats plain blame
d---------config228log stats plain
-rw-r--r--contact.c7818log stats plain blame
-rw-r--r--contact.h2412log stats plain blame
-rw-r--r--contact_list.c5815log stats plain blame
-rw-r--r--contact_list.h1862log stats plain blame
-rw-r--r--jid.c5092log stats plain blame
-rw-r--r--jid.h1488log stats plain blame
-rw-r--r--log.c11199log stats plain blame
-rw-r--r--log.h1718log stats plain blame
-rw-r--r--main.c2232log stats plain blame
-rw-r--r--muc.c9801log stats plain blame
-rw-r--r--muc.h2203log stats plain blame
-rw-r--r--profanity.c17038log stats plain blame
-rw-r--r--profanity.h3667log stats plain blame
-rw-r--r--resource.c2665log stats plain blame
-rw-r--r--resource.h1255log stats plain blame
d---------tools232log stats plain
d---------ui293log stats plain
d---------xmpp484log stats plain
b8c79787b67'>05b64a1d ^
a78c2619 ^
87f9bd65 ^



e2203257 ^

05b64a1d ^
17097052 ^
05b64a1d ^





8027e52c ^
05b64a1d ^






8027e52c ^





05b64a1d ^
8027e52c ^
05b64a1d ^

05b64a1d ^





e2203257 ^
e38402df ^



e2203257 ^

05b64a1d ^

e2203257 ^
05b64a1d ^
e2203257 ^
c235e638 ^


e2203257 ^
05b64a1d ^

e2203257 ^

05b64a1d ^
e2203257 ^
e2203257 ^

05b64a1d ^




6a990cef ^

05b64a1d ^


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




                    
                 
                 
                    

                     
                
                


                   


                                 
                    
                    
                    





                                                                               
                          











                                         














                                                                                                        
                                     

                        



                                      
                     
                                                        
                                        
                 



                         
                                                          
                                 
                 

                                        
                      


                                                                                                     
                                             
               



                                                 

              
                                                                          
                            





                                          
                                       






                                                   





                                                                              
             
                                                               

                                                                 





                                                                             
                             



                      

                                    

                                                       
                                                   
                                             
                                                      


                                        
                         

                                   

                                
                                           
                     

                              




                                                                           

                            


                      
import options
import streams
import strutils

import bindings/curl
import io/headers
import io/request
import ips/serialize
import types/blob
import types/formdata
import types/url
import utils/opt
import utils/twtstr

type
  HandleData* = ref HandleDataObj
  HandleDataObj = object
    curl*: CURL
    statusline: bool
    headers: Headers
    request: Request
    ostream*: Stream
    mime: curl_mime
    slist: curl_slist

func newHandleData(curl: CURL, request: Request, ostream: Stream): HandleData =
  let handleData = HandleData(
    headers: newHeaders(),
    curl: curl,
    ostream: ostream,
    request: request
  )
  return handleData

proc cleanup*(handleData: HandleData) =
  if handleData.mime != nil:
    curl_mime_free(handleData.mime)
  if handleData.slist != nil:
    curl_slist_free_all(handleData.slist)
  curl_easy_cleanup(handleData.curl)

template setopt(curl: CURL, opt: CURLoption, arg: typed) =
  discard curl_easy_setopt(curl, opt, arg)

template setopt(curl: CURL, opt: CURLoption, arg: string) =
  discard curl_easy_setopt(curl, opt, cstring(arg))

template getinfo(curl: CURL, info: CURLINFO, arg: typed) =
  discard curl_easy_getinfo(curl, info, arg)

proc curlWriteHeader(p: cstring, size: csize_t, nitems: csize_t, userdata: pointer): csize_t {.cdecl.} =
  var line = newString(nitems)
  for i in 0..<nitems:
    line[i] = p[i]

  let op = cast[HandleData](userdata)
  if not op.statusline:
    op.statusline = true
    try:
      op.ostream.swrite(int(CURLE_OK))
    except IOError: # Broken pipe
      return 0
    var status: clong
    op.curl.getinfo(CURLINFO_RESPONSE_CODE, addr status)
    op.ostream.swrite(cast[int](status))
    return nitems

  let k = line.until(':')

  if k.len == line.len:
    # empty line (last, before body) or invalid (=> error)
    op.ostream.swrite(op.headers)
    return nitems

  let v = line.substr(k.len + 1).strip()
  op.headers.add(k, v)
  return nitems

proc curlWriteBody(p: cstring, size: csize_t, nmemb: csize_t, userdata: pointer): csize_t {.cdecl.} =
  let handleData = cast[HandleData](userdata)
  if nmemb > 0:
    try:
      handleData.ostream.writeData(p, int(nmemb))
    except IOError: # Broken pipe
      return 0
  return nmemb

proc applyPostBody(curl: CURL, request: Request, handleData: HandleData) =
  if request.multipart.isOk:
    handleData.mime = curl_mime_init(curl)
    if handleData.mime == nil:
      # fail (TODO: raise?)
      handleData.ostream.swrite(-1)
      handleData.ostream.flush()
      return
    for entry in request.multipart.get:
      let part = curl_mime_addpart(handleData.mime)
      if part == nil:
        # fail (TODO: raise?)
        handleData.ostream.swrite(-1)
        handleData.ostream.flush()
        return
      curl_mime_name(part, cstring(entry.name))
      if entry.isstr:
        curl_mime_data(part, cstring(entry.svalue), csize_t(entry.svalue.len))
      else:
        let blob = entry.value
        if blob.isfile: #TODO ?
          curl_mime_filedata(part, cstring(WebFile(blob).path))
        else:
          curl_mime_data(part, blob.buffer, csize_t(blob.size))
        # may be overridden by curl_mime_filedata, so set it here
        curl_mime_filename(part, cstring(entry.filename))
    curl.setopt(CURLOPT_MIMEPOST, handleData.mime)
  elif request.body.issome:
    curl.setopt(CURLOPT_POSTFIELDS, cstring(request.body.get))
    curl.setopt(CURLOPT_POSTFIELDSIZE, request.body.get.len)

proc loadHttp*(curlm: CURLM, request: Request, ostream: Stream): HandleData =
  let curl = curl_easy_init()
  if curl == nil:
    ostream.swrite(-1)
    ostream.flush()
    return # fail
  let surl = request.url.serialize()
  curl.setopt(CURLOPT_URL, surl)
  let handleData = curl.newHandleData(request, ostream)
  curl.setopt(CURLOPT_WRITEDATA, handleData)
  curl.setopt(CURLOPT_WRITEFUNCTION, curlWriteBody)
  curl.setopt(CURLOPT_HEADERDATA, handleData)
  curl.setopt(CURLOPT_HEADERFUNCTION, curlWriteHeader)
  if request.proxy != nil:
    let purl = request.proxy.serialize()
    curl.setopt(CURLOPT_PROXY, purl)
  case request.httpmethod
  of HTTP_GET:
    curl.setopt(CURLOPT_HTTPGET, 1)
  of HTTP_POST:
    curl.setopt(CURLOPT_POST, 1)
    curl.applyPostBody(request, handleData)
  else: discard #TODO
  for k, v in request.headers:
    let header = k & ": " & v
    handleData.slist = curl_slist_append(handleData.slist, cstring(header))
  if handleData.slist != nil:
    curl.setopt(CURLOPT_HTTPHEADER, handleData.slist)
  let res = curl_multi_add_handle(curlm, curl)
  if res != CURLM_OK:
    ostream.swrite(int(res))
    ostream.flush()
    #TODO: raise here?
    return
  return handleData