summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------build0
-rw-r--r--compatibility/stdbool.h11
-rw-r--r--compatibility/stdint.h247
-rw-r--r--compatibility/unistd.h42
-rw-r--r--json-c/src/Android.configure.mk39
-rw-r--r--json-c/src/README.md63
-rw-r--r--json-c/src/configure.ac114
-rw-r--r--json-c/src/json-c-uninstalled.pc.in11
-rw-r--r--json-c/src/json-c.pc.in12
-rw-r--r--json-c/src/json-c.vcproj185
-rw-r--r--json-c/src/json-c.vcxproj165
-rw-r--r--json-c/src/json-c.vcxproj.filters90
-rw-r--r--json-c/src/json_c_version.c20
-rw-r--r--json-c/src/json_c_version.h22
-rw-r--r--json-c/src/json_config.h.win325
-rw-r--r--json-c/src/libjson.c26
-rw-r--r--json-c/src/math_compat.h31
-rw-r--r--json-c/src/random_seed.c238
-rw-r--r--json-c/src/random_seed.h25
-rw-r--r--json-c/src/tests/Makefile.am41
-rw-r--r--json-c/src/tests/parse_flags.c50
-rw-r--r--json-c/src/tests/parse_flags.h4
-rw-r--r--json-c/src/tests/test-defs.sh128
-rw-r--r--json-c/src/tests/test1.c134
-rw-r--r--json-c/src/tests/test1.expected36
-rw-r--r--json-c/src/tests/test1.test22
-rw-r--r--json-c/src/tests/test1Formatted_plain.expected36
-rw-r--r--json-c/src/tests/test1Formatted_pretty.expected59
-rw-r--r--json-c/src/tests/test1Formatted_spaced.expected36
-rw-r--r--json-c/src/tests/test2.c34
-rw-r--r--json-c/src/tests/test2.expected1
-rw-r--r--json-c/src/tests/test2.test22
-rw-r--r--json-c/src/tests/test2Formatted_plain.expected1
-rw-r--r--json-c/src/tests/test2Formatted_pretty.expected23
-rw-r--r--json-c/src/tests/test2Formatted_spaced.expected1
-rw-r--r--json-c/src/tests/test4.c53
-rw-r--r--json-c/src/tests/test4.expected3
-rw-r--r--json-c/src/tests/test4.test12
-rw-r--r--json-c/src/tests/testReplaceExisting.c78
-rw-r--r--json-c/src/tests/testReplaceExisting.expected15
-rw-r--r--json-c/src/tests/testReplaceExisting.test12
-rw-r--r--json-c/src/tests/test_cast.c111
-rw-r--r--json-c/src/tests/test_cast.expected56
-rw-r--r--json-c/src/tests/test_cast.test12
-rw-r--r--json-c/src/tests/test_charcase.c40
-rw-r--r--json-c/src/tests/test_charcase.expected1
-rw-r--r--json-c/src/tests/test_charcase.test12
-rw-r--r--json-c/src/tests/test_locale.c31
-rw-r--r--json-c/src/tests/test_locale.expected2
-rw-r--r--json-c/src/tests/test_locale.test12
-rw-r--r--json-c/src/tests/test_null.c57
-rw-r--r--json-c/src/tests/test_null.expected3
-rw-r--r--json-c/src/tests/test_null.test12
-rw-r--r--json-c/src/tests/test_parse.c342
-rw-r--r--json-c/src/tests/test_parse.expected70
-rw-r--r--json-c/src/tests/test_parse.test12
-rw-r--r--json-c/src/tests/test_parse_int64.c115
-rw-r--r--json-c/src/tests/test_parse_int64.expected29
-rw-r--r--json-c/src/tests/test_parse_int64.test12
-rw-r--r--json-c/src/tests/test_printbuf.c166
-rw-r--r--json-c/src/tests/test_printbuf.expected32
-rw-r--r--json-c/src/tests/test_printbuf.test12
-rw-r--r--json-c/src/tests/test_set_serializer.c71
-rw-r--r--json-c/src/tests/test_set_serializer.expected10
-rw-r--r--json-c/src/tests/test_set_serializer.test12
-rw-r--r--libcurl/libcurl.vcxproj (renamed from libmad/libmad.vcxproj)82
-rw-r--r--libcurl/libcurl.vcxproj.filters49
-rw-r--r--libcurl/src/include/curl/curl.h2364
-rw-r--r--libcurl/src/include/curl/curlbuild.h599
-rw-r--r--libcurl/src/include/curl/curlbuild.h.cmake197
-rw-r--r--libcurl/src/include/curl/curlbuild.h.in197
-rw-r--r--libcurl/src/include/curl/curlrules.h262
-rw-r--r--libcurl/src/include/curl/curlver.h69
-rw-r--r--libcurl/src/include/curl/easy.h102
-rw-r--r--libcurl/src/include/curl/mprintf.h74
-rw-r--r--libcurl/src/include/curl/multi.h400
-rw-r--r--libcurl/src/include/curl/stdcheaders.h33
-rw-r--r--libcurl/src/include/curl/typecheck-gcc.h610
-rw-r--r--libcurl/src/lib/amigaos.c77
-rw-r--r--libcurl/src/lib/amigaos.h39
-rw-r--r--libcurl/src/lib/arpa_telnet.h104
-rw-r--r--libcurl/src/lib/asyn-ares.c691
-rw-r--r--libcurl/src/lib/asyn-thread.c698
-rw-r--r--libcurl/src/lib/asyn.h168
-rw-r--r--libcurl/src/lib/base64.c309
-rw-r--r--libcurl/src/lib/bundles.c110
-rw-r--r--libcurl/src/lib/bundles.h45
-rw-r--r--libcurl/src/lib/config-amigaos.h166
-rw-r--r--libcurl/src/lib/config-android-arm.h1019
-rw-r--r--libcurl/src/lib/config-android-x86.h1019
-rw-r--r--libcurl/src/lib/config-dos.h181
-rw-r--r--libcurl/src/lib/config-emscripten.h1032
-rw-r--r--libcurl/src/lib/config-ios-sim.h1019
-rw-r--r--libcurl/src/lib/config-ios.h1019
-rw-r--r--libcurl/src/lib/config-mac.h125
-rw-r--r--libcurl/src/lib/config-os400.h563
-rw-r--r--libcurl/src/lib/config-osx.h1019
-rw-r--r--libcurl/src/lib/config-riscos.h513
-rw-r--r--libcurl/src/lib/config-symbian.h811
-rw-r--r--libcurl/src/lib/config-tpf.h772
-rw-r--r--libcurl/src/lib/config-vxworks.h928
-rw-r--r--libcurl/src/lib/config-win32.h734
-rw-r--r--libcurl/src/lib/config-win32ce.h448
-rw-r--r--libcurl/src/lib/config-winrt.h468
-rw-r--r--libcurl/src/lib/conncache.c289
-rw-r--r--libcurl/src/lib/conncache.h57
-rw-r--r--libcurl/src/lib/connect.c1377
-rw-r--r--libcurl/src/lib/connect.h122
-rw-r--r--libcurl/src/lib/content_encoding.c435
-rw-r--r--libcurl/src/lib/content_encoding.h48
-rw-r--r--libcurl/src/lib/cookie.c1365
-rw-r--r--libcurl/src/lib/cookie.h104
-rw-r--r--libcurl/src/lib/curl_addrinfo.c558
-rw-r--r--libcurl/src/lib/curl_addrinfo.h101
-rw-r--r--libcurl/src/lib/curl_base64.h35
-rw-r--r--libcurl/src/lib/curl_config.h.cmake952
-rw-r--r--libcurl/src/lib/curl_config.h.in1024
-rw-r--r--libcurl/src/lib/curl_des.c63
-rw-r--r--libcurl/src/lib/curl_des.h34
-rw-r--r--libcurl/src/lib/curl_endian.c236
-rw-r--r--libcurl/src/lib/curl_endian.h70
-rw-r--r--libcurl/src/lib/curl_fnmatch.c424
-rw-r--r--libcurl/src/lib/curl_fnmatch.h44
-rw-r--r--libcurl/src/lib/curl_gethostname.c100
-rw-r--r--libcurl/src/lib/curl_gethostname.h31
-rw-r--r--libcurl/src/lib/curl_gssapi.c120
-rw-r--r--libcurl/src/lib/curl_gssapi.h75
-rw-r--r--libcurl/src/lib/curl_hmac.h67
-rw-r--r--libcurl/src/lib/curl_ldap.h35
-rw-r--r--libcurl/src/lib/curl_md4.h35
-rw-r--r--libcurl/src/lib/curl_md5.h63
-rw-r--r--libcurl/src/lib/curl_memory.h180
-rw-r--r--libcurl/src/lib/curl_memrchr.c58
-rw-r--r--libcurl/src/lib/curl_memrchr.h44
-rw-r--r--libcurl/src/lib/curl_multibyte.c82
-rw-r--r--libcurl/src/lib/curl_multibyte.h92
-rw-r--r--libcurl/src/lib/curl_ntlm.c232
-rw-r--r--libcurl/src/lib/curl_ntlm.h40
-rw-r--r--libcurl/src/lib/curl_ntlm_core.c765
-rw-r--r--libcurl/src/lib/curl_ntlm_core.h106
-rw-r--r--libcurl/src/lib/curl_ntlm_msgs.c819
-rw-r--r--libcurl/src/lib/curl_ntlm_msgs.h143
-rw-r--r--libcurl/src/lib/curl_ntlm_wb.c431
-rw-r--r--libcurl/src/lib/curl_ntlm_wb.h38
-rw-r--r--libcurl/src/lib/curl_printf.h56
-rw-r--r--libcurl/src/lib/curl_rtmp.c306
-rw-r--r--libcurl/src/lib/curl_rtmp.h33
-rw-r--r--libcurl/src/lib/curl_sasl.c1667
-rw-r--r--libcurl/src/lib/curl_sasl.h245
-rw-r--r--libcurl/src/lib/curl_sasl_gssapi.c392
-rw-r--r--libcurl/src/lib/curl_sasl_sspi.c1207
-rw-r--r--libcurl/src/lib/curl_sec.h51
-rw-r--r--libcurl/src/lib/curl_setup.h713
-rw-r--r--libcurl/src/lib/curl_setup_once.h551
-rw-r--r--libcurl/src/lib/curl_sspi.c252
-rw-r--r--libcurl/src/lib/curl_sspi.h342
-rw-r--r--libcurl/src/lib/curl_threads.c136
-rw-r--r--libcurl/src/lib/curl_threads.h62
-rw-r--r--libcurl/src/lib/curlx.h118
-rw-r--r--libcurl/src/lib/dict.c279
-rw-r--r--libcurl/src/lib/dict.h29
-rw-r--r--libcurl/src/lib/dotdot.c170
-rw-r--r--libcurl/src/lib/dotdot.h25
-rw-r--r--libcurl/src/lib/easy.c1130
-rw-r--r--libcurl/src/lib/easyif.h33
-rw-r--r--libcurl/src/lib/escape.c231
-rw-r--r--libcurl/src/lib/escape.h33
-rw-r--r--libcurl/src/lib/file.c588
-rw-r--r--libcurl/src/lib/file.h41
-rw-r--r--libcurl/src/lib/fileinfo.c50
-rw-r--r--libcurl/src/lib/fileinfo.h33
-rw-r--r--libcurl/src/lib/formdata.c1551
-rw-r--r--libcurl/src/lib/formdata.h98
-rw-r--r--libcurl/src/lib/ftp.c4586
-rw-r--r--libcurl/src/lib/ftp.h159
-rw-r--r--libcurl/src/lib/ftplistparser.c1048
-rw-r--r--libcurl/src/lib/ftplistparser.h41
-rw-r--r--libcurl/src/lib/getenv.c53
-rw-r--r--libcurl/src/lib/getinfo.c382
-rw-r--r--libcurl/src/lib/getinfo.h27
-rw-r--r--libcurl/src/lib/gopher.c165
-rw-r--r--libcurl/src/lib/gopher.h29
-rw-r--r--libcurl/src/lib/hash.c396
-rw-r--r--libcurl/src/lib/hash.h106
-rw-r--r--libcurl/src/lib/hmac.c129
-rw-r--r--libcurl/src/lib/hostasyn.c153
-rw-r--r--libcurl/src/lib/hostcheck.c147
-rw-r--r--libcurl/src/lib/hostcheck.h32
-rw-r--r--libcurl/src/lib/hostip.c879
-rw-r--r--libcurl/src/lib/hostip.h250
-rw-r--r--libcurl/src/lib/hostip4.c307
-rw-r--r--libcurl/src/lib/hostip6.c221
-rw-r--r--libcurl/src/lib/hostsyn.c107
-rw-r--r--libcurl/src/lib/http.c3717
-rw-r--r--libcurl/src/lib/http.h224
-rw-r--r--libcurl/src/lib/http2.c1077
-rw-r--r--libcurl/src/lib/http2.h51
-rw-r--r--libcurl/src/lib/http_chunks.c382
-rw-r--r--libcurl/src/lib/http_chunks.h91
-rw-r--r--libcurl/src/lib/http_digest.c179
-rw-r--r--libcurl/src/lib/http_digest.h42
-rw-r--r--libcurl/src/lib/http_negotiate.c208
-rw-r--r--libcurl/src/lib/http_negotiate.h42
-rw-r--r--libcurl/src/lib/http_negotiate_sspi.c298
-rw-r--r--libcurl/src/lib/http_proxy.c590
-rw-r--r--libcurl/src/lib/http_proxy.h41
-rw-r--r--libcurl/src/lib/idn_win32.c108
-rw-r--r--libcurl/src/lib/if2ip.c271
-rw-r--r--libcurl/src/lib/if2ip.h83
-rw-r--r--libcurl/src/lib/imap.c2142
-rw-r--r--libcurl/src/lib/imap.h96
-rw-r--r--libcurl/src/lib/inet_ntop.c198
-rw-r--r--libcurl/src/lib/inet_ntop.h38
-rw-r--r--libcurl/src/lib/inet_pton.c234
-rw-r--r--libcurl/src/lib/inet_pton.h37
-rw-r--r--libcurl/src/lib/krb5.c332
-rw-r--r--libcurl/src/lib/ldap.c1013
-rw-r--r--libcurl/src/lib/libcurl.rc63
-rw-r--r--libcurl/src/lib/llist.c212
-rw-r--r--libcurl/src/lib/llist.h57
-rw-r--r--libcurl/src/lib/md4.c304
-rw-r--r--libcurl/src/lib/md5.c560
-rw-r--r--libcurl/src/lib/memdebug.c489
-rw-r--r--libcurl/src/lib/memdebug.h176
-rw-r--r--libcurl/src/lib/mprintf.c1142
-rw-r--r--libcurl/src/lib/multi.c2815
-rw-r--r--libcurl/src/lib/multihandle.h143
-rw-r--r--libcurl/src/lib/multiif.h93
-rw-r--r--libcurl/src/lib/netrc.c199
-rw-r--r--libcurl/src/lib/netrc.h36
-rw-r--r--libcurl/src/lib/non-ascii.c338
-rw-r--r--libcurl/src/lib/non-ascii.h63
-rw-r--r--libcurl/src/lib/nonblock.c91
-rw-r--r--libcurl/src/lib/nonblock.h31
-rw-r--r--libcurl/src/lib/nwlib.c325
-rw-r--r--libcurl/src/lib/nwos.c88
-rw-r--r--libcurl/src/lib/openldap.c684
-rw-r--r--libcurl/src/lib/parsedate.c583
-rw-r--r--libcurl/src/lib/parsedate.h31
-rw-r--r--libcurl/src/lib/pingpong.c507
-rw-r--r--libcurl/src/lib/pingpong.h150
-rw-r--r--libcurl/src/lib/pipeline.c338
-rw-r--r--libcurl/src/lib/pipeline.h44
-rw-r--r--libcurl/src/lib/pop3.c1601
-rw-r--r--libcurl/src/lib/pop3.h95
-rw-r--r--libcurl/src/lib/progress.c492
-rw-r--r--libcurl/src/lib/progress.h73
-rw-r--r--libcurl/src/lib/rawstr.c142
-rw-r--r--libcurl/src/lib/rawstr.h47
-rw-r--r--libcurl/src/lib/rtsp.c807
-rw-r--r--libcurl/src/lib/rtsp.h69
-rw-r--r--libcurl/src/lib/security.c597
-rw-r--r--libcurl/src/lib/select.c578
-rw-r--r--libcurl/src/lib/select.h114
-rw-r--r--libcurl/src/lib/sendf.c710
-rw-r--r--libcurl/src/lib/sendf.h93
-rw-r--r--libcurl/src/lib/setup-os400.h223
-rw-r--r--libcurl/src/lib/setup-vms.h430
-rw-r--r--libcurl/src/lib/share.c253
-rw-r--r--libcurl/src/lib/share.h61
-rw-r--r--libcurl/src/lib/sigpipe.h78
-rw-r--r--libcurl/src/lib/slist.c143
-rw-r--r--libcurl/src/lib/slist.h40
-rw-r--r--libcurl/src/lib/smb.c970
-rw-r--r--libcurl/src/lib/smb.h271
-rw-r--r--libcurl/src/lib/smtp.c1671
-rw-r--r--libcurl/src/lib/smtp.h91
-rw-r--r--libcurl/src/lib/sockaddr.h43
-rw-r--r--libcurl/src/lib/socks.c755
-rw-r--r--libcurl/src/lib/socks.h77
-rw-r--r--libcurl/src/lib/socks_gssapi.c522
-rw-r--r--libcurl/src/lib/socks_sspi.c601
-rw-r--r--libcurl/src/lib/speedcheck.c74
-rw-r--r--libcurl/src/lib/speedcheck.h33
-rw-r--r--libcurl/src/lib/splay.c288
-rw-r--r--libcurl/src/lib/splay.h66
-rw-r--r--libcurl/src/lib/ssh.c3341
-rw-r--r--libcurl/src/lib/ssh.h195
-rw-r--r--libcurl/src/lib/strdup.c73
-rw-r--r--libcurl/src/lib/strdup.h31
-rw-r--r--libcurl/src/lib/strequal.c79
-rw-r--r--libcurl/src/lib/strequal.h31
-rw-r--r--libcurl/src/lib/strerror.c1139
-rw-r--r--libcurl/src/lib/strerror.h37
-rw-r--r--libcurl/src/lib/strtok.c66
-rw-r--r--libcurl/src/lib/strtok.h34
-rw-r--r--libcurl/src/lib/strtoofft.c188
-rw-r--r--libcurl/src/lib/strtoofft.h75
-rw-r--r--libcurl/src/lib/telnet.c1674
-rw-r--r--libcurl/src/lib/telnet.h29
-rw-r--r--libcurl/src/lib/tftp.c1376
-rw-r--r--libcurl/src/lib/tftp.h29
-rw-r--r--libcurl/src/lib/timeval.c142
-rw-r--r--libcurl/src/lib/timeval.h58
-rw-r--r--libcurl/src/lib/transfer.c2004
-rw-r--r--libcurl/src/lib/transfer.h70
-rw-r--r--libcurl/src/lib/url.c6164
-rw-r--r--libcurl/src/lib/url.h82
-rw-r--r--libcurl/src/lib/urldata.h1695
-rw-r--r--libcurl/src/lib/version.c362
-rw-r--r--libcurl/src/lib/vtls/axtls.c696
-rw-r--r--libcurl/src/lib/vtls/axtls.h71
-rw-r--r--libcurl/src/lib/vtls/cyassl.c734
-rw-r--r--libcurl/src/lib/vtls/cyassl.h70
-rw-r--r--libcurl/src/lib/vtls/darwinssl.c2484
-rw-r--r--libcurl/src/lib/vtls/darwinssl.h76
-rw-r--r--libcurl/src/lib/vtls/gskit.c1069
-rw-r--r--libcurl/src/lib/vtls/gskit.h71
-rw-r--r--libcurl/src/lib/vtls/gtls.c1480
-rw-r--r--libcurl/src/lib/vtls/gtls.h83
-rw-r--r--libcurl/src/lib/vtls/nss.c2006
-rw-r--r--libcurl/src/lib/vtls/nssg.h96
-rw-r--r--libcurl/src/lib/vtls/openssl.c3226
-rw-r--r--libcurl/src/lib/vtls/openssl.h113
-rw-r--r--libcurl/src/lib/vtls/polarssl.c753
-rw-r--r--libcurl/src/lib/vtls/polarssl.h75
-rw-r--r--libcurl/src/lib/vtls/polarssl_threadlock.c153
-rw-r--r--libcurl/src/lib/vtls/polarssl_threadlock.h53
-rw-r--r--libcurl/src/lib/vtls/schannel.c1364
-rw-r--r--libcurl/src/lib/vtls/schannel.h117
-rw-r--r--libcurl/src/lib/vtls/vtls.c895
-rw-r--r--libcurl/src/lib/vtls/vtls.h153
-rw-r--r--libcurl/src/lib/warnless.c486
-rw-r--r--libcurl/src/lib/warnless.h107
-rw-r--r--libcurl/src/lib/wildcard.c69
-rw-r--r--libcurl/src/lib/wildcard.h58
-rw-r--r--libcurl/src/lib/x509asn1.c1187
-rw-r--r--libcurl/src/lib/x509asn1.h131
-rw-r--r--libcurl/src/libcurl_unified.c172
-rw-r--r--libmad/configured/config.h130
-rw-r--r--libmad/configured/mad.h948
-rw-r--r--libmad/libmad.vcxproj.filters105
-rw-r--r--libmad/src/CHANGES338
-rw-r--r--libmad/src/COPYING340
-rw-r--r--libmad/src/COPYRIGHT21
-rw-r--r--libmad/src/CREDITS116
-rw-r--r--libmad/src/D.dat607
-rw-r--r--libmad/src/README241
-rw-r--r--libmad/src/bit.c237
-rw-r--r--libmad/src/bit.h47
-rw-r--r--libmad/src/decoder.c582
-rw-r--r--libmad/src/decoder.h91
-rw-r--r--libmad/src/fixed.c90
-rw-r--r--libmad/src/fixed.h499
-rw-r--r--libmad/src/frame.c512
-rw-r--r--libmad/src/frame.h118
-rw-r--r--libmad/src/global.h58
-rw-r--r--libmad/src/huffman.c3109
-rw-r--r--libmad/src/huffman.h66
-rw-r--r--libmad/src/imdct_s.dat62
-rw-r--r--libmad/src/layer12.c543
-rw-r--r--libmad/src/layer12.h31
-rw-r--r--libmad/src/layer3.c2707
-rw-r--r--libmad/src/layer3.h30
-rw-r--r--libmad/src/qc_table.dat77
-rw-r--r--libmad/src/rq_table.dat8747
-rw-r--r--libmad/src/sf_table.dat106
-rw-r--r--libmad/src/stream.c161
-rw-r--r--libmad/src/stream.h108
-rw-r--r--libmad/src/synth.c866
-rw-r--r--libmad/src/synth.h69
-rw-r--r--libmad/src/timer.c485
-rw-r--r--libmad/src/timer.h100
-rw-r--r--libmad/src/version.c91
-rw-r--r--libmad/src/version.h47
-rw-r--r--pianobar/resources/pianobar.icobin0 -> 90566 bytes
-rw-r--r--pianobar/resources/pianobar.rc36
-rw-r--r--polarssl/polarssl.vcxproj271
-rw-r--r--polarssl/polarssl.vcxproj.filters258
-rw-r--r--polarssl/src/LICENSE339
-rw-r--r--polarssl/src/include/polarssl/aes.h176
-rw-r--r--polarssl/src/include/polarssl/arc4.h80
-rw-r--r--polarssl/src/include/polarssl/asn1.h246
-rw-r--r--polarssl/src/include/polarssl/asn1write.h46
-rw-r--r--polarssl/src/include/polarssl/base64.h87
-rw-r--r--polarssl/src/include/polarssl/bignum.h632
-rw-r--r--polarssl/src/include/polarssl/bn_mul.h742
-rw-r--r--polarssl/src/include/polarssl/camellia.h182
-rw-r--r--polarssl/src/include/polarssl/certs.h47
-rw-r--r--polarssl/src/include/polarssl/cipher.h459
-rw-r--r--polarssl/src/include/polarssl/cipher_wrap.h95
-rw-r--r--polarssl/src/include/polarssl/config.h744
-rw-r--r--polarssl/src/include/polarssl/ctr_drbg.h228
-rw-r--r--polarssl/src/include/polarssl/debug.h89
-rw-r--r--polarssl/src/include/polarssl/des.h227
-rw-r--r--polarssl/src/include/polarssl/dhm.h153
-rw-r--r--polarssl/src/include/polarssl/entropy.h150
-rw-r--r--polarssl/src/include/polarssl/entropy_poll.h75
-rw-r--r--polarssl/src/include/polarssl/error.h102
-rw-r--r--polarssl/src/include/polarssl/gcm.h142
-rw-r--r--polarssl/src/include/polarssl/havege.h71
-rw-r--r--polarssl/src/include/polarssl/md.h354
-rw-r--r--polarssl/src/include/polarssl/md2.h153
-rw-r--r--polarssl/src/include/polarssl/md4.h152
-rw-r--r--polarssl/src/include/polarssl/md5.h154
-rw-r--r--polarssl/src/include/polarssl/md_wrap.h64
-rw-r--r--polarssl/src/include/polarssl/net.h159
-rw-r--r--polarssl/src/include/polarssl/openssl.h136
-rw-r--r--polarssl/src/include/polarssl/padlock.h100
-rw-r--r--polarssl/src/include/polarssl/pem.h100
-rw-r--r--polarssl/src/include/polarssl/pkcs11.h126
-rw-r--r--polarssl/src/include/polarssl/rsa.h379
-rw-r--r--polarssl/src/include/polarssl/sha1.h152
-rw-r--r--polarssl/src/include/polarssl/sha2.h160
-rw-r--r--polarssl/src/include/polarssl/sha4.h168
-rw-r--r--polarssl/src/include/polarssl/ssl.h766
-rw-r--r--polarssl/src/include/polarssl/timing.h75
-rw-r--r--polarssl/src/include/polarssl/version.h81
-rw-r--r--polarssl/src/include/polarssl/x509.h733
-rw-r--r--polarssl/src/include/polarssl/x509write.h46
-rw-r--r--polarssl/src/include/polarssl/xtea.h111
-rw-r--r--polarssl/src/library/aes.c1346
-rw-r--r--polarssl/src/library/arc4.c169
-rw-r--r--polarssl/src/library/asn1parse.c260
-rw-r--r--polarssl/src/library/asn1write.c241
-rw-r--r--polarssl/src/library/base64.c254
-rw-r--r--polarssl/src/library/bignum.c2111
-rw-r--r--polarssl/src/library/camellia.c1032
-rw-r--r--polarssl/src/library/certs.c196
-rw-r--r--polarssl/src/library/cipher.c557
-rw-r--r--polarssl/src/library/cipher_wrap.c595
-rw-r--r--polarssl/src/library/ctr_drbg.c562
-rw-r--r--polarssl/src/library/debug.c238
-rw-r--r--polarssl/src/library/des.c993
-rw-r--r--polarssl/src/library/dhm.c296
-rw-r--r--polarssl/src/library/entropy.c204
-rw-r--r--polarssl/src/library/entropy_poll.c136
-rw-r--r--polarssl/src/library/error.c525
-rw-r--r--polarssl/src/library/gcm.c653
-rw-r--r--polarssl/src/library/havege.c231
-rw-r--r--polarssl/src/library/md.c297
-rw-r--r--polarssl/src/library/md2.c364
-rw-r--r--polarssl/src/library/md4.c460
-rw-r--r--polarssl/src/library/md5.c583
-rw-r--r--polarssl/src/library/md_wrap.c733
-rw-r--r--polarssl/src/library/net.c358
-rw-r--r--polarssl/src/library/padlock.c162
-rw-r--r--polarssl/src/library/pem.c352
-rw-r--r--polarssl/src/library/pkcs11.c238
-rw-r--r--polarssl/src/library/rsa.c1219
-rw-r--r--polarssl/src/library/sha1.c624
-rw-r--r--polarssl/src/library/sha2.c705
-rw-r--r--polarssl/src/library/sha4.c760
-rw-r--r--polarssl/src/library/ssl_cli.c1130
-rw-r--r--polarssl/src/library/ssl_srv.c1080
-rw-r--r--polarssl/src/library/ssl_tls.c3166
-rw-r--r--polarssl/src/library/timing.c271
-rw-r--r--polarssl/src/library/version.c50
-rw-r--r--polarssl/src/library/x509parse.c3425
-rw-r--r--polarssl/src/library/x509write.c287
-rw-r--r--polarssl/src/library/xtea.c248
-rw-r--r--pthreads/pthread-win32.vcxproj.filters33
-rw-r--r--pthreads/src/COPYING.LIB504
-rw-r--r--pthreads/src/README601
-rw-r--r--pthreads/src/attr.c53
-rw-r--r--pthreads/src/autostatic.c69
-rw-r--r--pthreads/src/barrier.c47
-rw-r--r--pthreads/src/cancel.c44
-rw-r--r--pthreads/src/cleanup.c148
-rw-r--r--pthreads/src/condvar.c50
-rw-r--r--pthreads/src/config.h153
-rw-r--r--pthreads/src/context.h74
-rw-r--r--pthreads/src/create.c308
-rw-r--r--pthreads/src/dll.c92
-rw-r--r--pthreads/src/errno.c94
-rw-r--r--pthreads/src/exit.c44
-rw-r--r--pthreads/src/fork.c39
-rw-r--r--pthreads/src/global.c107
-rw-r--r--pthreads/src/implement.h943
-rw-r--r--pthreads/src/misc.c51
-rw-r--r--pthreads/src/mutex.c62
-rw-r--r--pthreads/src/need_errno.h145
-rw-r--r--pthreads/src/nonportable.c47
-rw-r--r--pthreads/src/private.c52
-rw-r--r--pthreads/src/pthread.c66
-rw-r--r--pthreads/src/pthread.h1368
-rw-r--r--pthreads/src/pthread_attr_destroy.c79
-rw-r--r--pthreads/src/pthread_attr_getdetachstate.c86
-rw-r--r--pthreads/src/pthread_attr_getinheritsched.c51
-rw-r--r--pthreads/src/pthread_attr_getschedparam.c52
-rw-r--r--pthreads/src/pthread_attr_getschedpolicy.c61
-rw-r--r--pthreads/src/pthread_attr_getscope.c54
-rw-r--r--pthreads/src/pthread_attr_getstackaddr.c97
-rw-r--r--pthreads/src/pthread_attr_getstacksize.c100
-rw-r--r--pthreads/src/pthread_attr_init.c117
-rw-r--r--pthreads/src/pthread_attr_setdetachstate.c91
-rw-r--r--pthreads/src/pthread_attr_setinheritsched.c57
-rw-r--r--pthreads/src/pthread_attr_setschedparam.c63
-rw-r--r--pthreads/src/pthread_attr_setschedpolicy.c55
-rw-r--r--pthreads/src/pthread_attr_setscope.c62
-rw-r--r--pthreads/src/pthread_attr_setstackaddr.c97
-rw-r--r--pthreads/src/pthread_attr_setstacksize.c110
-rw-r--r--pthreads/src/pthread_barrier_destroy.c103
-rw-r--r--pthreads/src/pthread_barrier_init.c69
-rw-r--r--pthreads/src/pthread_barrier_wait.c104
-rw-r--r--pthreads/src/pthread_barrierattr_destroy.c83
-rw-r--r--pthreads/src/pthread_barrierattr_getpshared.c95
-rw-r--r--pthreads/src/pthread_barrierattr_init.c85
-rw-r--r--pthreads/src/pthread_barrierattr_setpshared.c119
-rw-r--r--pthreads/src/pthread_cancel.c189
-rw-r--r--pthreads/src/pthread_cond_destroy.c253
-rw-r--r--pthreads/src/pthread_cond_init.c167
-rw-r--r--pthreads/src/pthread_cond_signal.c231
-rw-r--r--pthreads/src/pthread_cond_wait.c567
-rw-r--r--pthreads/src/pthread_condattr_destroy.c86
-rw-r--r--pthreads/src/pthread_condattr_getpshared.c97
-rw-r--r--pthreads/src/pthread_condattr_init.c87
-rw-r--r--pthreads/src/pthread_condattr_setpshared.c117
-rw-r--r--pthreads/src/pthread_delay_np.c172
-rw-r--r--pthreads/src/pthread_detach.c136
-rw-r--r--pthreads/src/pthread_equal.c76
-rw-r--r--pthreads/src/pthread_exit.c106
-rw-r--r--pthreads/src/pthread_getconcurrency.c45
-rw-r--r--pthreads/src/pthread_getschedparam.c75
-rw-r--r--pthreads/src/pthread_getspecific.c87
-rw-r--r--pthreads/src/pthread_getunique_np.c47
-rw-r--r--pthreads/src/pthread_getw32threadhandle_np.c65
-rw-r--r--pthreads/src/pthread_join.c157
-rw-r--r--pthreads/src/pthread_key_create.c108
-rw-r--r--pthreads/src/pthread_key_delete.c125
-rw-r--r--pthreads/src/pthread_kill.c105
-rw-r--r--pthreads/src/pthread_mutex_consistent.c190
-rw-r--r--pthreads/src/pthread_mutex_destroy.c148
-rw-r--r--pthreads/src/pthread_mutex_init.c130
-rw-r--r--pthreads/src/pthread_mutex_lock.c269
-rw-r--r--pthreads/src/pthread_mutex_timedlock.c324
-rw-r--r--pthreads/src/pthread_mutex_trylock.c154
-rw-r--r--pthreads/src/pthread_mutex_unlock.c175
-rw-r--r--pthreads/src/pthread_mutexattr_destroy.c83
-rw-r--r--pthreads/src/pthread_mutexattr_getkind_np.c44
-rw-r--r--pthreads/src/pthread_mutexattr_getpshared.c95
-rw-r--r--pthreads/src/pthread_mutexattr_getrobust.c113
-rw-r--r--pthreads/src/pthread_mutexattr_gettype.c56
-rw-r--r--pthreads/src/pthread_mutexattr_init.c86
-rw-r--r--pthreads/src/pthread_mutexattr_setkind_np.c44
-rw-r--r--pthreads/src/pthread_mutexattr_setpshared.c119
-rw-r--r--pthreads/src/pthread_mutexattr_setrobust.c119
-rw-r--r--pthreads/src/pthread_mutexattr_settype.c143
-rw-r--r--pthreads/src/pthread_num_processors_np.c56
-rw-r--r--pthreads/src/pthread_once.c79
-rw-r--r--pthreads/src/pthread_rwlock_destroy.c143
-rw-r--r--pthreads/src/pthread_rwlock_init.c109
-rw-r--r--pthreads/src/pthread_rwlock_rdlock.c102
-rw-r--r--pthreads/src/pthread_rwlock_timedrdlock.c109
-rw-r--r--pthreads/src/pthread_rwlock_timedwrlock.c139
-rw-r--r--pthreads/src/pthread_rwlock_tryrdlock.c102
-rw-r--r--pthreads/src/pthread_rwlock_trywrlock.c122
-rw-r--r--pthreads/src/pthread_rwlock_unlock.c93
-rw-r--r--pthreads/src/pthread_rwlock_wrlock.c133
-rw-r--r--pthreads/src/pthread_rwlockattr_destroy.c84
-rw-r--r--pthreads/src/pthread_rwlockattr_getpshared.c97
-rw-r--r--pthreads/src/pthread_rwlockattr_init.c83
-rw-r--r--pthreads/src/pthread_rwlockattr_setpshared.c120
-rw-r--r--pthreads/src/pthread_self.c141
-rw-r--r--pthreads/src/pthread_setcancelstate.c125
-rw-r--r--pthreads/src/pthread_setcanceltype.c126
-rw-r--r--pthreads/src/pthread_setconcurrency.c53
-rw-r--r--pthreads/src/pthread_setschedparam.c123
-rw-r--r--pthreads/src/pthread_setspecific.c167
-rw-r--r--pthreads/src/pthread_spin_destroy.c111
-rw-r--r--pthreads/src/pthread_spin_init.c123
-rw-r--r--pthreads/src/pthread_spin_lock.c80
-rw-r--r--pthreads/src/pthread_spin_trylock.c77
-rw-r--r--pthreads/src/pthread_spin_unlock.c71
-rw-r--r--pthreads/src/pthread_testcancel.c103
-rw-r--r--pthreads/src/pthread_timechange_handler_np.c108
-rw-r--r--pthreads/src/pthread_win32_attach_detach_np.c256
-rw-r--r--pthreads/src/ptw32_MCS_lock.c278
-rw-r--r--pthreads/src/ptw32_callUserDestroyRoutines.c232
-rw-r--r--pthreads/src/ptw32_calloc.c56
-rw-r--r--pthreads/src/ptw32_cond_check_need_init.c78
-rw-r--r--pthreads/src/ptw32_getprocessors.c91
-rw-r--r--pthreads/src/ptw32_is_attr.c47
-rw-r--r--pthreads/src/ptw32_mutex_check_need_init.c92
-rw-r--r--pthreads/src/ptw32_new.c94
-rw-r--r--pthreads/src/ptw32_processInitialize.c92
-rw-r--r--pthreads/src/ptw32_processTerminate.c105
-rw-r--r--pthreads/src/ptw32_relmillisecs.c132
-rw-r--r--pthreads/src/ptw32_reuse.c151
-rw-r--r--pthreads/src/ptw32_rwlock_cancelwrwait.c50
-rw-r--r--pthreads/src/ptw32_rwlock_check_need_init.c77
-rw-r--r--pthreads/src/ptw32_semwait.c135
-rw-r--r--pthreads/src/ptw32_spinlock_check_need_init.c78
-rw-r--r--pthreads/src/ptw32_threadDestroy.c79
-rw-r--r--pthreads/src/ptw32_threadStart.c357
-rw-r--r--pthreads/src/ptw32_throw.c189
-rw-r--r--pthreads/src/ptw32_timespec.c83
-rw-r--r--pthreads/src/ptw32_tkAssocCreate.c118
-rw-r--r--pthreads/src/ptw32_tkAssocDestroy.c114
-rw-r--r--pthreads/src/rwlock.c51
-rw-r--r--pthreads/src/sched.c53
-rw-r--r--pthreads/src/sched.h183
-rw-r--r--pthreads/src/sched_get_priority_max.c134
-rw-r--r--pthreads/src/sched_get_priority_min.c135
-rw-r--r--pthreads/src/sched_getscheduler.c71
-rw-r--r--pthreads/src/sched_setscheduler.c83
-rw-r--r--pthreads/src/sched_yield.c71
-rw-r--r--pthreads/src/sem_close.c58
-rw-r--r--pthreads/src/sem_destroy.c144
-rw-r--r--pthreads/src/sem_getvalue.c110
-rw-r--r--pthreads/src/sem_init.c169
-rw-r--r--pthreads/src/sem_open.c58
-rw-r--r--pthreads/src/sem_post.c128
-rw-r--r--pthreads/src/sem_post_multiple.c142
-rw-r--r--pthreads/src/sem_timedwait.c238
-rw-r--r--pthreads/src/sem_trywait.c117
-rw-r--r--pthreads/src/sem_unlink.c58
-rw-r--r--pthreads/src/sem_wait.c187
-rw-r--r--pthreads/src/semaphore.c69
-rw-r--r--pthreads/src/semaphore.h169
-rw-r--r--pthreads/src/signal.c179
-rw-r--r--pthreads/src/spin.c46
-rw-r--r--pthreads/src/sync.c43
-rw-r--r--pthreads/src/tsd.c44
-rw-r--r--pthreads/src/w32_CancelableWait.c161
-rw-r--r--vtparse/src/Makefile19
-rw-r--r--vtparse/src/README67
-rw-r--r--vtparse/src/vtparse.c152
-rw-r--r--vtparse/src/vtparse.h31
-rw-r--r--vtparse/src/vtparse_check_tables.rb24
-rw-r--r--vtparse/src/vtparse_gen_c_tables.rb95
-rw-r--r--vtparse/src/vtparse_table.c2657
-rw-r--r--vtparse/src/vtparse_table.h43
-rw-r--r--vtparse/src/vtparse_tables.rb269
-rw-r--r--vtparse/src/vtparse_test.c37
-rw-r--r--vtparse/vtparse.vcxproj (renamed from pthreads/pthread-win32.vcxproj)42
-rw-r--r--vtparse/vtparse.vcxproj.filters11
627 files changed, 126326 insertions, 81114 deletions
diff --git a/build b/build
-Subproject d1924ec4fd379f5f906bb4be4f9654d79db9d74
+Subproject 58b2c56f0d96a54497f13fc295298dccd6e6ca9
diff --git a/compatibility/stdbool.h b/compatibility/stdbool.h
deleted file mode 100644
index 1ea9bb1..0000000
--- a/compatibility/stdbool.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __STDBOOL_REPLACEMENT__H__
-#define __STDBOOL_REPLACEMENT__H__
-
-#ifdef _MSC_VER
-typedef enum { __bool_must_promote_to_int = -1, false = 0, true = 1 } __bool;
-#define bool __bool
-#define false 0
-#define true 1
-#endif
-
-#endif /* __STDBOOL_REPLACEMENT__H__ */
diff --git a/compatibility/stdint.h b/compatibility/stdint.h
deleted file mode 100644
index 59d0673..0000000
--- a/compatibility/stdint.h
+++ /dev/null
@@ -1,247 +0,0 @@
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2008 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The name of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_STDINT_H_ // [
-#define _MSC_STDINT_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include <limits.h>
-
-// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
-// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
-// or compiler give many errors like this:
-// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#ifdef __cplusplus
-extern "C" {
-#endif
-# include <wchar.h>
-#ifdef __cplusplus
-}
-#endif
-
-// Define _W64 macros to mark types changing their size, like intptr_t.
-#ifndef _W64
-# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
-# define _W64 __w64
-# else
-# define _W64
-# endif
-#endif
-
-
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-
-// Visual Studio 6 and Embedded Visual C++ 4 doesn't
-// realize that, e.g. char has the same size as __int8
-// so we give up on __intX for them.
-#if (_MSC_VER < 1300)
- typedef signed char int8_t;
- typedef signed short int16_t;
- typedef signed int int32_t;
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int uint32_t;
-#else
- typedef signed __int8 int8_t;
- typedef signed __int16 int16_t;
- typedef signed __int32 int32_t;
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
-#endif
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-
-// 7.18.1.2 Minimum-width integer types
-typedef int8_t int_least8_t;
-typedef int16_t int_least16_t;
-typedef int32_t int_least32_t;
-typedef int64_t int_least64_t;
-typedef uint8_t uint_least8_t;
-typedef uint16_t uint_least16_t;
-typedef uint32_t uint_least32_t;
-typedef uint64_t uint_least64_t;
-
-// 7.18.1.3 Fastest minimum-width integer types
-typedef int8_t int_fast8_t;
-typedef int16_t int_fast16_t;
-typedef int32_t int_fast32_t;
-typedef int64_t int_fast64_t;
-typedef uint8_t uint_fast8_t;
-typedef uint16_t uint_fast16_t;
-typedef uint32_t uint_fast32_t;
-typedef uint64_t uint_fast64_t;
-
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
- typedef signed __int64 intptr_t;
- typedef unsigned __int64 uintptr_t;
-#else // _WIN64 ][
- typedef _W64 signed int intptr_t;
- typedef _W64 unsigned int uintptr_t;
-#endif // _WIN64 ]
-
-// 7.18.1.5 Greatest-width integer types
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
-#ifndef WCHAR_MIN // [
-# define WCHAR_MIN 0
-#endif // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
-# define WCHAR_MAX _UI16_MAX
-#endif // WCHAR_MAX ]
-
-#define WINT_MIN 0
-#define WINT_MAX _UI16_MAX
-
-#endif // __STDC_LIMIT_MACROS ]
-
-
-// 7.18.4 Limits of other integer types
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val) val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-#define INT64_C(val) val##i64
-
-#define UINT8_C(val) val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-#define INTMAX_C INT64_C
-#define UINTMAX_C UINT64_C
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-
-#endif // _MSC_STDINT_H_ ]
diff --git a/compatibility/unistd.h b/compatibility/unistd.h
deleted file mode 100644
index 3360ae2..0000000
--- a/compatibility/unistd.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _UNISTD_H
-#define _UNISTD_H 1
-
-/* This file intended to serve as a drop-in replacement for
- * unistd.h on Windows
- * Please add functionality as neeeded
- */
-
-#include <stdlib.h>
-#include <io.h>
-//#include <getopt.h> /* getopt from: http://www.pwilson.net/sample.html. */
-
-#define srandom srand
-#define random rand
-
-static const W_OK = 2;
-static const R_OK = 4;
-
-#define access _access
-#define ftruncate _chsize
-
-#undef ssize_t
-#ifdef _WIN64
-typedef __int64 ssize_t;
-#else
-typedef _W64 int ssize_t;
-#endif
-
-#define STDIN_FILENO 0
-#define STDOUT_FILENO 1
-#define STDERR_FILENO 2
-/* should be in some equivalent to <sys/types.h> */
-typedef __int8 int8_t;
-typedef __int16 int16_t;
-typedef __int32 int32_t;
-typedef __int64 int64_t;
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-
-#endif /* unistd.h */
diff --git a/json-c/src/Android.configure.mk b/json-c/src/Android.configure.mk
new file mode 100644
index 0000000..c52c220
--- /dev/null
+++ b/json-c/src/Android.configure.mk
@@ -0,0 +1,39 @@
+# This file is the top android makefile for all sub-modules.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+json_c_TOP := $(LOCAL_PATH)
+
+JSON_C_BUILT_SOURCES := Android.mk
+
+JSON_C_BUILT_SOURCES := $(patsubst %, $(abspath $(json_c_TOP))/%, $(JSON_C_BUILT_SOURCES))
+
+.PHONY: json-c-configure json-c-configure-real
+json-c-configure-real:
+ echo $(JSON_C_BUILT_SOURCES)
+ cd $(json_c_TOP) ; \
+ $(abspath $(json_c_TOP))/autogen.sh && \
+ CC="$(CONFIGURE_CC)" \
+ CFLAGS="$(CONFIGURE_CFLAGS)" \
+ LD=$(TARGET_LD) \
+ LDFLAGS="$(CONFIGURE_LDFLAGS)" \
+ CPP=$(CONFIGURE_CPP) \
+ CPPFLAGS="$(CONFIGURE_CPPFLAGS)" \
+ PKG_CONFIG_LIBDIR=$(CONFIGURE_PKG_CONFIG_LIBDIR) \
+ PKG_CONFIG_TOP_BUILD_DIR=/ \
+ ac_cv_func_malloc_0_nonnull=yes \
+ ac_cv_func_realloc_0_nonnull=yes \
+ $(abspath $(json_c_TOP))/$(CONFIGURE) --host=$(CONFIGURE_HOST) \
+ --prefix=/system \
+ && \
+ for file in $(JSON_C_BUILT_SOURCES); do \
+ rm -f $$file && \
+ make -C $$(dirname $$file) $$(basename $$file) ; \
+ done
+
+json-c-configure: json-c-configure-real
+
+PA_CONFIGURE_TARGETS += json-c-configure
+
+-include $(json_c_TOP)/Android.mk
diff --git a/json-c/src/README.md b/json-c/src/README.md
new file mode 100644
index 0000000..3d009b5
--- /dev/null
+++ b/json-c/src/README.md
@@ -0,0 +1,63 @@
+`json-c`
+========
+
+Building on Unix with `git`, `gcc` and `autotools`
+--------------------------------------------------
+
+Home page for json-c: https://github.com/json-c/json-c/wiki
+
+Caution: do **NOT** use sources from svn.metaparadigm.com,
+they are old.
+
+Prerequisites:
+
+ - `gcc`, `clang`, or another C compiler
+ - `libtool`
+
+If you're not using a release tarball, you'll also need:
+
+ - `autoconf` (`autoreconf`)
+ - `automake`
+
+Make sure you have a complete `libtool` install, including `libtoolize`.
+
+`json-c` GitHub repo: https://github.com/json-c/json-c
+
+```bash
+$ git clone https://github.com/json-c/json-c.git
+$ cd json-c
+$ sh autogen.sh
+```
+
+followed by
+
+```bash
+$ ./configure
+$ make
+$ make install
+```
+
+To build and run the test programs:
+
+```bash
+$ make check
+```
+
+Linking to `libjson-c`
+----------------------
+
+If your system has `pkgconfig`,
+then you can just add this to your `makefile`:
+
+```make
+CFLAGS += $(shell pkg-config --cflags json-c)
+LDFLAGS += $(shell pkg-config --libs json-c)
+```
+
+Without `pkgconfig`, you would do something like this:
+
+```make
+JSON_C_DIR=/path/to/json_c/install
+CFLAGS += -I$(JSON_C_DIR)/include/json-c
+LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c
+```
diff --git a/json-c/src/configure.ac b/json-c/src/configure.ac
new file mode 100644
index 0000000..94b0d0c
--- /dev/null
+++ b/json-c/src/configure.ac
@@ -0,0 +1,114 @@
+AC_PREREQ(2.52)
+
+# Process this file with autoconf to produce a configure script.
+AC_INIT([json-c], 0.12.99, [json-c@googlegroups.com])
+
+AM_INIT_AUTOMAKE
+
+AC_PROG_MAKE_SET
+
+AC_ARG_ENABLE(rdrand,
+ AS_HELP_STRING([--enable-rdrand],
+ [Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]),
+[if test x$enableval = xyes; then
+ enable_rdrand=yes
+ AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed])
+fi])
+
+if test "x$enable_rdrand" = "xyes"; then
+ AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed enabled on supported x86/x64 platforms])
+else
+ AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed disabled. Use --enable-rdrand to enable])
+fi
+
+# enable silent build by default
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+# Checks for programs.
+
+# Checks for libraries.
+
+# Checks for header files.
+AM_PROG_CC_C_O
+AC_CONFIG_HEADER(config.h)
+AC_CONFIG_HEADER(json_config.h)
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/cdefs.h] [sys/param.h] stdarg.h locale.h endian.h)
+AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public define for json_inttypes.h])])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_VPRINTF
+AC_FUNC_MEMCMP
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale)
+AC_CHECK_DECLS([INFINITY], [], [], [[#include <math.h>]])
+AC_CHECK_DECLS([nan], [], [], [[#include <math.h>]])
+AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]])
+AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]])
+AC_CHECK_DECLS([_isnan], [], [], [[#include <float.h>]])
+AC_CHECK_DECLS([_finite], [], [], [[#include <float.h>]])
+
+if test "$ac_cv_have_decl_isnan" = "yes" ; then
+ AC_TRY_LINK([#include <math.h>], [float f = 0.0; return isnan(f)], [], [LIBS="$LIBS -lm"])
+fi
+
+#check if .section.gnu.warning accepts long strings (for __warn_references)
+AC_LANG_PUSH([C])
+
+AC_MSG_CHECKING([if .gnu.warning accepts long strings])
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
+extern void json_object_get();
+__asm__(".section .gnu.json_object_get,\n\t.ascii \"Please link against libjson-c instead of libjson\"\n\t.text");
+
+int main(int c,char* v) {return 0;}
+]])], [
+ AC_DEFINE(HAS_GNU_WARNING_LONG, 1, [Define if .gnu.warning accepts long strings.])
+ AC_MSG_RESULT(yes)
+], [
+ AC_MSG_RESULT(no)
+])
+
+AC_LANG_POP([C])
+
+AM_PROG_LIBTOOL
+
+# Check for the -Bsymbolic-functions linker flag
+AC_ARG_ENABLE([Bsymbolic],
+ [AS_HELP_STRING([--disable-Bsymbolic], [Avoid linking with -Bsymbolic-function])],
+ [],
+ [enable_Bsymbolic=check])
+
+AS_IF([test "x$enable_Bsymbolic" = "xcheck"],
+ [
+ saved_LDFLAGS="${LDFLAGS}"
+ AC_MSG_CHECKING([for -Bsymbolic-functions linker flag])
+ LDFLAGS=-Wl,-Bsymbolic-functions
+ AC_TRY_LINK([], [int main (void) { return 0; }],
+ [
+ AC_MSG_RESULT([yes])
+ enable_Bsymbolic=yes
+ ],
+ [
+ AC_MSG_RESULT([no])
+ enable_Bsymbolic=no
+ ])
+ LDFLAGS="${saved_LDFLAGS}"
+ ])
+
+AS_IF([test "x$enable_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions])
+AC_SUBST(JSON_BSYMBOLIC_LDFLAGS)
+
+AC_CONFIG_FILES([
+Makefile
+json-c.pc
+tests/Makefile
+json-c-uninstalled.pc
+])
+
+AC_OUTPUT
+
diff --git a/json-c/src/json-c-uninstalled.pc.in b/json-c/src/json-c-uninstalled.pc.in
new file mode 100644
index 0000000..288f29c
--- /dev/null
+++ b/json-c/src/json-c-uninstalled.pc.in
@@ -0,0 +1,11 @@
+prefix=
+exec_prefix=
+libdir=@abs_top_builddir@
+includedir=@abs_top_srcdir@
+
+Name: json
+Description: JSON implementation in C
+Version: @VERSION@
+Requires:
+Libs: -L@abs_top_builddir@ -ljson-c
+Cflags: -I@abs_top_srcdir@
diff --git a/json-c/src/json-c.pc.in b/json-c/src/json-c.pc.in
new file mode 100644
index 0000000..54b65e6
--- /dev/null
+++ b/json-c/src/json-c.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: json-c
+Description: JSON implementation in C
+Version: @VERSION@
+Requires:
+Libs.private: @LIBS@
+Libs: -L${libdir} -ljson-c
+Cflags: -I${includedir}/json-c
diff --git a/json-c/src/json-c.vcproj b/json-c/src/json-c.vcproj
new file mode 100644
index 0000000..55a579f
--- /dev/null
+++ b/json-c/src/json-c.vcproj
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="json-c"
+ ProjectGUID="{04D8CDBE-FB3E-4362-87E6-07DC3C0083B2}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/jsonD.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="copy config.h.win32 config.h
+copy json_config.h.win32 json_config.h"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/json.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="copy config.h.win32 config.h
+copy json_config.h.win32 json_config.h"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath=".\arraylist.c">
+ </File>
+ <File
+ RelativePath=".\debug.c">
+ </File>
+ <File
+ RelativePath=".\json_object.c">
+ </File>
+ <File
+ RelativePath=".\json_tokener.c">
+ </File>
+ <File
+ RelativePath=".\json_util.c">
+ </File>
+ <File
+ RelativePath=".\linkhash.c">
+ </File>
+ <File
+ RelativePath=".\printbuf.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath=".\arraylist.h">
+ </File>
+ <File
+ RelativePath=".\bits.h">
+ </File>
+ <File
+ RelativePath=".\debug.h">
+ </File>
+ <File
+ RelativePath=".\json_object.h">
+ </File>
+ <File
+ RelativePath=".\json_object_private.h">
+ </File>
+ <File
+ RelativePath=".\json_tokener.h">
+ </File>
+ <File
+ RelativePath=".\json_util.h">
+ </File>
+ <File
+ RelativePath=".\linkhash.h">
+ </File>
+ <File
+ RelativePath=".\printbuf.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ <Filter
+ Name="Documentation"
+ Filter="">
+ <File
+ RelativePath=".\Doxyfile">
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\config.h.win32">
+ </File>
+ <File
+ RelativePath=".\json_config.h.win32">
+ </File>
+ <File
+ RelativePath=".\README-WIN32.html">
+ </File>
+ <File
+ RelativePath=".\README.html">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/json-c/src/json-c.vcxproj b/json-c/src/json-c.vcxproj
new file mode 100644
index 0000000..d9ec767
--- /dev/null
+++ b/json-c/src/json-c.vcxproj
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{04D8CDBE-FB3E-4362-87E6-07DC3C0083B2}</ProjectGuid>
+ <RootNamespace>jsonc</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <PreBuildEvent>
+ <Command>copy config.h.win32 config.h
+copy json_config.h.win32 json_config.h
+</Command>
+ </PreBuildEvent>
+ <PreBuildEvent>
+ <Message>copy config.h from Windows template instead of calling configure</Message>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <PreBuildEvent>
+ <Command>copy config.h.win32 config.h
+copy json_config.h.win32 json_config.h
+</Command>
+ </PreBuildEvent>
+ <PreBuildEvent>
+ <Message>copy config.h from Windows template instead of calling configure</Message>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <PreBuildEvent>
+ <Command>copy config.h.win32 config.h
+copy json_config.h.win32 json_config.h
+</Command>
+ </PreBuildEvent>
+ <PreBuildEvent>
+ <Message>copy config.h from Windows template instead of calling configure</Message>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <PreBuildEvent>
+ <Command>copy config.h.win32 config.h
+copy json_config.h.win32 json_config.h
+</Command>
+ </PreBuildEvent>
+ <PreBuildEvent>
+ <Message>copy config.h from Windows template instead of calling configure</Message>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="arraylist.c" />
+ <ClCompile Include="debug.c" />
+ <ClCompile Include="json_object.c" />
+ <ClCompile Include="json_tokener.c" />
+ <ClCompile Include="json_util.c" />
+ <ClCompile Include="linkhash.c" />
+ <ClCompile Include="printbuf.c" />
+ <ClCompile Include="random_seed.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="arraylist.h" />
+ <ClInclude Include="debug.h" />
+ <ClInclude Include="json_inttypes.h" />
+ <ClInclude Include="json_object.h" />
+ <ClInclude Include="json_object_private.h" />
+ <ClInclude Include="json_tokener.h" />
+ <ClInclude Include="json_util.h" />
+ <ClInclude Include="linkhash.h" />
+ <ClInclude Include="math_compat.h" />
+ <ClInclude Include="printbuf.h" />
+ <ClInclude Include="random_seed.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="config.h.win32" />
+ <None Include="Doxyfile" />
+ <None Include="json_config.h.win32" />
+ <None Include="README-WIN32.html" />
+ <None Include="README.html" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/json-c/src/json-c.vcxproj.filters b/json-c/src/json-c.vcxproj.filters
new file mode 100644
index 0000000..b199efb
--- /dev/null
+++ b/json-c/src/json-c.vcxproj.filters
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
+ </Filter>
+ <Filter Include="Documentation">
+ <UniqueIdentifier>{8c5a59ed-4639-4361-9b7c-ecdcd09b953c}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="arraylist.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="debug.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="json_object.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="json_tokener.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="json_util.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="linkhash.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="printbuf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="random_seed.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="arraylist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="debug.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="json_object.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="json_object_private.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="json_tokener.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="json_util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="linkhash.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="printbuf.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="json_inttypes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="math_compat.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="random_seed.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Doxyfile">
+ <Filter>Documentation</Filter>
+ </None>
+ <None Include="config.h.win32" />
+ <None Include="json_config.h.win32" />
+ <None Include="README-WIN32.html" />
+ <None Include="README.html" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/json-c/src/json_c_version.c b/json-c/src/json_c_version.c
new file mode 100644
index 0000000..b6ded48
--- /dev/null
+++ b/json-c/src/json_c_version.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 Eric Haszlakiewicz
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+#include "config.h"
+
+#include "json_c_version.h"
+
+const char *json_c_version(void)
+{
+ return JSON_C_VERSION;
+}
+
+int json_c_version_num(void)
+{
+ return JSON_C_VERSION_NUM;
+}
+
diff --git a/json-c/src/json_c_version.h b/json-c/src/json_c_version.h
new file mode 100644
index 0000000..617e7f2
--- /dev/null
+++ b/json-c/src/json_c_version.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Eric Haszlakiewicz
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+
+#ifndef _json_c_version_h_
+#define _json_c_version_h_
+
+#define JSON_C_MAJOR_VERSION 0
+#define JSON_C_MINOR_VERSION 12
+#define JSON_C_MICRO_VERSION 99
+#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
+ (JSON_C_MINOR_VERSION << 8) | \
+ JSON_C_MICRO_VERSION)
+#define JSON_C_VERSION "0.12.99"
+
+const char *json_c_version(void); /* Returns JSON_C_VERSION */
+int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
+
+#endif
diff --git a/json-c/src/json_config.h.win32 b/json-c/src/json_config.h.win32
new file mode 100644
index 0000000..00f55bb
--- /dev/null
+++ b/json-c/src/json_config.h.win32
@@ -0,0 +1,5 @@
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#if defined(_MSC_VER) && _MSC_VER >= 1800
+#define JSON_C_HAVE_INTTYPES_H 1
+#endif
diff --git a/json-c/src/libjson.c b/json-c/src/libjson.c
new file mode 100644
index 0000000..1e2bab5
--- /dev/null
+++ b/json-c/src/libjson.c
@@ -0,0 +1,26 @@
+
+/* dummy source file for compatibility purposes */
+
+#if defined(HAVE_CDEFS_H)
+#include <sys/cdefs.h>
+#endif
+
+#ifndef __warn_references
+
+#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG)
+
+#define __warn_references(sym,msg) \
+ __asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text");
+
+#else
+#define __warn_references(sym,msg) /* nothing */
+#endif
+
+#endif
+
+#include "json_object.h"
+
+__warn_references(json_object_get, "Warning: please link against libjson-c instead of libjson");
+
+/* __asm__(".section .gnu.warning." __STRING(sym) \
+ " ; .ascii \"" msg "\" ; .text") */
diff --git a/json-c/src/math_compat.h b/json-c/src/math_compat.h
new file mode 100644
index 0000000..6506bd9
--- /dev/null
+++ b/json-c/src/math_compat.h
@@ -0,0 +1,31 @@
+#ifndef __math_compat_h
+#define __math_compat_h
+
+/* Define isnan, isinf, infinity and nan on Windows/MSVC */
+
+#ifndef HAVE_DECL_ISNAN
+# ifdef HAVE_DECL__ISNAN
+#include <float.h>
+#define isnan(x) _isnan(x)
+# endif
+#endif
+
+#ifndef HAVE_DECL_ISINF
+# ifdef HAVE_DECL__FINITE
+#include <float.h>
+#define isinf(x) (!_finite(x))
+# endif
+#endif
+
+#ifndef HAVE_DECL_INFINITY
+#include <float.h>
+#define INFINITY (DBL_MAX + DBL_MAX)
+#define HAVE_DECL_INFINITY
+#endif
+
+#ifndef HAVE_DECL_NAN
+#define NAN (INFINITY - INFINITY)
+#define HAVE_DECL_NAN
+#endif
+
+#endif
diff --git a/json-c/src/random_seed.c b/json-c/src/random_seed.c
new file mode 100644
index 0000000..7fe538d
--- /dev/null
+++ b/json-c/src/random_seed.c
@@ -0,0 +1,238 @@
+/*
+ * random_seed.c
+ *
+ * Copyright (c) 2013 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael@metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+#include "random_seed.h"
+
+#define DEBUG_SEED(s)
+
+
+#if defined ENABLE_RDRAND
+
+/* cpuid */
+
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+#define HAS_X86_CPUID 1
+
+static void do_cpuid(int regs[], int h)
+{
+ __asm__ __volatile__(
+#if defined __x86_64__
+ "pushq %%rbx;\n"
+#else
+ "pushl %%ebx;\n"
+#endif
+ "cpuid;\n"
+#if defined __x86_64__
+ "popq %%rbx;\n"
+#else
+ "popl %%ebx;\n"
+#endif
+ : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
+ : "a"(h));
+}
+
+#elif defined _MSC_VER
+
+#define HAS_X86_CPUID 1
+#define do_cpuid __cpuid
+
+#endif
+
+/* has_rdrand */
+
+#if HAS_X86_CPUID
+
+static int has_rdrand()
+{
+ // CPUID.01H:ECX.RDRAND[bit 30] == 1
+ int regs[4];
+ do_cpuid(regs, 1);
+ return (regs[2] & (1 << 30)) != 0;
+}
+
+#endif
+
+/* get_rdrand_seed - GCC x86 and X64 */
+
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+
+#define HAVE_RDRAND 1
+
+static int get_rdrand_seed()
+{
+ DEBUG_SEED("get_rdrand_seed");
+ int _eax;
+ // rdrand eax
+ __asm__ __volatile__("1: .byte 0x0F\n"
+ " .byte 0xC7\n"
+ " .byte 0xF0\n"
+ " jnc 1b;\n"
+ : "=a" (_eax));
+ return _eax;
+}
+
+#endif
+
+#if defined _MSC_VER
+
+#if _MSC_VER >= 1700
+#define HAVE_RDRAND 1
+
+/* get_rdrand_seed - Visual Studio 2012 and above */
+
+static int get_rdrand_seed()
+{
+ DEBUG_SEED("get_rdrand_seed");
+ int r;
+ while (_rdrand32_step(&r) == 0);
+ return r;
+}
+
+#elif defined _M_IX86
+#define HAVE_RDRAND 1
+
+/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */
+
+static int get_rdrand_seed()
+{
+ DEBUG_SEED("get_rdrand_seed");
+ int _eax;
+retry:
+ // rdrand eax
+ __asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0
+ __asm jnc retry
+ __asm mov _eax, eax
+ return _eax;
+}
+
+#endif
+#endif
+
+#endif /* defined ENABLE_RDRAND */
+
+
+/* has_dev_urandom */
+
+#if defined (__APPLE__) || defined(__unix__) || defined(__linux__)
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define HAVE_DEV_RANDOM 1
+
+static const char *dev_random_file = "/dev/urandom";
+
+static int has_dev_urandom()
+{
+ struct stat buf;
+ if (stat(dev_random_file, &buf)) {
+ return 0;
+ }
+ return ((buf.st_mode & S_IFCHR) != 0);
+}
+
+
+/* get_dev_random_seed */
+
+static int get_dev_random_seed()
+{
+ DEBUG_SEED("get_dev_random_seed");
+
+ int fd = open(dev_random_file, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno));
+ exit(1);
+ }
+
+ int r;
+ ssize_t nread = read(fd, &r, sizeof(r));
+ if (nread != sizeof(r)) {
+ fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno));
+ exit(1);
+ }
+
+ close(fd);
+ return r;
+}
+
+#endif
+
+
+/* get_cryptgenrandom_seed */
+
+#ifdef WIN32
+
+#define HAVE_CRYPTGENRANDOM 1
+
+#include <windows.h>
+#include <wincrypt.h>
+#ifndef __GNUC__
+#pragma comment(lib, "advapi32.lib")
+#endif
+
+static int get_cryptgenrandom_seed()
+{
+ DEBUG_SEED("get_cryptgenrandom_seed");
+
+ HCRYPTPROV hProvider = 0;
+ int r;
+
+ if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+ fprintf(stderr, "error CryptAcquireContextW");
+ exit(1);
+ }
+
+ if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) {
+ fprintf(stderr, "error CryptGenRandom");
+ exit(1);
+ }
+
+ CryptReleaseContext(hProvider, 0);
+
+ return r;
+}
+
+#endif
+
+
+/* get_time_seed */
+
+#include <time.h>
+
+static int get_time_seed()
+{
+ DEBUG_SEED("get_time_seed");
+
+ return (int)time(NULL) * 433494437;
+}
+
+
+/* json_c_get_random_seed */
+
+int json_c_get_random_seed()
+{
+#if HAVE_RDRAND
+ if (has_rdrand()) return get_rdrand_seed();
+#endif
+#if HAVE_DEV_RANDOM
+ if (has_dev_urandom()) return get_dev_random_seed();
+#endif
+#if HAVE_CRYPTGENRANDOM
+ return get_cryptgenrandom_seed();
+#endif
+ return get_time_seed();
+}
diff --git a/json-c/src/random_seed.h b/json-c/src/random_seed.h
new file mode 100644
index 0000000..6d1e268
--- /dev/null
+++ b/json-c/src/random_seed.h
@@ -0,0 +1,25 @@
+/*
+ * random_seed.h
+ *
+ * Copyright (c) 2013 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael@metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef seed_h
+#define seed_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int json_c_get_random_seed();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/src/tests/Makefile.am b/json-c/src/tests/Makefile.am
new file mode 100644
index 0000000..ea4b051
--- /dev/null
+++ b/json-c/src/tests/Makefile.am
@@ -0,0 +1,41 @@
+
+include ../Makefile.am.inc
+LDADD= $(LIBJSON_LA)
+
+LIBJSON_LA=$(top_builddir)/libjson-c.la
+
+TESTS=
+TESTS+= test1.test
+TESTS+= test2.test
+TESTS+= test4.test
+TESTS+= testReplaceExisting.test
+TESTS+= test_parse_int64.test
+TESTS+= test_null.test
+TESTS+= test_cast.test
+TESTS+= test_parse.test
+TESTS+= test_locale.test
+TESTS+= test_charcase.test
+TESTS+= test_printbuf.test
+TESTS+= test_set_serializer.test
+
+check_PROGRAMS=
+check_PROGRAMS += $(TESTS:.test=)
+
+# Note: handled by test1.test
+check_PROGRAMS += test1Formatted
+test1Formatted_SOURCES = test1.c parse_flags.c
+test1Formatted_CPPFLAGS = -DTEST_FORMATTED
+
+# Note: handled by test2.test
+check_PROGRAMS += test2Formatted
+test2Formatted_SOURCES = test2.c parse_flags.c
+test2Formatted_CPPFLAGS = -DTEST_FORMATTED
+
+EXTRA_DIST=
+EXTRA_DIST += $(TESTS)
+
+testsubdir=testSubDir
+TESTS_ENVIRONMENT = top_builddir=$(top_builddir)
+
+distclean-local:
+ -rm -rf $(testsubdir)
diff --git a/json-c/src/tests/parse_flags.c b/json-c/src/tests/parse_flags.c
new file mode 100644
index 0000000..06910e6
--- /dev/null
+++ b/json-c/src/tests/parse_flags.c
@@ -0,0 +1,50 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "json.h"
+#include "parse_flags.h"
+
+#if !defined(HAVE_STRCASECMP) && defined(_MSC_VER)
+# define strcasecmp _stricmp
+#elif !defined(HAVE_STRCASECMP)
+# error You do not have strcasecmp on your system.
+#endif /* HAVE_STRNCASECMP */
+
+static struct {
+ const char *arg;
+ int flag;
+} format_args[] = {
+ { "plain", JSON_C_TO_STRING_PLAIN },
+ { "spaced", JSON_C_TO_STRING_SPACED },
+ { "pretty", JSON_C_TO_STRING_PRETTY },
+};
+
+#ifndef NELEM
+#define NELEM(x) (sizeof(x) / sizeof(&x[0]))
+#endif
+
+int parse_flags(int argc, char **argv)
+{
+ int arg_idx;
+ int sflags = 0;
+ for (arg_idx = 1; arg_idx < argc ; arg_idx++)
+ {
+ int jj;
+ for (jj = 0; jj < (int)NELEM(format_args); jj++)
+ {
+ if (strcasecmp(argv[arg_idx], format_args[jj].arg) == 0)
+ {
+ sflags |= format_args[jj].flag;
+ break;
+ }
+ }
+ if (jj == NELEM(format_args))
+ {
+ printf("Unknown arg: %s\n", argv[arg_idx]);
+ exit(1);
+ }
+ }
+ return sflags;
+}
diff --git a/json-c/src/tests/parse_flags.h b/json-c/src/tests/parse_flags.h
new file mode 100644
index 0000000..dd5149d
--- /dev/null
+++ b/json-c/src/tests/parse_flags.h
@@ -0,0 +1,4 @@
+#ifndef __parse_flags_h
+#define __parse_flags_h
+int parse_flags(int argc, char **argv);
+#endif
diff --git a/json-c/src/tests/test-defs.sh b/json-c/src/tests/test-defs.sh
new file mode 100644
index 0000000..062170a
--- /dev/null
+++ b/json-c/src/tests/test-defs.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+
+# Make sure srcdir is an absolute path. Supply the variable
+# if it does not exist. We want to be able to run the tests
+# stand-alone!!
+#
+srcdir=${srcdir-.}
+if test ! -d $srcdir ; then
+ echo "test-defs.sh: installation error" 1>&2
+ exit 1
+fi
+
+# Use absolute paths
+case "$srcdir" in
+ /* | [A-Za-z]:\\*) ;;
+ *) srcdir=`\cd $srcdir && pwd` ;;
+esac
+
+case "$top_builddir" in
+ /* | [A-Za-z]:\\*) ;;
+ *) top_builddir=`\cd ${top_builddir-..} && pwd` ;;
+esac
+
+top_builddir=${top_builddir}/tests
+
+progname=`echo "$0" | sed 's,^.*/,,'`
+testname=`echo "$progname" | sed 's,-.*$,,'`
+testsubdir=${testsubdir-testSubDir}
+testsubdir=${testsubdir}/${progname}
+
+# User can set VERBOSE to cause output redirection
+case "$VERBOSE" in
+[Nn]|[Nn][Oo]|0|"")
+ VERBOSE=0
+ exec > /dev/null
+ ;;
+[Yy]|[Yy][Ee][Ss])
+ VERBOSE=1
+ ;;
+esac
+
+rm -rf "$testsubdir" > /dev/null 2>&1
+mkdir -p "$testsubdir"
+CURDIR=$(pwd)
+cd "$testsubdir" \
+ || { echo "Cannot make or change into $testsubdir"; exit 1; }
+
+echo "=== Running test $progname"
+
+CMP="${CMP-cmp}"
+
+use_valgrind=${USE_VALGRIND-1}
+valgrind_path=$(which valgrind 2> /dev/null)
+if [ -z "${valgrind_path}" -o ! -x "${valgrind_path}" ] ; then
+ use_valgrind=0
+fi
+
+#
+# This is a common function to check the results of a test program
+# that is intended to generate consistent output across runs.
+#
+# ${top_builddir} must be set to the top level build directory.
+#
+# Output will be written to the current directory.
+#
+# It must be passed the name of the test command to run, which must be present
+# in the ${top_builddir} directory.
+#
+# It will compare the output of running that against <name of command>.expected
+#
+run_output_test()
+{
+ if [ "$1" = "-o" ] ; then
+ TEST_OUTPUT="$2"
+ shift
+ shift
+ fi
+ TEST_COMMAND="$1"
+ shift
+ if [ -z "${TEST_OUTPUT}" ] ; then
+ TEST_OUTPUT=${TEST_COMMAND}
+ fi
+
+ REDIR_OUTPUT="> \"${TEST_OUTPUT}.out\""
+ if [ $VERBOSE -gt 1 ] ; then
+ REDIR_OUTPUT="| tee \"${TEST_OUTPUT}.out\""
+ fi
+
+ if [ $use_valgrind -eq 1 ] ; then
+ eval valgrind --tool=memcheck \
+ --trace-children=yes \
+ --demangle=yes \
+ --log-file="${TEST_OUTPUT}.vg.out" \
+ --leak-check=full \
+ --show-reachable=yes \
+ --run-libc-freeres=yes \
+ "\"${top_builddir}/${TEST_COMMAND}\"" \"\$@\" ${REDIR_OUTPUT}
+ err=$?
+
+ else
+ eval "\"${top_builddir}/${TEST_COMMAND}"\" \"\$@\" ${REDIR_OUTPUT}
+ err=$?
+ fi
+
+ if [ $err -ne 0 ] ; then
+ echo "ERROR: \"${TEST_COMMAND} $@\" exited with non-zero exit status: $err" 1>&2
+ fi
+
+ if [ $use_valgrind -eq 1 ] ; then
+ if ! tail -1 "${TEST_OUTPUT}.vg.out" | grep -q "ERROR SUMMARY: 0 errors" ; then
+ echo "ERROR: valgrind found errors during execution:" 1>&2
+ cat "${TEST_OUTPUT}.vg.out"
+ err=1
+ fi
+ fi
+
+ if ! "$CMP" -s "${top_builddir}/${TEST_OUTPUT}.expected" "${TEST_OUTPUT}.out" ; then
+ echo "ERROR: \"${TEST_COMMAND} $@\" (${TEST_OUTPUT}) failed (set VERBOSE=1 to see full output):" 1>&2
+ (cd "${CURDIR}" ; set -x ; diff "${top_builddir}/${TEST_OUTPUT}.expected" "$testsubdir/${TEST_OUTPUT}.out")
+ echo "cp \"$testsubdir/${TEST_OUTPUT}.out\" \"${top_builddir}/${TEST_OUTPUT}.expected\"" 1>&2
+
+ err=1
+ fi
+
+ return $err
+}
+
+
diff --git a/json-c/src/tests/test1.c b/json-c/src/tests/test1.c
new file mode 100644
index 0000000..8136227
--- /dev/null
+++ b/json-c/src/tests/test1.c
@@ -0,0 +1,134 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+
+#include "json.h"
+#include "parse_flags.h"
+
+static int sort_fn (const void *j1, const void *j2)
+{
+ json_object * const *jso1, * const *jso2;
+ int i1, i2;
+
+ jso1 = (json_object* const*)j1;
+ jso2 = (json_object* const*)j2;
+ if (!*jso1 && !*jso2)
+ return 0;
+ if (!*jso1)
+ return -1;
+ if (!*jso2)
+ return 1;
+
+ i1 = json_object_get_int(*jso1);
+ i2 = json_object_get_int(*jso2);
+
+ return i1 - i2;
+}
+
+#ifdef TEST_FORMATTED
+#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj,sflags)
+#else
+/* no special define */
+#endif
+
+int main(int argc, char **argv)
+{
+ json_object *my_string, *my_int, *my_object, *my_array;
+ int i;
+#ifdef TEST_FORMATTED
+ int sflags = 0;
+#endif
+
+ MC_SET_DEBUG(1);
+
+#ifdef TEST_FORMATTED
+ sflags = parse_flags(argc, argv);
+#endif
+
+ my_string = json_object_new_string("\t");
+ printf("my_string=%s\n", json_object_get_string(my_string));
+ printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
+ json_object_put(my_string);
+
+ my_string = json_object_new_string("\\");
+ printf("my_string=%s\n", json_object_get_string(my_string));
+ printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
+ json_object_put(my_string);
+
+ my_string = json_object_new_string("foo");
+ printf("my_string=%s\n", json_object_get_string(my_string));
+ printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
+
+ my_int = json_object_new_int(9);
+ printf("my_int=%d\n", json_object_get_int(my_int));
+ printf("my_int.to_string()=%s\n", json_object_to_json_string(my_int));
+
+ my_array = json_object_new_array();
+ json_object_array_add(my_array, json_object_new_int(1));
+ json_object_array_add(my_array, json_object_new_int(2));
+ json_object_array_add(my_array, json_object_new_int(3));
+ json_object_array_put_idx(my_array, 4, json_object_new_int(5));
+ printf("my_array=\n");
+ for(i=0; i < json_object_array_length(my_array); i++)
+ {
+ json_object *obj = json_object_array_get_idx(my_array, i);
+ printf("\t[%d]=%s\n", i, json_object_to_json_string(obj));
+ }
+ printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
+
+ json_object_put(my_array);
+
+ my_array = json_object_new_array();
+ json_object_array_add(my_array, json_object_new_int(3));
+ json_object_array_add(my_array, json_object_new_int(1));
+ json_object_array_add(my_array, json_object_new_int(2));
+ json_object_array_put_idx(my_array, 4, json_object_new_int(0));
+ printf("my_array=\n");
+ for(i=0; i < json_object_array_length(my_array); i++)
+ {
+ json_object *obj = json_object_array_get_idx(my_array, i);
+ printf("\t[%d]=%s\n", i, json_object_to_json_string(obj));
+ }
+ printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
+ json_object_array_sort(my_array, sort_fn);
+ printf("my_array=\n");
+ for(i=0; i < json_object_array_length(my_array); i++)
+ {
+ json_object *obj = json_object_array_get_idx(my_array, i);
+ printf("\t[%d]=%s\n", i, json_object_to_json_string(obj));
+ }
+ printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
+
+ my_object = json_object_new_object();
+ json_object_object_add(my_object, "abc", json_object_new_int(12));
+ json_object_object_add(my_object, "foo", json_object_new_string("bar"));
+ json_object_object_add(my_object, "bool0", json_object_new_boolean(0));
+ json_object_object_add(my_object, "bool1", json_object_new_boolean(1));
+ json_object_object_add(my_object, "baz", json_object_new_string("bang"));
+
+ json_object *baz_obj = json_object_new_string("fark");
+ json_object_get(baz_obj);
+ json_object_object_add(my_object, "baz", baz_obj);
+ json_object_object_del(my_object, "baz");
+
+ /* baz_obj should still be valid */
+ printf("baz_obj.to_string()=%s\n", json_object_to_json_string(baz_obj));
+ json_object_put(baz_obj);
+
+ /*json_object_object_add(my_object, "arr", my_array);*/
+ printf("my_object=\n");
+ json_object_object_foreach(my_object, key, val)
+ {
+ printf("\t%s: %s\n", key, json_object_to_json_string(val));
+ }
+ printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object));
+
+ json_object_put(my_string);
+ json_object_put(my_int);
+ json_object_put(my_object);
+ json_object_put(my_array);
+
+ return 0;
+}
diff --git a/json-c/src/tests/test1.expected b/json-c/src/tests/test1.expected
new file mode 100644
index 0000000..4aaf6cc
--- /dev/null
+++ b/json-c/src/tests/test1.expected
@@ -0,0 +1,36 @@
+my_string=
+my_string.to_string()="\t"
+my_string=\
+my_string.to_string()="\\"
+my_string=foo
+my_string.to_string()="foo"
+my_int=9
+my_int.to_string()=9
+my_array=
+ [0]=1
+ [1]=2
+ [2]=3
+ [3]=null
+ [4]=5
+my_array.to_string()=[ 1, 2, 3, null, 5 ]
+my_array=
+ [0]=3
+ [1]=1
+ [2]=2
+ [3]=null
+ [4]=0
+my_array.to_string()=[ 3, 1, 2, null, 0 ]
+my_array=
+ [0]=null
+ [1]=0
+ [2]=1
+ [3]=2
+ [4]=3
+my_array.to_string()=[ null, 0, 1, 2, 3 ]
+baz_obj.to_string()="fark"
+my_object=
+ abc: 12
+ foo: "bar"
+ bool0: false
+ bool1: true
+my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true }
diff --git a/json-c/src/tests/test1.test b/json-c/src/tests/test1.test
new file mode 100644
index 0000000..bf9d75e
--- /dev/null
+++ b/json-c/src/tests/test1.test
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test1
+_err=$?
+
+for flag in plain spaced pretty ; do
+ run_output_test -o test1Formatted_${flag} test1Formatted ${flag}
+ _err2=$?
+ if [ $_err -eq 0 ] ; then
+ _err=$_err2
+ fi
+done
+
+exit $_err
diff --git a/json-c/src/tests/test1Formatted_plain.expected b/json-c/src/tests/test1Formatted_plain.expected
new file mode 100644
index 0000000..843f55a
--- /dev/null
+++ b/json-c/src/tests/test1Formatted_plain.expected
@@ -0,0 +1,36 @@
+my_string=
+my_string.to_string()="\t"
+my_string=\
+my_string.to_string()="\\"
+my_string=foo
+my_string.to_string()="foo"
+my_int=9
+my_int.to_string()=9
+my_array=
+ [0]=1
+ [1]=2
+ [2]=3
+ [3]=null
+ [4]=5
+my_array.to_string()=[1,2,3,null,5]
+my_array=
+ [0]=3
+ [1]=1
+ [2]=2
+ [3]=null
+ [4]=0
+my_array.to_string()=[3,1,2,null,0]
+my_array=
+ [0]=null
+ [1]=0
+ [2]=1
+ [3]=2
+ [4]=3
+my_array.to_string()=[null,0,1,2,3]
+baz_obj.to_string()="fark"
+my_object=
+ abc: 12
+ foo: "bar"
+ bool0: false
+ bool1: true
+my_object.to_string()={"abc":12,"foo":"bar","bool0":false,"bool1":true}
diff --git a/json-c/src/tests/test1Formatted_pretty.expected b/json-c/src/tests/test1Formatted_pretty.expected
new file mode 100644
index 0000000..ca4ff67
--- /dev/null
+++ b/json-c/src/tests/test1Formatted_pretty.expected
@@ -0,0 +1,59 @@
+my_string=
+my_string.to_string()="\t"
+my_string=\
+my_string.to_string()="\\"
+my_string=foo
+my_string.to_string()="foo"
+my_int=9
+my_int.to_string()=9
+my_array=
+ [0]=1
+ [1]=2
+ [2]=3
+ [3]=null
+ [4]=5
+my_array.to_string()=[
+ 1,
+ 2,
+ 3,
+ null,
+ 5
+]
+my_array=
+ [0]=3
+ [1]=1
+ [2]=2
+ [3]=null
+ [4]=0
+my_array.to_string()=[
+ 3,
+ 1,
+ 2,
+ null,
+ 0
+]
+my_array=
+ [0]=null
+ [1]=0
+ [2]=1
+ [3]=2
+ [4]=3
+my_array.to_string()=[
+ null,
+ 0,
+ 1,
+ 2,
+ 3
+]
+baz_obj.to_string()="fark"
+my_object=
+ abc: 12
+ foo: "bar"
+ bool0: false
+ bool1: true
+my_object.to_string()={
+ "abc":12,
+ "foo":"bar",
+ "bool0":false,
+ "bool1":true
+}
diff --git a/json-c/src/tests/test1Formatted_spaced.expected b/json-c/src/tests/test1Formatted_spaced.expected
new file mode 100644
index 0000000..4aaf6cc
--- /dev/null
+++ b/json-c/src/tests/test1Formatted_spaced.expected
@@ -0,0 +1,36 @@
+my_string=
+my_string.to_string()="\t"
+my_string=\
+my_string.to_string()="\\"
+my_string=foo
+my_string.to_string()="foo"
+my_int=9
+my_int.to_string()=9
+my_array=
+ [0]=1
+ [1]=2
+ [2]=3
+ [3]=null
+ [4]=5
+my_array.to_string()=[ 1, 2, 3, null, 5 ]
+my_array=
+ [0]=3
+ [1]=1
+ [2]=2
+ [3]=null
+ [4]=0
+my_array.to_string()=[ 3, 1, 2, null, 0 ]
+my_array=
+ [0]=null
+ [1]=0
+ [2]=1
+ [3]=2
+ [4]=3
+my_array.to_string()=[ null, 0, 1, 2, 3 ]
+baz_obj.to_string()="fark"
+my_object=
+ abc: 12
+ foo: "bar"
+ bool0: false
+ bool1: true
+my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true }
diff --git a/json-c/src/tests/test2.c b/json-c/src/tests/test2.c
new file mode 100644
index 0000000..9b30c62
--- /dev/null
+++ b/json-c/src/tests/test2.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "json.h"
+#include "parse_flags.h"
+
+#ifdef TEST_FORMATTED
+#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj,sflags)
+#else
+/* no special define */
+#endif
+
+
+int main(int argc, char **argv)
+{
+ json_object *new_obj;
+#ifdef TEST_FORMATTED
+ int sflags = 0;
+#endif
+
+ MC_SET_DEBUG(1);
+
+#ifdef TEST_FORMATTED
+ sflags = parse_flags(argc, argv);
+#endif
+
+ new_obj = json_tokener_parse("/* more difficult test case */ { \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ return 0;
+}
diff --git a/json-c/src/tests/test2.expected b/json-c/src/tests/test2.expected
new file mode 100644
index 0000000..ac404e0
--- /dev/null
+++ b/json-c/src/tests/test2.expected
@@ -0,0 +1 @@
+new_obj.to_string()={ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": [ "GML", "XML", "markup" ] } ] } } }
diff --git a/json-c/src/tests/test2.test b/json-c/src/tests/test2.test
new file mode 100644
index 0000000..0b5fc87
--- /dev/null
+++ b/json-c/src/tests/test2.test
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test2
+_err=$?
+
+for flag in plain spaced pretty ; do
+ run_output_test -o test2Formatted_${flag} test2Formatted ${flag}
+ _err2=$?
+ if [ $_err -eq 0 ] ; then
+ _err=$_err2
+ fi
+done
+
+exit $_err
diff --git a/json-c/src/tests/test2Formatted_plain.expected b/json-c/src/tests/test2Formatted_plain.expected
new file mode 100644
index 0000000..8b2053d
--- /dev/null
+++ b/json-c/src/tests/test2Formatted_plain.expected
@@ -0,0 +1 @@
+new_obj.to_string()={"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":[{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML","markup"]}]}}}
diff --git a/json-c/src/tests/test2Formatted_pretty.expected b/json-c/src/tests/test2Formatted_pretty.expected
new file mode 100644
index 0000000..c311691
--- /dev/null
+++ b/json-c/src/tests/test2Formatted_pretty.expected
@@ -0,0 +1,23 @@
+new_obj.to_string()={
+ "glossary":{
+ "title":"example glossary",
+ "GlossDiv":{
+ "title":"S",
+ "GlossList":[
+ {
+ "ID":"SGML",
+ "SortAs":"SGML",
+ "GlossTerm":"Standard Generalized Markup Language",
+ "Acronym":"SGML",
+ "Abbrev":"ISO 8879:1986",
+ "GlossDef":"A meta-markup language, used to create markup languages such as DocBook.",
+ "GlossSeeAlso":[
+ "GML",
+ "XML",
+ "markup"
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/json-c/src/tests/test2Formatted_spaced.expected b/json-c/src/tests/test2Formatted_spaced.expected
new file mode 100644
index 0000000..ac404e0
--- /dev/null
+++ b/json-c/src/tests/test2Formatted_spaced.expected
@@ -0,0 +1 @@
+new_obj.to_string()={ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": [ "GML", "XML", "markup" ] } ] } } }
diff --git a/json-c/src/tests/test4.c b/json-c/src/tests/test4.c
new file mode 100644
index 0000000..99331bb
--- /dev/null
+++ b/json-c/src/tests/test4.c
@@ -0,0 +1,53 @@
+/*
+ * gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_tokener.h"
+
+void print_hex( const char* s)
+{
+ const char *iter = s;
+ unsigned char ch;
+ while ((ch = *iter++) != 0)
+ {
+ if( ',' != ch)
+ printf("%x ", ch);
+ else
+ printf( ",");
+ }
+ printf("\n");
+}
+
+int main()
+{
+ const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\"";
+ const char *expected = "\xF0\xA0\x84\xA6,\xF0\xA0\x84\xA7,\xF0\x90\x84\xA6,\xF0\x90\x84\xA7";
+ struct json_object *parse_result = json_tokener_parse((char*)input);
+ const char *unjson = json_object_get_string(parse_result);
+
+ printf("input: %s\n", input);
+
+ int strings_match = !strcmp( expected, unjson);
+ int retval = 0;
+ if (strings_match)
+ {
+ printf("JSON parse result is correct: %s\n", unjson);
+ printf("PASS\n");
+ } else {
+ printf("JSON parse result doesn't match expected string\n");
+ printf("expected string bytes: ");
+ print_hex( expected);
+ printf("parsed string bytes: ");
+ print_hex( unjson);
+ printf("FAIL\n");
+ retval = 1;
+ }
+ json_object_put(parse_result);
+ return retval;
+}
diff --git a/json-c/src/tests/test4.expected b/json-c/src/tests/test4.expected
new file mode 100644
index 0000000..932761d
--- /dev/null
+++ b/json-c/src/tests/test4.expected
@@ -0,0 +1,3 @@
+input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27"
+JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧
+PASS
diff --git a/json-c/src/tests/test4.test b/json-c/src/tests/test4.test
new file mode 100644
index 0000000..4e8147e
--- /dev/null
+++ b/json-c/src/tests/test4.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test4
+exit $?
diff --git a/json-c/src/tests/testReplaceExisting.c b/json-c/src/tests/testReplaceExisting.c
new file mode 100644
index 0000000..0534cf9
--- /dev/null
+++ b/json-c/src/tests/testReplaceExisting.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "json.h"
+
+int main(int argc, char **argv)
+{
+ MC_SET_DEBUG(1);
+
+ /*
+ * Check that replacing an existing object keeps the key valid,
+ * and that it keeps the order the same.
+ */
+ json_object *my_object = json_object_new_object();
+ json_object_object_add(my_object, "foo1", json_object_new_string("bar1"));
+ json_object_object_add(my_object, "foo2", json_object_new_string("bar2"));
+ json_object_object_add(my_object, "deleteme", json_object_new_string("bar2"));
+ json_object_object_add(my_object, "foo3", json_object_new_string("bar3"));
+
+ printf("==== delete-in-loop test starting ====\n");
+
+ int orig_count = 0;
+ json_object_object_foreach(my_object, key0, val0)
+ {
+ printf("Key at index %d is [%s]", orig_count, key0);
+ if (strcmp(key0, "deleteme") == 0)
+ {
+ json_object_object_del(my_object, key0);
+ printf(" (deleted)\n");
+ }
+ else
+ printf(" (kept)\n");
+ orig_count++;
+ }
+
+ printf("==== replace-value first loop starting ====\n");
+
+ const char *original_key = NULL;
+ orig_count = 0;
+ json_object_object_foreach(my_object, key, val)
+ {
+ printf("Key at index %d is [%s]\n", orig_count, key);
+ orig_count++;
+ if (strcmp(key, "foo2") != 0)
+ continue;
+ printf("replacing value for key [%s]\n", key);
+ original_key = key;
+ json_object_object_add(my_object, key, json_object_new_string("zzz"));
+ }
+
+ printf("==== second loop starting ====\n");
+
+ int new_count = 0;
+ int retval = 0;
+ json_object_object_foreach(my_object, key2, val2)
+ {
+ printf("Key at index %d is [%s]\n", new_count, key2);
+ new_count++;
+ if (strcmp(key2, "foo2") != 0)
+ continue;
+ printf("pointer for key [%s] does %smatch\n", key2,
+ (key2 == original_key) ? "" : "NOT ");
+ if (key2 != original_key)
+ retval = 1;
+ }
+ if (new_count != orig_count)
+ {
+ printf("mismatch between original count (%d) and new count (%d)\n",
+ orig_count, new_count);
+ retval = 1;
+ }
+
+ json_object_put( my_object );
+
+ return retval;
+}
diff --git a/json-c/src/tests/testReplaceExisting.expected b/json-c/src/tests/testReplaceExisting.expected
new file mode 100644
index 0000000..2b6e532
--- /dev/null
+++ b/json-c/src/tests/testReplaceExisting.expected
@@ -0,0 +1,15 @@
+==== delete-in-loop test starting ====
+Key at index 0 is [foo1] (kept)
+Key at index 1 is [foo2] (kept)
+Key at index 2 is [deleteme] (deleted)
+Key at index 3 is [foo3] (kept)
+==== replace-value first loop starting ====
+Key at index 0 is [foo1]
+Key at index 1 is [foo2]
+replacing value for key [foo2]
+Key at index 2 is [foo3]
+==== second loop starting ====
+Key at index 0 is [foo1]
+Key at index 1 is [foo2]
+pointer for key [foo2] does match
+Key at index 2 is [foo3]
diff --git a/json-c/src/tests/testReplaceExisting.test b/json-c/src/tests/testReplaceExisting.test
new file mode 100644
index 0000000..8ac7674
--- /dev/null
+++ b/json-c/src/tests/testReplaceExisting.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test testReplaceExisting
+exit $?
diff --git a/json-c/src/tests/test_cast.c b/json-c/src/tests/test_cast.c
new file mode 100644
index 0000000..edbb348
--- /dev/null
+++ b/json-c/src/tests/test_cast.c
@@ -0,0 +1,111 @@
+/*
+ * Tests if casting within the json_object_get_* functions work correctly.
+ * Also checks the json_object_get_type and json_object_is_type functions.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "config.h"
+
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_util.h"
+
+static void getit(struct json_object *new_obj, const char *field);
+static void checktype_header(void);
+static void checktype(struct json_object *new_obj, const char *field);
+
+int main(int argc, char **argv)
+{
+ const char *input = "{\n\
+ \"string_of_digits\": \"123\",\n\
+ \"regular_number\": 222,\n\
+ \"decimal_number\": 99.55,\n\
+ \"boolean_true\": true,\n\
+ \"boolean_false\": false,\n\
+ \"big_number\": 2147483649,\n\
+ \"a_null\": null,\n\
+ }";
+ /* Note: 2147483649 = INT_MAX + 2 */
+
+ struct json_object *new_obj;
+
+ new_obj = json_tokener_parse(input);
+ printf("Parsed input: %s\n", input);
+ printf("Result is %s\n", (new_obj == NULL) ? "NULL (error!)" : "not NULL");
+ if (!new_obj)
+ return 1; // oops, we failed.
+
+ getit(new_obj, "string_of_digits");
+ getit(new_obj, "regular_number");
+ getit(new_obj, "decimal_number");
+ getit(new_obj, "boolean_true");
+ getit(new_obj, "boolean_false");
+ getit(new_obj, "big_number");
+ getit(new_obj, "a_null");
+
+ // Now check the behaviour of the json_object_is_type() function.
+ printf("\n================================\n");
+ checktype_header();
+ checktype(new_obj, NULL);
+ checktype(new_obj, "string_of_digits");
+ checktype(new_obj, "regular_number");
+ checktype(new_obj, "decimal_number");
+ checktype(new_obj, "boolean_true");
+ checktype(new_obj, "boolean_false");
+ checktype(new_obj, "big_number");
+ checktype(new_obj, "a_null");
+
+ json_object_put(new_obj);
+
+ return 0;
+}
+
+static void getit(struct json_object *new_obj, const char *field)
+{
+ struct json_object *o = NULL;
+ if (!json_object_object_get_ex(new_obj, field, &o))
+ printf("Field %s does not exist\n", field);
+
+ enum json_type o_type = json_object_get_type(o);
+ printf("new_obj.%s json_object_get_type()=%s\n", field,
+ json_type_to_name(o_type));
+ printf("new_obj.%s json_object_get_int()=%d\n", field,
+ json_object_get_int(o));
+ printf("new_obj.%s json_object_get_int64()=%" PRId64 "\n", field,
+ json_object_get_int64(o));
+ printf("new_obj.%s json_object_get_boolean()=%d\n", field,
+ json_object_get_boolean(o));
+ printf("new_obj.%s json_object_get_double()=%f\n", field,
+ json_object_get_double(o));
+}
+
+static void checktype_header()
+{
+ printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n",
+ json_type_to_name(json_type_null),
+ json_type_to_name(json_type_boolean),
+ json_type_to_name(json_type_double),
+ json_type_to_name(json_type_int),
+ json_type_to_name(json_type_object),
+ json_type_to_name(json_type_array),
+ json_type_to_name(json_type_string));
+}
+static void checktype(struct json_object *new_obj, const char *field)
+{
+ struct json_object *o = new_obj;
+ if (field && !json_object_object_get_ex(new_obj, field, &o))
+ printf("Field %s does not exist\n", field);
+
+ printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d\n",
+ field ? "." : " ", field ? field : "",
+ json_object_is_type(o, json_type_null),
+ json_object_is_type(o, json_type_boolean),
+ json_object_is_type(o, json_type_double),
+ json_object_is_type(o, json_type_int),
+ json_object_is_type(o, json_type_object),
+ json_object_is_type(o, json_type_array),
+ json_object_is_type(o, json_type_string));
+}
diff --git a/json-c/src/tests/test_cast.expected b/json-c/src/tests/test_cast.expected
new file mode 100644
index 0000000..abf8924
--- /dev/null
+++ b/json-c/src/tests/test_cast.expected
@@ -0,0 +1,56 @@
+Parsed input: {
+ "string_of_digits": "123",
+ "regular_number": 222,
+ "decimal_number": 99.55,
+ "boolean_true": true,
+ "boolean_false": false,
+ "big_number": 2147483649,
+ "a_null": null,
+ }
+Result is not NULL
+new_obj.string_of_digits json_object_get_type()=string
+new_obj.string_of_digits json_object_get_int()=123
+new_obj.string_of_digits json_object_get_int64()=123
+new_obj.string_of_digits json_object_get_boolean()=1
+new_obj.string_of_digits json_object_get_double()=123.000000
+new_obj.regular_number json_object_get_type()=int
+new_obj.regular_number json_object_get_int()=222
+new_obj.regular_number json_object_get_int64()=222
+new_obj.regular_number json_object_get_boolean()=1
+new_obj.regular_number json_object_get_double()=222.000000
+new_obj.decimal_number json_object_get_type()=double
+new_obj.decimal_number json_object_get_int()=99
+new_obj.decimal_number json_object_get_int64()=99
+new_obj.decimal_number json_object_get_boolean()=1
+new_obj.decimal_number json_object_get_double()=99.550000
+new_obj.boolean_true json_object_get_type()=boolean
+new_obj.boolean_true json_object_get_int()=1
+new_obj.boolean_true json_object_get_int64()=1
+new_obj.boolean_true json_object_get_boolean()=1
+new_obj.boolean_true json_object_get_double()=1.000000
+new_obj.boolean_false json_object_get_type()=boolean
+new_obj.boolean_false json_object_get_int()=0
+new_obj.boolean_false json_object_get_int64()=0
+new_obj.boolean_false json_object_get_boolean()=0
+new_obj.boolean_false json_object_get_double()=0.000000
+new_obj.big_number json_object_get_type()=int
+new_obj.big_number json_object_get_int()=2147483647
+new_obj.big_number json_object_get_int64()=2147483649
+new_obj.big_number json_object_get_boolean()=1
+new_obj.big_number json_object_get_double()=2147483649.000000
+new_obj.a_null json_object_get_type()=null
+new_obj.a_null json_object_get_int()=0
+new_obj.a_null json_object_get_int64()=0
+new_obj.a_null json_object_get_boolean()=0
+new_obj.a_null json_object_get_double()=0.000000
+
+================================
+json_object_is_type: null,boolean,double,int,object,array,string
+new_obj : 0,0,0,0,1,0,0
+new_obj.string_of_digits : 0,0,0,0,0,0,1
+new_obj.regular_number : 0,0,0,1,0,0,0
+new_obj.decimal_number : 0,0,1,0,0,0,0
+new_obj.boolean_true : 0,1,0,0,0,0,0
+new_obj.boolean_false : 0,1,0,0,0,0,0
+new_obj.big_number : 0,0,0,1,0,0,0
+new_obj.a_null : 1,0,0,0,0,0,0
diff --git a/json-c/src/tests/test_cast.test b/json-c/src/tests/test_cast.test
new file mode 100644
index 0000000..df165f8
--- /dev/null
+++ b/json-c/src/tests/test_cast.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_cast
+exit $?
diff --git a/json-c/src/tests/test_charcase.c b/json-c/src/tests/test_charcase.c
new file mode 100644
index 0000000..9179467
--- /dev/null
+++ b/json-c/src/tests/test_charcase.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+
+#include "json.h"
+#include "json_tokener.h"
+
+static void test_case_parse(void);
+
+int main(int argc, char **argv)
+{
+ MC_SET_DEBUG(1);
+
+ test_case_parse();
+}
+
+/* make sure only lowercase forms are parsed in strict mode */
+static void test_case_parse()
+{
+ struct json_tokener *tok;
+ json_object *new_obj;
+
+ tok = json_tokener_new();
+ json_tokener_set_flags(tok, JSON_TOKENER_STRICT);
+
+ new_obj = json_tokener_parse_ex(tok, "True", 4);
+ assert (new_obj == NULL);
+
+ new_obj = json_tokener_parse_ex(tok, "False", 5);
+ assert (new_obj == NULL);
+
+ new_obj = json_tokener_parse_ex(tok, "Null", 4);
+ assert (new_obj == NULL);
+
+ printf("OK\n");
+
+ json_tokener_free(tok);
+}
diff --git a/json-c/src/tests/test_charcase.expected b/json-c/src/tests/test_charcase.expected
new file mode 100644
index 0000000..e178f82
--- /dev/null
+++ b/json-c/src/tests/test_charcase.expected
@@ -0,0 +1 @@
+OK
diff --git a/json-c/src/tests/test_charcase.test b/json-c/src/tests/test_charcase.test
new file mode 100644
index 0000000..40edbf4
--- /dev/null
+++ b/json-c/src/tests/test_charcase.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_charcase
+exit $?
diff --git a/json-c/src/tests/test_locale.c b/json-c/src/tests/test_locale.c
new file mode 100644
index 0000000..7924bca
--- /dev/null
+++ b/json-c/src/tests/test_locale.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+
+#include "config.h"
+#include "json.h"
+#include "json_tokener.h"
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif /* HAVE_LOCALE_H */
+
+int main(int argc, char **argv)
+{
+ json_object *new_obj;
+#ifdef HAVE_SETLOCALE
+ setlocale(LC_NUMERIC, "de_DE");
+#else
+ printf("No locale\n");
+#endif
+
+ MC_SET_DEBUG(1);
+
+ new_obj = json_tokener_parse("[1.2,3.4,123456.78,5.0,2.3e10]");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string_ext(new_obj,JSON_C_TO_STRING_NOZERO));
+ json_object_put(new_obj);
+}
+
diff --git a/json-c/src/tests/test_locale.expected b/json-c/src/tests/test_locale.expected
new file mode 100644
index 0000000..4415692
--- /dev/null
+++ b/json-c/src/tests/test_locale.expected
@@ -0,0 +1,2 @@
+new_obj.to_string()=[ 1.2, 3.4, 123456.78, 5.0, 2.3e10 ]
+new_obj.to_string()=[1.2,3.4,123456.78,5.0,2.3e10]
diff --git a/json-c/src/tests/test_locale.test b/json-c/src/tests/test_locale.test
new file mode 100644
index 0000000..436587f
--- /dev/null
+++ b/json-c/src/tests/test_locale.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_locale
+exit $?
diff --git a/json-c/src/tests/test_null.c b/json-c/src/tests/test_null.c
new file mode 100644
index 0000000..da86fb6
--- /dev/null
+++ b/json-c/src/tests/test_null.c
@@ -0,0 +1,57 @@
+/*
+* Tests if binary strings are supported.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_tokener.h"
+
+int main()
+{
+ // this test has a space after the null character. check that it's still included
+ const char *input = " \0 ";
+ const char *expected = "\" \\u0000 \"";
+ struct json_object *string = json_object_new_string_len(input, 3);
+ const char *json = json_object_to_json_string(string);
+
+ int strings_match = !strcmp( expected, json);
+ int retval = 0;
+ if (strings_match)
+ {
+ printf("JSON write result is correct: %s\n", json);
+ printf("PASS\n");
+ } else {
+ printf("JSON write result doesn't match expected string\n");
+ printf("expected string: ");
+ printf("%s\n", expected);
+ printf("parsed string: ");
+ printf("%s\n", json);
+ printf("FAIL\n");
+ retval=1;
+ }
+ json_object_put(string);
+
+ struct json_object *parsed_str = json_tokener_parse(expected);
+ if (parsed_str)
+ {
+ int parsed_len = json_object_get_string_len(parsed_str);
+ const char *parsed_cstr = json_object_get_string(parsed_str);
+ int ii;
+ printf("Re-parsed object string len=%d, chars=[", parsed_len);
+ for (ii = 0; ii < parsed_len ; ii++)
+ {
+ printf("%s%d", (ii ? ", " : ""), (int)parsed_cstr[ii]);
+ }
+ printf("]\n");
+ json_object_put(parsed_str);
+ }
+ else
+ {
+ printf("ERROR: failed to parse\n");
+ }
+ return retval;
+}
diff --git a/json-c/src/tests/test_null.expected b/json-c/src/tests/test_null.expected
new file mode 100644
index 0000000..be1c9d1
--- /dev/null
+++ b/json-c/src/tests/test_null.expected
@@ -0,0 +1,3 @@
+JSON write result is correct: " \u0000 "
+PASS
+Re-parsed object string len=3, chars=[32, 0, 32]
diff --git a/json-c/src/tests/test_null.test b/json-c/src/tests/test_null.test
new file mode 100644
index 0000000..7c4365c
--- /dev/null
+++ b/json-c/src/tests/test_null.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_null
+exit $?
diff --git a/json-c/src/tests/test_parse.c b/json-c/src/tests/test_parse.c
new file mode 100644
index 0000000..2e5996e
--- /dev/null
+++ b/json-c/src/tests/test_parse.c
@@ -0,0 +1,342 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+
+#include "json.h"
+#include "json_tokener.h"
+
+static void test_basic_parse(void);
+static void test_verbose_parse(void);
+static void test_incremental_parse(void);
+
+int main(int argc, char **argv)
+{
+ MC_SET_DEBUG(1);
+
+ test_basic_parse();
+ printf("==================================\n");
+ test_verbose_parse();
+ printf("==================================\n");
+ test_incremental_parse();
+ printf("==================================\n");
+}
+
+static void test_basic_parse()
+{
+ json_object *new_obj;
+
+ new_obj = json_tokener_parse("\"\003\"");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("/* hello */\"foo\"");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("// hello\n\"foo\"");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\"");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("null");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("NaN");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("-NaN"); /* non-sensical, returns null */
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("Inf"); /* must use full string, returns null */
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("inf"); /* must use full string, returns null */
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("Infinity");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("infinity");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("-Infinity");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("-infinity");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("True");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("12");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("12.3");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("12.3.4"); /* non-sensical, returns null */
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ /* was returning (int)2015 before patch, should return null */
+ new_obj = json_tokener_parse("2015-01-15");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("{\"FoO\" : -12.3E512}");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("{\"FoO\" : -12.3E51.2}"); /* non-sensical, returns null */
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("[\"\\n\"]");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("[\"\\nabc\\n\"]");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("[null]");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("[]");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("[false]");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("{}");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("{ \"foo\": \"bar\" }");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+
+ new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }");
+ printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
+ json_object_put(new_obj);
+}
+
+static void test_verbose_parse()
+{
+ json_object *new_obj;
+ enum json_tokener_error error = json_tokener_success;
+
+ new_obj = json_tokener_parse_verbose("{ foo }", &error);
+ assert (error == json_tokener_error_parse_object_key_name);
+ assert (new_obj == NULL);
+
+ new_obj = json_tokener_parse("{ foo }");
+ assert (new_obj == NULL);
+
+ new_obj = json_tokener_parse("foo");
+ assert (new_obj == NULL);
+ new_obj = json_tokener_parse_verbose("foo", &error);
+ assert (new_obj == NULL);
+
+ /* b/c the string starts with 'f' parsing return a boolean error */
+ assert (error == json_tokener_error_parse_boolean);
+
+ printf("json_tokener_parse_versbose() OK\n");
+}
+
+struct incremental_step {
+ const char *string_to_parse;
+ int length;
+ int char_offset;
+ enum json_tokener_error expected_error;
+ int reset_tokener;
+} incremental_steps[] = {
+
+ /* Check that full json messages can be parsed, both w/ and w/o a reset */
+ { "{ \"foo\": 123 }", -1, -1, json_tokener_success, 0 },
+ { "{ \"foo\": 456 }", -1, -1, json_tokener_success, 1 },
+ { "{ \"foo\": 789 }", -1, -1, json_tokener_success, 1 },
+
+ /* Check a basic incremental parse */
+ { "{ \"foo", -1, -1, json_tokener_continue, 0 },
+ { "\": {\"bar", -1, -1, json_tokener_continue, 0 },
+ { "\":13}}", -1, -1, json_tokener_success, 1 },
+
+ /* Check that json_tokener_reset actually resets */
+ { "{ \"foo", -1, -1, json_tokener_continue, 1 },
+ { ": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1 },
+
+ /* Check incremental parsing with trailing characters */
+ { "{ \"foo", -1, -1, json_tokener_continue, 0 },
+ { "\": {\"bar", -1, -1, json_tokener_continue, 0 },
+ { "\":13}}XXXX", 10, 6, json_tokener_success, 0 },
+ { "XXXX", 4, 0, json_tokener_error_parse_unexpected, 1 },
+
+ /* Check that trailing characters can change w/o a reset */
+ { "{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0 },
+ { "\"Y\"", -1, -1, json_tokener_success, 1 },
+
+ /* To stop parsing a number we need to reach a non-digit, e.g. a \0 */
+ { "1", 1, 1, json_tokener_continue, 0 },
+ { "2", 2, 1, json_tokener_success, 0 },
+
+ /* Some bad formatting. Check we get the correct error status */
+ { "2015-01-15", 10, 4, json_tokener_error_parse_number, 1 },
+
+ /* Strings have a well defined end point, so we can stop at the quote */
+ { "\"blue\"", -1, -1, json_tokener_success, 0 },
+
+ /* Check each of the escape sequences defined by the spec */
+ { "\"\\\"\"", -1, -1, json_tokener_success, 0 },
+ { "\"\\\\\"", -1, -1, json_tokener_success, 0 },
+ { "\"\\b\"", -1, -1, json_tokener_success, 0 },
+ { "\"\\f\"", -1, -1, json_tokener_success, 0 },
+ { "\"\\n\"", -1, -1, json_tokener_success, 0 },
+ { "\"\\r\"", -1, -1, json_tokener_success, 0 },
+ { "\"\\t\"", -1, -1, json_tokener_success, 0 },
+
+ { "[1,2,3]", -1, -1, json_tokener_success, 0 },
+
+ /* This behaviour doesn't entirely follow the json spec, but until we have
+ a way to specify how strict to be we follow Postel's Law and be liberal
+ in what we accept (up to a point). */
+ { "[1,2,3,]", -1, -1, json_tokener_success, 0 },
+ { "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 },
+
+ { "[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 3 },
+ { "{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 3 },
+
+ { NULL, -1, -1, json_tokener_success, 0 },
+};
+
+static void test_incremental_parse()
+{
+ json_object *new_obj;
+ enum json_tokener_error jerr;
+ json_tokener *tok;
+ const char *string_to_parse;
+ int ii;
+ int num_ok, num_error;
+
+ num_ok = 0;
+ num_error = 0;
+
+ printf("Starting incremental tests.\n");
+ printf("Note: quotes and backslashes seen in the output here are literal values passed\n");
+ printf(" to the parse functions. e.g. this is 4 characters: \"\\f\"\n");
+
+ string_to_parse = "{ \"foo"; /* } */
+ printf("json_tokener_parse(%s) ... ", string_to_parse);
+ new_obj = json_tokener_parse(string_to_parse);
+ if (new_obj == NULL) printf("got error as expected\n");
+
+ /* test incremental parsing in various forms */
+ tok = json_tokener_new();
+ for (ii = 0; incremental_steps[ii].string_to_parse != NULL; ii++)
+ {
+ int this_step_ok = 0;
+ struct incremental_step *step = &incremental_steps[ii];
+ int length = step->length;
+ int expected_char_offset = step->char_offset;
+
+ if (step->reset_tokener & 2)
+ json_tokener_set_flags(tok, JSON_TOKENER_STRICT);
+ else
+ json_tokener_set_flags(tok, 0);
+
+ if (length == -1)
+ length = strlen(step->string_to_parse);
+ if (expected_char_offset == -1)
+ expected_char_offset = length;
+
+ printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ",
+ step->string_to_parse, length);
+ new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length);
+
+ jerr = json_tokener_get_error(tok);
+ if (step->expected_error != json_tokener_success)
+ {
+ if (new_obj != NULL)
+ printf("ERROR: invalid object returned: %s\n",
+ json_object_to_json_string(new_obj));
+ else if (jerr != step->expected_error)
+ printf("ERROR: got wrong error: %s\n",
+ json_tokener_error_desc(jerr));
+ else if (tok->char_offset != expected_char_offset)
+ printf("ERROR: wrong char_offset %d != expected %d\n",
+ tok->char_offset,
+ expected_char_offset);
+ else
+ {
+ printf("OK: got correct error: %s\n", json_tokener_error_desc(jerr));
+ this_step_ok = 1;
+ }
+ }
+ else
+ {
+ if (new_obj == NULL)
+ printf("ERROR: expected valid object, instead: %s\n",
+ json_tokener_error_desc(jerr));
+ else if (tok->char_offset != expected_char_offset)
+ printf("ERROR: wrong char_offset %d != expected %d\n",
+ tok->char_offset,
+ expected_char_offset);
+ else
+ {
+ printf("OK: got object of type [%s]: %s\n",
+ json_type_to_name(json_object_get_type(new_obj)),
+ json_object_to_json_string(new_obj));
+ this_step_ok = 1;
+ }
+ }
+
+ if (new_obj)
+ json_object_put(new_obj);
+
+ if (step->reset_tokener & 1)
+ json_tokener_reset(tok);
+
+ if (this_step_ok)
+ num_ok++;
+ else
+ num_error++;
+ }
+
+ json_tokener_free(tok);
+
+ printf("End Incremental Tests OK=%d ERROR=%d\n", num_ok, num_error);
+
+ return;
+}
diff --git a/json-c/src/tests/test_parse.expected b/json-c/src/tests/test_parse.expected
new file mode 100644
index 0000000..bb76db2
--- /dev/null
+++ b/json-c/src/tests/test_parse.expected
@@ -0,0 +1,70 @@
+new_obj.to_string()="\u0003"
+new_obj.to_string()="foo"
+new_obj.to_string()="foo"
+new_obj.to_string()="ABC"
+new_obj.to_string()=null
+new_obj.to_string()=NaN
+new_obj.to_string()=null
+new_obj.to_string()=null
+new_obj.to_string()=null
+new_obj.to_string()=Infinity
+new_obj.to_string()=Infinity
+new_obj.to_string()=-Infinity
+new_obj.to_string()=-Infinity
+new_obj.to_string()=true
+new_obj.to_string()=12
+new_obj.to_string()=12.3
+new_obj.to_string()=null
+new_obj.to_string()=null
+new_obj.to_string()={ "FoO": -12.3E512 }
+new_obj.to_string()=null
+new_obj.to_string()=[ "\n" ]
+new_obj.to_string()=[ "\nabc\n" ]
+new_obj.to_string()=[ null ]
+new_obj.to_string()=[ ]
+new_obj.to_string()=[ false ]
+new_obj.to_string()=[ "abc", null, "def", 12 ]
+new_obj.to_string()={ }
+new_obj.to_string()={ "foo": "bar" }
+new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true }
+new_obj.to_string()={ "foo": [ null, "foo" ] }
+new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] }
+==================================
+json_tokener_parse_versbose() OK
+==================================
+Starting incremental tests.
+Note: quotes and backslashes seen in the output here are literal values passed
+ to the parse functions. e.g. this is 4 characters: "\f"
+json_tokener_parse({ "foo) ... got error as expected
+json_tokener_parse_ex(tok, { "foo": 123 }, 14) ... OK: got object of type [object]: { "foo": 123 }
+json_tokener_parse_ex(tok, { "foo": 456 }, 14) ... OK: got object of type [object]: { "foo": 456 }
+json_tokener_parse_ex(tok, { "foo": 789 }, 14) ... OK: got object of type [object]: { "foo": 789 }
+json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, ":13}} , 6) ... OK: got object of type [object]: { "foo": { "bar": 13 } }
+json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, : "bar"} , 8) ... OK: got correct error: unexpected character
+json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, ":13}}XXXX , 10) ... OK: got object of type [object]: { "foo": { "bar": 13 } }
+json_tokener_parse_ex(tok, XXXX , 4) ... OK: got correct error: unexpected character
+json_tokener_parse_ex(tok, {"x": 123 }"X", 14) ... OK: got object of type [object]: { "x": 123 }
+json_tokener_parse_ex(tok, "Y" , 3) ... OK: got object of type [string]: "Y"
+json_tokener_parse_ex(tok, 1 , 1) ... OK: got correct error: continue
+json_tokener_parse_ex(tok, 2 , 2) ... OK: got object of type [int]: 12
+json_tokener_parse_ex(tok, 2015-01-15 , 10) ... OK: got correct error: number expected
+json_tokener_parse_ex(tok, "blue" , 6) ... OK: got object of type [string]: "blue"
+json_tokener_parse_ex(tok, "\"" , 4) ... OK: got object of type [string]: "\""
+json_tokener_parse_ex(tok, "\\" , 4) ... OK: got object of type [string]: "\\"
+json_tokener_parse_ex(tok, "\b" , 4) ... OK: got object of type [string]: "\b"
+json_tokener_parse_ex(tok, "\f" , 4) ... OK: got object of type [string]: "\f"
+json_tokener_parse_ex(tok, "\n" , 4) ... OK: got object of type [string]: "\n"
+json_tokener_parse_ex(tok, "\r" , 4) ... OK: got object of type [string]: "\r"
+json_tokener_parse_ex(tok, "\t" , 4) ... OK: got object of type [string]: "\t"
+json_tokener_parse_ex(tok, [1,2,3] , 7) ... OK: got object of type [array]: [ 1, 2, 3 ]
+json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array]: [ 1, 2, 3 ]
+json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character
+json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got correct error: unexpected character
+json_tokener_parse_ex(tok, {"a":1,} , 8) ... OK: got correct error: unexpected character
+End Incremental Tests OK=30 ERROR=0
+==================================
diff --git a/json-c/src/tests/test_parse.test b/json-c/src/tests/test_parse.test
new file mode 100644
index 0000000..719a3ad
--- /dev/null
+++ b/json-c/src/tests/test_parse.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_parse
+exit $?
diff --git a/json-c/src/tests/test_parse_int64.c b/json-c/src/tests/test_parse_int64.c
new file mode 100644
index 0000000..dfcdae0
--- /dev/null
+++ b/json-c/src/tests/test_parse_int64.c
@@ -0,0 +1,115 @@
+
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+#include "json_inttypes.h"
+#include "json_util.h"
+
+void checkit(const char *buf)
+{
+ int64_t cint64 = -666;
+
+ int retval = json_parse_int64(buf, &cint64);
+ printf("buf=%s parseit=%d, value=%" PRId64 " \n", buf, retval, cint64);
+}
+
+/**
+ * This test calls json_parse_int64 with a variety of different strings.
+ * It's purpose is to ensure that the results are consistent across all
+ * different environments that it might be executed in.
+ *
+ * This always exits with a 0 exit value. The output should be compared
+ * against previously saved expected output.
+ */
+int main()
+{
+ char buf[100];
+
+ checkit("x");
+
+ checkit("0");
+ checkit("-0");
+
+ checkit("00000000");
+ checkit("-00000000");
+
+ checkit("1");
+
+ strcpy(buf, "2147483647"); // aka INT32_MAX
+ checkit(buf);
+
+ strcpy(buf, "-1");
+ checkit(buf);
+
+ strcpy(buf, " -1");
+ checkit(buf);
+
+ strcpy(buf, "00001234");
+ checkit(buf);
+
+ strcpy(buf, "0001234x");
+ checkit(buf);
+
+ strcpy(buf, "-00001234");
+ checkit(buf);
+
+ strcpy(buf, "-00001234x");
+ checkit(buf);
+
+ strcpy(buf, "4294967295"); // aka UINT32_MAX
+
+ sprintf(buf, "4294967296"); // aka UINT32_MAX + 1
+
+ strcpy(buf, "21474836470"); // INT32_MAX * 10
+ checkit(buf);
+
+ strcpy(buf, "31474836470"); // INT32_MAX * 10 + a bunch
+ checkit(buf);
+
+ strcpy(buf, "-2147483647"); // INT32_MIN + 1
+ checkit(buf);
+
+ strcpy(buf, "-2147483648"); // INT32_MIN
+ checkit(buf);
+
+ strcpy(buf, "-2147483649"); // INT32_MIN - 1
+ checkit(buf);
+
+ strcpy(buf, "-21474836480"); // INT32_MIN * 10
+ checkit(buf);
+
+ strcpy(buf, "9223372036854775806"); // INT64_MAX - 1
+ checkit(buf);
+
+ strcpy(buf, "9223372036854775807"); // INT64_MAX
+ checkit(buf);
+
+ strcpy(buf, "9223372036854775808"); // INT64_MAX + 1
+ checkit(buf);
+
+ strcpy(buf, "-9223372036854775808"); // INT64_MIN
+ checkit(buf);
+
+ strcpy(buf, "-9223372036854775809"); // INT64_MIN - 1
+ checkit(buf);
+
+ strcpy(buf, "18446744073709551614"); // UINT64_MAX - 1
+ checkit(buf);
+
+ strcpy(buf, "18446744073709551615"); // UINT64_MAX
+ checkit(buf);
+
+ strcpy(buf, "18446744073709551616"); // UINT64_MAX + 1
+ checkit(buf);
+
+ strcpy(buf, "-18446744073709551616"); // -UINT64_MAX
+ checkit(buf);
+
+ // Ensure we can still parse valid numbers after parsing out of range ones.
+ strcpy(buf, "123");
+ checkit(buf);
+
+ return 0;
+}
diff --git a/json-c/src/tests/test_parse_int64.expected b/json-c/src/tests/test_parse_int64.expected
new file mode 100644
index 0000000..1ed8f02
--- /dev/null
+++ b/json-c/src/tests/test_parse_int64.expected
@@ -0,0 +1,29 @@
+buf=x parseit=1, value=-666
+buf=0 parseit=0, value=0
+buf=-0 parseit=0, value=0
+buf=00000000 parseit=0, value=0
+buf=-00000000 parseit=0, value=0
+buf=1 parseit=0, value=1
+buf=2147483647 parseit=0, value=2147483647
+buf=-1 parseit=0, value=-1
+buf= -1 parseit=0, value=-1
+buf=00001234 parseit=0, value=1234
+buf=0001234x parseit=0, value=1234
+buf=-00001234 parseit=0, value=-1234
+buf=-00001234x parseit=0, value=-1234
+buf=21474836470 parseit=0, value=21474836470
+buf=31474836470 parseit=0, value=31474836470
+buf=-2147483647 parseit=0, value=-2147483647
+buf=-2147483648 parseit=0, value=-2147483648
+buf=-2147483649 parseit=0, value=-2147483649
+buf=-21474836480 parseit=0, value=-21474836480
+buf=9223372036854775806 parseit=0, value=9223372036854775806
+buf=9223372036854775807 parseit=0, value=9223372036854775807
+buf=9223372036854775808 parseit=0, value=9223372036854775807
+buf=-9223372036854775808 parseit=0, value=-9223372036854775808
+buf=-9223372036854775809 parseit=0, value=-9223372036854775808
+buf=18446744073709551614 parseit=0, value=9223372036854775807
+buf=18446744073709551615 parseit=0, value=9223372036854775807
+buf=18446744073709551616 parseit=0, value=9223372036854775807
+buf=-18446744073709551616 parseit=0, value=-9223372036854775808
+buf=123 parseit=0, value=123
diff --git a/json-c/src/tests/test_parse_int64.test b/json-c/src/tests/test_parse_int64.test
new file mode 100644
index 0000000..556681f
--- /dev/null
+++ b/json-c/src/tests/test_parse_int64.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_parse_int64
+exit $?
diff --git a/json-c/src/tests/test_printbuf.c b/json-c/src/tests/test_printbuf.c
new file mode 100644
index 0000000..b363296
--- /dev/null
+++ b/json-c/src/tests/test_printbuf.c
@@ -0,0 +1,166 @@
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "debug.h"
+#include "printbuf.h"
+
+static void test_basic_printbuf_memset(void);
+static void test_printbuf_memset_length(void);
+
+static void test_basic_printbuf_memset()
+{
+ struct printbuf *pb;
+
+ printf("%s: starting test\n", __func__);
+ pb = printbuf_new();
+ sprintbuf(pb, "blue:%d", 1);
+ printbuf_memset(pb, -1, 'x', 52);
+ printf("Buffer contents:%.*s\n", printbuf_length(pb), pb->buf);
+ printbuf_free(pb);
+ printf("%s: end test\n", __func__);
+}
+
+static void test_printbuf_memset_length()
+{
+ struct printbuf *pb;
+
+ printf("%s: starting test\n", __func__);
+ pb = printbuf_new();
+ printbuf_memset(pb, -1, ' ', 0);
+ printbuf_memset(pb, -1, ' ', 0);
+ printbuf_memset(pb, -1, ' ', 0);
+ printbuf_memset(pb, -1, ' ', 0);
+ printbuf_memset(pb, -1, ' ', 0);
+ printf("Buffer length: %d\n", printbuf_length(pb));
+ printbuf_memset(pb, -1, ' ', 2);
+ printbuf_memset(pb, -1, ' ', 4);
+ printbuf_memset(pb, -1, ' ', 6);
+ printf("Buffer length: %d\n", printbuf_length(pb));
+ printbuf_memset(pb, -1, ' ', 6);
+ printf("Buffer length: %d\n", printbuf_length(pb));
+ printbuf_memset(pb, -1, ' ', 8);
+ printbuf_memset(pb, -1, ' ', 10);
+ printbuf_memset(pb, -1, ' ', 10);
+ printbuf_memset(pb, -1, ' ', 10);
+ printbuf_memset(pb, -1, ' ', 20);
+ printf("Buffer length: %d\n", printbuf_length(pb));
+
+ // No length change should occur
+ printbuf_memset(pb, 0, 'x', 30);
+ printf("Buffer length: %d\n", printbuf_length(pb));
+
+ // This should extend it by one.
+ printbuf_memset(pb, 0, 'x', printbuf_length(pb) + 1);
+ printf("Buffer length: %d\n", printbuf_length(pb));
+
+ printbuf_free(pb);
+ printf("%s: end test\n", __func__);
+}
+
+static void test_printbuf_memappend(int *before_resize);
+static void test_printbuf_memappend(int *before_resize)
+{
+ struct printbuf *pb;
+ int initial_size;
+
+ printf("%s: starting test\n", __func__);
+ pb = printbuf_new();
+ printf("Buffer length: %d\n", printbuf_length(pb));
+
+ initial_size = pb->size;
+
+ while(pb->size == initial_size)
+ {
+ printbuf_memappend_fast(pb, "x", 1);
+ }
+ *before_resize = printbuf_length(pb) - 1;
+ printf("Appended %d bytes for resize: [%s]\n", *before_resize + 1, pb->buf);
+
+ printbuf_reset(pb);
+ printbuf_memappend_fast(pb, "bluexyz123", 3);
+ printf("Partial append: %d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ char with_nulls[] = { 'a', 'b', '\0', 'c' };
+ printbuf_reset(pb);
+ printbuf_memappend_fast(pb, with_nulls, (int)sizeof(with_nulls));
+ printf("With embedded \\0 character: %d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ printbuf_free(pb);
+ pb = printbuf_new();
+ char *data = malloc(*before_resize);
+ memset(data, 'X', *before_resize);
+ printbuf_memappend_fast(pb, data, *before_resize);
+ printf("Append to just before resize: %d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ free(data);
+ printbuf_free(pb);
+
+ pb = printbuf_new();
+ data = malloc(*before_resize + 1);
+ memset(data, 'X', *before_resize + 1);
+ printbuf_memappend_fast(pb, data, *before_resize + 1);
+ printf("Append to just after resize: %d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ free(data);
+
+ printbuf_free(pb);
+ printf("%s: end test\n", __func__);
+}
+
+static void test_sprintbuf(int before_resize);
+static void test_sprintbuf(int before_resize)
+{
+ struct printbuf *pb;
+
+ printf("%s: starting test\n", __func__);
+ pb = printbuf_new();
+ printf("Buffer length: %d\n", printbuf_length(pb));
+
+ char *data = malloc(before_resize + 1 + 1);
+ memset(data, 'X', before_resize + 1 + 1);
+ data[before_resize + 1] = '\0';
+ sprintbuf(pb, "%s", data);
+ free(data);
+ printf("sprintbuf to just after resize(%d+1): %d, [%s], strlen(buf)=%d\n", before_resize, printbuf_length(pb), pb->buf, (int)strlen(pb->buf));
+
+ printbuf_reset(pb);
+ sprintbuf(pb, "plain");
+ printf("%d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ sprintbuf(pb, "%d", 1);
+ printf("%d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ sprintbuf(pb, "%d", INT_MAX);
+ printf("%d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ sprintbuf(pb, "%d", INT_MIN);
+ printf("%d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ sprintbuf(pb, "%s", "%s");
+ printf("%d, [%s]\n", printbuf_length(pb), pb->buf);
+
+ printbuf_free(pb);
+ printf("%s: end test\n", __func__);
+}
+
+int main(int argc, char **argv)
+{
+ int before_resize = 0;
+
+ mc_set_debug(1);
+
+ test_basic_printbuf_memset();
+ printf("========================================\n");
+ test_printbuf_memset_length();
+ printf("========================================\n");
+ test_printbuf_memappend(&before_resize);
+ printf("========================================\n");
+ test_sprintbuf(before_resize);
+ printf("========================================\n");
+
+ return 0;
+}
diff --git a/json-c/src/tests/test_printbuf.expected b/json-c/src/tests/test_printbuf.expected
new file mode 100644
index 0000000..ec69095
--- /dev/null
+++ b/json-c/src/tests/test_printbuf.expected
@@ -0,0 +1,32 @@
+test_basic_printbuf_memset: starting test
+Buffer contents:blue:1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+test_basic_printbuf_memset: end test
+========================================
+test_printbuf_memset_length: starting test
+Buffer length: 0
+Buffer length: 12
+Buffer length: 18
+Buffer length: 76
+Buffer length: 76
+Buffer length: 77
+test_printbuf_memset_length: end test
+========================================
+test_printbuf_memappend: starting test
+Buffer length: 0
+Appended 32 bytes for resize: [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
+Partial append: 3, [blu]
+With embedded \0 character: 4, [ab]
+Append to just before resize: 31, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]
+Append to just after resize: 32, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]
+test_printbuf_memappend: end test
+========================================
+test_sprintbuf: starting test
+Buffer length: 0
+sprintbuf to just after resize(31+1): 32, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX], strlen(buf)=32
+5, [plain]
+6, [plain1]
+16, [plain12147483647]
+27, [plain12147483647-2147483648]
+29, [plain12147483647-2147483648%s]
+test_sprintbuf: end test
+========================================
diff --git a/json-c/src/tests/test_printbuf.test b/json-c/src/tests/test_printbuf.test
new file mode 100644
index 0000000..8da4fb5
--- /dev/null
+++ b/json-c/src/tests/test_printbuf.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_printbuf
+exit $?
diff --git a/json-c/src/tests/test_set_serializer.c b/json-c/src/tests/test_set_serializer.c
new file mode 100644
index 0000000..e79b00d
--- /dev/null
+++ b/json-c/src/tests/test_set_serializer.c
@@ -0,0 +1,71 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "json.h"
+#include "printbuf.h"
+
+struct myinfo {
+ int value;
+};
+
+static int freeit_was_called = 0;
+static void freeit(json_object *jso, void *userdata)
+{
+ struct myinfo *info = userdata;
+ printf("freeit, value=%d\n", info->value);
+ // Don't actually free anything here, the userdata is stack allocated.
+ freeit_was_called = 1;
+}
+static int custom_serializer(struct json_object *o,
+ struct printbuf *pb,
+ int level,
+ int flags)
+{
+ sprintbuf(pb, "Custom Output");
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ json_object *my_object;
+
+ MC_SET_DEBUG(1);
+
+ printf("Test setting, then resetting a custom serializer:\n");
+ my_object = json_object_new_object();
+ json_object_object_add(my_object, "abc", json_object_new_int(12));
+ json_object_object_add(my_object, "foo", json_object_new_string("bar"));
+
+ printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object));
+
+ struct myinfo userdata = { .value = 123 };
+ json_object_set_serializer(my_object, custom_serializer, &userdata, freeit);
+
+ printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object));
+
+ printf("Next line of output should be from the custom freeit function:\n");
+ freeit_was_called = 0;
+ json_object_set_serializer(my_object, NULL, NULL, NULL);
+ assert(freeit_was_called);
+
+ printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object));
+
+ json_object_put(my_object);
+
+ // ============================================
+
+ my_object = json_object_new_object();
+ printf("Check that the custom serializer isn't free'd until the last json_object_put:\n");
+ json_object_set_serializer(my_object, custom_serializer, &userdata, freeit);
+ json_object_get(my_object);
+ json_object_put(my_object);
+ printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object));
+ printf("Next line of output should be from the custom freeit function:\n");
+
+ freeit_was_called = 0;
+ json_object_put(my_object);
+ assert(freeit_was_called);
+
+ return 0;
+}
diff --git a/json-c/src/tests/test_set_serializer.expected b/json-c/src/tests/test_set_serializer.expected
new file mode 100644
index 0000000..f5d3747
--- /dev/null
+++ b/json-c/src/tests/test_set_serializer.expected
@@ -0,0 +1,10 @@
+Test setting, then resetting a custom serializer:
+my_object.to_string(standard)={ "abc": 12, "foo": "bar" }
+my_object.to_string(custom serializer)=Custom Output
+Next line of output should be from the custom freeit function:
+freeit, value=123
+my_object.to_string(standard)={ "abc": 12, "foo": "bar" }
+Check that the custom serializer isn't free'd until the last json_object_put:
+my_object.to_string(custom serializer)=Custom Output
+Next line of output should be from the custom freeit function:
+freeit, value=123
diff --git a/json-c/src/tests/test_set_serializer.test b/json-c/src/tests/test_set_serializer.test
new file mode 100644
index 0000000..0034183
--- /dev/null
+++ b/json-c/src/tests/test_set_serializer.test
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Common definitions
+if test -z "$srcdir"; then
+ srcdir="${0%/*}"
+ test "$srcdir" = "$0" && srcdir=.
+ test -z "$srcdir" && srcdir=.
+fi
+. "$srcdir/test-defs.sh"
+
+run_output_test test_set_serializer
+exit $?
diff --git a/libmad/libmad.vcxproj b/libcurl/libcurl.vcxproj
index 2a8de58..98d529d 100644
--- a/libmad/libmad.vcxproj
+++ b/libcurl/libcurl.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -10,9 +10,23 @@
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\include\curl\curl.h" />
+ <ClInclude Include="src\include\curl\curlbuild.h" />
+ <ClInclude Include="src\include\curl\curlrules.h" />
+ <ClInclude Include="src\include\curl\curlver.h" />
+ <ClInclude Include="src\include\curl\easy.h" />
+ <ClInclude Include="src\include\curl\mprintf.h" />
+ <ClInclude Include="src\include\curl\multi.h" />
+ <ClInclude Include="src\include\curl\stdcheaders.h" />
+ <ClInclude Include="src\include\curl\typecheck-gcc.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\libcurl_unified.c" />
+ </ItemGroup>
<PropertyGroup Label="Globals">
- <ProjectGuid>{7DDFB46B-0754-450D-9A7A-4B982E40367D}</ProjectGuid>
- <RootNamespace>libmad</RootNamespace>
+ <ProjectGuid>{B69D7658-2A3F-4BB5-9A7E-4546B8551EC0}</ProjectGuid>
+ <RootNamespace>libcurl</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -20,12 +34,12 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v110_xp</PlatformToolset>
+ <PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
- <PlatformToolset>v110_xp</PlatformToolset>
+ <PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -55,8 +69,8 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>$(ProjectDir)configured\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;FPM_INTEL;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)src\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;AO_BUILDING_LIBAO;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
@@ -71,7 +85,12 @@
<Lib>
</Lib>
<PostBuildEvent>
- <Command>xcopy "$(ProjectDir)configured\mad.h" "$(SolutionDir)build\temp\include\" /I /Y /D
+ <Command>@echo off
+set curl_headers=curl.h,curlbuild.h,curlrules.h,curlver.h,easy.h,mprintf.h,multi.h,stdcheaders.h,typecheck-gcc.h
+
+for %%a in ("%curl_headers:,=" "%") do (
+ xcopy "$(ProjectDir)src\include\curl\%%a" "$(SolutionDir)build\temp\include\curl\" /I /Y /D
+)
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
@@ -79,8 +98,8 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <AdditionalIncludeDirectories>$(ProjectDir)configured\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;FPM_INTEL;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)src\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;AO_BUILDING_LIBAO;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -95,46 +114,15 @@
<Lib>
</Lib>
<PostBuildEvent>
- <Command>xcopy "$(ProjectDir)configured\mad.h" "$(SolutionDir)build\temp\include\" /I /Y /D
+ <Command>@echo off
+set curl_headers=curl.h,curlbuild.h,curlrules.h,curlver.h,easy.h,mprintf.h,multi.h,stdcheaders.h,typecheck-gcc.h
+
+for %%a in ("%curl_headers:,=" "%") do (
+ xcopy "$(ProjectDir)src\include\curl\%%a" "$(SolutionDir)build\temp\include\curl\" /I /Y /D
+)
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="src\bit.c" />
- <ClCompile Include="src\decoder.c" />
- <ClCompile Include="src\fixed.c" />
- <ClCompile Include="src\frame.c" />
- <ClCompile Include="src\huffman.c" />
- <ClCompile Include="src\layer12.c" />
- <ClCompile Include="src\layer3.c" />
- <ClCompile Include="src\stream.c" />
- <ClCompile Include="src\synth.c" />
- <ClCompile Include="src\timer.c" />
- <ClCompile Include="src\version.c" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\bit.h" />
- <ClInclude Include="configured\config.h" />
- <ClInclude Include="src\decoder.h" />
- <ClInclude Include="src\fixed.h" />
- <ClInclude Include="src\frame.h" />
- <ClInclude Include="src\global.h" />
- <ClInclude Include="src\huffman.h" />
- <ClInclude Include="src\layer12.h" />
- <ClInclude Include="src\layer3.h" />
- <ClInclude Include="configured\mad.h" />
- <ClInclude Include="src\stream.h" />
- <ClInclude Include="src\synth.h" />
- <ClInclude Include="src\timer.h" />
- <ClInclude Include="src\version.h" />
- </ItemGroup>
- <ItemGroup>
- <None Include="src\D.dat" />
- <None Include="src\imdct_s.dat" />
- <None Include="src\qc_table.dat" />
- <None Include="src\rq_table.dat" />
- <None Include="src\sf_table.dat" />
- </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/libcurl/libcurl.vcxproj.filters b/libcurl/libcurl.vcxproj.filters
new file mode 100644
index 0000000..1ad06e9
--- /dev/null
+++ b/libcurl/libcurl.vcxproj.filters
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Include">
+ <UniqueIdentifier>{2a0877fb-7db4-436f-967f-0784ed77c701}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Include\curl">
+ <UniqueIdentifier>{16157074-e564-417f-9c0b-a94b51acc7a7}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\include\curl\curl.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\curlbuild.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\curlrules.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\curlver.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\easy.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\mprintf.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\multi.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\stdcheaders.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ <ClInclude Include="src\include\curl\typecheck-gcc.h">
+ <Filter>Include\curl</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\libcurl_unified.c">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/libcurl/src/include/curl/curl.h b/libcurl/src/include/curl/curl.h
new file mode 100644
index 0000000..07ff831
--- /dev/null
+++ b/libcurl/src/include/curl/curl.h
@@ -0,0 +1,2364 @@
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * If you have libcurl problems, all docs and details are found here:
+ * http://curl.haxx.se/libcurl/
+ *
+ * curl-library mailing list subscription and unsubscription web interface:
+ * http://cool.haxx.se/mailman/listinfo/curl-library/
+ */
+
+#include "curlver.h" /* libcurl version defines */
+#include "curlbuild.h" /* libcurl build definitions */
+#include "curlrules.h" /* libcurl rules enforcement */
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && \
+ !defined(WIN32) && !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+/* Needed for __FreeBSD_version symbol definition */
+#include <osreldate.h>
+#endif
+
+/* The include stuff here below is mainly for time_t! */
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || defined(__LWIP_OPT_H__))
+/* The check above prevents the winsock2 inclusion if winsock.h already was
+ included, since they can't co-exist without problems */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#endif
+
+/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+ libc5-based Linux systems. Only include it on systems that are known to
+ require it! */
+#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
+ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+#include <sys/select.h>
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+#include <sys/socket.h>
+#endif
+
+#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+#include <sys/time.h>
+#endif
+
+#ifdef __BEOS__
+#include <support/SupportDefs.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void CURL;
+
+/*
+ * libcurl external API function linkage decorations.
+ */
+
+#ifdef CURL_STATICLIB
+# define CURL_EXTERN
+#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
+# if defined(BUILDING_LIBCURL)
+# define CURL_EXTERN __declspec(dllexport)
+# else
+# define CURL_EXTERN __declspec(dllimport)
+# endif
+#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
+# define CURL_EXTERN CURL_EXTERN_SYMBOL
+#else
+# define CURL_EXTERN
+#endif
+
+#ifndef curl_socket_typedef
+/* socket typedef */
+#if defined(WIN32) && !defined(__LWIP_OPT_H__)
+typedef SOCKET curl_socket_t;
+#define CURL_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int curl_socket_t;
+#define CURL_SOCKET_BAD -1
+#endif
+#define curl_socket_typedef
+#endif /* curl_socket_typedef */
+
+struct curl_httppost {
+ struct curl_httppost *next; /* next entry in the list */
+ char *name; /* pointer to allocated name */
+ long namelength; /* length of name length */
+ char *contents; /* pointer to allocated data contents */
+ long contentslength; /* length of contents field */
+ char *buffer; /* pointer to allocated buffer contents */
+ long bufferlength; /* length of buffer field */
+ char *contenttype; /* Content-Type */
+ struct curl_slist* contentheader; /* list of extra headers for this form */
+ struct curl_httppost *more; /* if one field name has more than one
+ file, this link should link to following
+ files */
+ long flags; /* as defined below */
+#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */
+#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */
+#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer
+ do not free in formfree */
+#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
+ do not free in formfree */
+#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */
+#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */
+#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the
+ regular read callback to get the data
+ and pass the given pointer as custom
+ pointer */
+
+ char *showfilename; /* The file name to show. If not set, the
+ actual file name will be used (if this
+ is a file part) */
+ void *userp; /* custom pointer used for
+ HTTPPOST_CALLBACK posts */
+};
+
+/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
+ deprecated but was the only choice up until 7.31.0 */
+typedef int (*curl_progress_callback)(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow);
+
+/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
+ 7.32.0, it avoids floating point and provides more detailed information. */
+typedef int (*curl_xferinfo_callback)(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow);
+
+#ifndef CURL_MAX_WRITE_SIZE
+ /* Tests have proven that 20K is a very bad buffer size for uploads on
+ Windows, while 16K for some odd reason performed a lot better.
+ We do the ifndef check to allow this value to easier be changed at build
+ time for those who feel adventurous. The practical minimum is about
+ 400 bytes since libcurl uses a buffer of this size as a scratch area
+ (unrelated to network send operations). */
+#define CURL_MAX_WRITE_SIZE 16384
+#endif
+
+#ifndef CURL_MAX_HTTP_HEADER
+/* The only reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause reallocs
+ infinitely */
+#define CURL_MAX_HTTP_HEADER (100*1024)
+#endif
+
+/* This is a magic return code for the write callback that, when returned,
+ will signal libcurl to pause receiving on the current transfer. */
+#define CURL_WRITEFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_write_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *outstream);
+
+
+
+/* enumeration of file types */
+typedef enum {
+ CURLFILETYPE_FILE = 0,
+ CURLFILETYPE_DIRECTORY,
+ CURLFILETYPE_SYMLINK,
+ CURLFILETYPE_DEVICE_BLOCK,
+ CURLFILETYPE_DEVICE_CHAR,
+ CURLFILETYPE_NAMEDPIPE,
+ CURLFILETYPE_SOCKET,
+ CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
+
+ CURLFILETYPE_UNKNOWN /* should never occur */
+} curlfiletype;
+
+#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0)
+#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1)
+#define CURLFINFOFLAG_KNOWN_TIME (1<<2)
+#define CURLFINFOFLAG_KNOWN_PERM (1<<3)
+#define CURLFINFOFLAG_KNOWN_UID (1<<4)
+#define CURLFINFOFLAG_KNOWN_GID (1<<5)
+#define CURLFINFOFLAG_KNOWN_SIZE (1<<6)
+#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7)
+
+/* Content of this structure depends on information which is known and is
+ achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
+ page for callbacks returning this structure -- some fields are mandatory,
+ some others are optional. The FLAG field has special meaning. */
+struct curl_fileinfo {
+ char *filename;
+ curlfiletype filetype;
+ time_t time;
+ unsigned int perm;
+ int uid;
+ int gid;
+ curl_off_t size;
+ long int hardlinks;
+
+ struct {
+ /* If some of these fields is not NULL, it is a pointer to b_data. */
+ char *time;
+ char *perm;
+ char *user;
+ char *group;
+ char *target; /* pointer to the target filename of a symlink */
+ } strings;
+
+ unsigned int flags;
+
+ /* used internally */
+ char * b_data;
+ size_t b_size;
+ size_t b_used;
+};
+
+/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
+#define CURL_CHUNK_BGN_FUNC_OK 0
+#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */
+#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */
+
+/* if splitting of data transfer is enabled, this callback is called before
+ download of an individual chunk started. Note that parameter "remains" works
+ only for FTP wildcard downloading (for now), otherwise is not used */
+typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
+ void *ptr,
+ int remains);
+
+/* return codes for CURLOPT_CHUNK_END_FUNCTION */
+#define CURL_CHUNK_END_FUNC_OK 0
+#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */
+
+/* If splitting of data transfer is enabled this callback is called after
+ download of an individual chunk finished.
+ Note! After this callback was set then it have to be called FOR ALL chunks.
+ Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
+ This is the reason why we don't need "transfer_info" parameter in this
+ callback and we are not interested in "remains" parameter too. */
+typedef long (*curl_chunk_end_callback)(void *ptr);
+
+/* return codes for FNMATCHFUNCTION */
+#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */
+#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */
+#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */
+
+/* callback type for wildcard downloading pattern matching. If the
+ string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
+typedef int (*curl_fnmatch_callback)(void *ptr,
+ const char *pattern,
+ const char *string);
+
+/* These are the return codes for the seek callbacks */
+#define CURL_SEEKFUNC_OK 0
+#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
+#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
+ libcurl might try other means instead */
+typedef int (*curl_seek_callback)(void *instream,
+ curl_off_t offset,
+ int origin); /* 'whence' */
+
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to immediately abort the current transfer. */
+#define CURL_READFUNC_ABORT 0x10000000
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to pause sending data on the current transfer. */
+#define CURL_READFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_read_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *instream);
+
+typedef enum {
+ CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
+ CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
+ CURLSOCKTYPE_LAST /* never use */
+} curlsocktype;
+
+/* The return code from the sockopt_callback can signal information back
+ to libcurl: */
+#define CURL_SOCKOPT_OK 0
+#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
+ CURLE_ABORTED_BY_CALLBACK */
+#define CURL_SOCKOPT_ALREADY_CONNECTED 2
+
+typedef int (*curl_sockopt_callback)(void *clientp,
+ curl_socket_t curlfd,
+ curlsocktype purpose);
+
+struct curl_sockaddr {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
+ turned really ugly and painful on the systems that
+ lack this type */
+ struct sockaddr addr;
+};
+
+typedef curl_socket_t
+(*curl_opensocket_callback)(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address);
+
+typedef int
+(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
+
+typedef enum {
+ CURLIOE_OK, /* I/O operation successful */
+ CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
+ CURLIOE_FAILRESTART, /* failed to restart the read */
+ CURLIOE_LAST /* never use */
+} curlioerr;
+
+typedef enum {
+ CURLIOCMD_NOP, /* no operation */
+ CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+ CURLIOCMD_LAST /* never use */
+} curliocmd;
+
+typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+ int cmd,
+ void *clientp);
+
+/*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively. Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+typedef void *(*curl_malloc_callback)(size_t size);
+typedef void (*curl_free_callback)(void *ptr);
+typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+typedef char *(*curl_strdup_callback)(const char *str);
+typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
+/* the kind of data that is passed to information_callback*/
+typedef enum {
+ CURLINFO_TEXT = 0,
+ CURLINFO_HEADER_IN, /* 1 */
+ CURLINFO_HEADER_OUT, /* 2 */
+ CURLINFO_DATA_IN, /* 3 */
+ CURLINFO_DATA_OUT, /* 4 */
+ CURLINFO_SSL_DATA_IN, /* 5 */
+ CURLINFO_SSL_DATA_OUT, /* 6 */
+ CURLINFO_END
+} curl_infotype;
+
+typedef int (*curl_debug_callback)
+ (CURL *handle, /* the handle/transfer this concerns */
+ curl_infotype type, /* what kind of data */
+ char *data, /* points to the data */
+ size_t size, /* size of the data pointed to */
+ void *userptr); /* whatever the user please */
+
+/* All possible error codes from all sorts of curl functions. Future versions
+ may return other values, stay prepared.
+
+ Always add new return codes last. Never *EVER* remove any. The return
+ codes must remain the same!
+ */
+
+typedef enum {
+ CURLE_OK = 0,
+ CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
+ CURLE_FAILED_INIT, /* 2 */
+ CURLE_URL_MALFORMAT, /* 3 */
+ CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
+ 7.17.0, reused in April 2011 for 7.21.5] */
+ CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
+ CURLE_COULDNT_RESOLVE_HOST, /* 6 */
+ CURLE_COULDNT_CONNECT, /* 7 */
+ CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
+ CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
+ due to lack of access - when login fails
+ this is not returned. */
+ CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for
+ 7.15.4, reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
+ CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
+ CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
+ CURLE_FTP_CANT_GET_HOST, /* 15 */
+ CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in July 2014 for 7.38.0] */
+ CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
+ CURLE_PARTIAL_FILE, /* 18 */
+ CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
+ CURLE_OBSOLETE20, /* 20 - NOT USED */
+ CURLE_QUOTE_ERROR, /* 21 - quote command failure */
+ CURLE_HTTP_RETURNED_ERROR, /* 22 */
+ CURLE_WRITE_ERROR, /* 23 */
+ CURLE_OBSOLETE24, /* 24 - NOT USED */
+ CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */
+ CURLE_READ_ERROR, /* 26 - couldn't open/read from file */
+ CURLE_OUT_OF_MEMORY, /* 27 */
+ /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+ instead of a memory allocation error if CURL_DOES_CONVERSIONS
+ is defined
+ */
+ CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */
+ CURLE_OBSOLETE29, /* 29 - NOT USED */
+ CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
+ CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
+ CURLE_OBSOLETE32, /* 32 - NOT USED */
+ CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
+ CURLE_HTTP_POST_ERROR, /* 34 */
+ CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
+ CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
+ CURLE_FILE_COULDNT_READ_FILE, /* 37 */
+ CURLE_LDAP_CANNOT_BIND, /* 38 */
+ CURLE_LDAP_SEARCH_FAILED, /* 39 */
+ CURLE_OBSOLETE40, /* 40 - NOT USED */
+ CURLE_FUNCTION_NOT_FOUND, /* 41 */
+ CURLE_ABORTED_BY_CALLBACK, /* 42 */
+ CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
+ CURLE_OBSOLETE44, /* 44 - NOT USED */
+ CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
+ CURLE_OBSOLETE46, /* 46 - NOT USED */
+ CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
+ CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
+ CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
+ CURLE_OBSOLETE50, /* 50 - NOT USED */
+ CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
+ wasn't verified fine */
+ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
+ CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
+ CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
+ default */
+ CURLE_SEND_ERROR, /* 55 - failed sending network data */
+ CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
+ CURLE_OBSOLETE57, /* 57 - NOT IN USE */
+ CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
+ CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
+ CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
+ CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
+ CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
+ CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
+ CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
+ CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
+ that failed */
+ CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
+ CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
+ accepted and we failed to login */
+ CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
+ CURLE_TFTP_PERM, /* 69 - permission problem on server */
+ CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */
+ CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
+ CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
+ CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
+ CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
+ CURLE_CONV_FAILED, /* 75 - conversion failed */
+ CURLE_CONV_REQD, /* 76 - caller must register conversion
+ callbacks using curl_easy_setopt options
+ CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ CURLOPT_CONV_TO_NETWORK_FUNCTION, and
+ CURLOPT_CONV_FROM_UTF8_FUNCTION */
+ CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
+ or wrong format */
+ CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
+ CURLE_SSH, /* 79 - error from the SSH layer, somewhat
+ generic so the error message will be of
+ interest when this has happened */
+
+ CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
+ connection */
+ CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
+ wait till it's ready and try again (Added
+ in 7.18.2) */
+ CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
+ wrong format (Added in 7.19.0) */
+ CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
+ 7.19.0) */
+ CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
+ CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
+ CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
+ CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
+ CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
+ CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
+ session will be queued */
+ CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
+ match */
+ CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
+ CURL_LAST /* never use! */
+} CURLcode;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Previously obsolete error code re-used in 7.38.0 */
+#define CURLE_OBSOLETE16 CURLE_HTTP2
+
+/* Previously obsolete error codes re-used in 7.24.0 */
+#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
+#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
+
+/* compatibility with older names */
+#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
+
+/* The following were added in 7.21.5, April 2011 */
+#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+
+/* The following were added in 7.17.1 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.17.0 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
+#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
+#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
+#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
+#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
+#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
+#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
+#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
+#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
+#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
+#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
+#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
+#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
+
+#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
+#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
+#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
+#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
+#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
+#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
+#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
+
+/* The following were added earlier */
+
+#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
+
+#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
+#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
+#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
+
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+
+/* This was the error code 50 in 7.7.3 and a few earlier versions, this
+ is no longer used by libcurl but is instead #defined here only to not
+ make programs break */
+#define CURLE_ALREADY_COMPLETE 99999
+
+/* Provide defines for really old option names */
+#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
+#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
+#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
+
+/* Since long deprecated options with no code in the lib that does anything
+ with them. */
+#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
+#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
+
+#endif /*!CURL_NO_OLDIES*/
+
+/* This prototype applies to all conversion callbacks */
+typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
+ void *ssl_ctx, /* actually an
+ OpenSSL SSL_CTX */
+ void *userptr);
+
+typedef enum {
+ CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
+ CONNECT HTTP/1.1 */
+ CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
+ HTTP/1.0 */
+ CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+ in 7.10 */
+ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+ CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
+ CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
+ host name rather than the IP address. added
+ in 7.18.0 */
+} curl_proxytype; /* this enum was added in 7.10 */
+
+/*
+ * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
+ *
+ * CURLAUTH_NONE - No HTTP authentication
+ * CURLAUTH_BASIC - HTTP Basic authentication (default)
+ * CURLAUTH_DIGEST - HTTP Digest authentication
+ * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication
+ * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
+ * CURLAUTH_NTLM - HTTP NTLM authentication
+ * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
+ * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_ONLY - Use together with a single other type to force no
+ * authentication or just that single type
+ * CURLAUTH_ANY - All fine types set
+ * CURLAUTH_ANYSAFE - All fine types except Basic
+ */
+
+#define CURLAUTH_NONE ((unsigned long)0)
+#define CURLAUTH_BASIC (((unsigned long)1)<<0)
+#define CURLAUTH_DIGEST (((unsigned long)1)<<1)
+#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2)
+/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
+#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
+#define CURLAUTH_NTLM (((unsigned long)1)<<3)
+#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
+#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
+#define CURLAUTH_ONLY (((unsigned long)1)<<31)
+#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
+#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+
+#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
+#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
+#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
+#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */
+#define CURLSSH_AUTH_HOST (1<<2) /* host key files */
+#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */
+#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */
+#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
+
+#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */
+#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
+#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */
+
+#define CURL_ERROR_SIZE 256
+
+enum curl_khtype {
+ CURLKHTYPE_UNKNOWN,
+ CURLKHTYPE_RSA1,
+ CURLKHTYPE_RSA,
+ CURLKHTYPE_DSS
+};
+
+struct curl_khkey {
+ const char *key; /* points to a zero-terminated string encoded with base64
+ if len is zero, otherwise to the "raw" data */
+ size_t len;
+ enum curl_khtype keytype;
+};
+
+/* this is the set of return values expected from the curl_sshkeycallback
+ callback */
+enum curl_khstat {
+ CURLKHSTAT_FINE_ADD_TO_FILE,
+ CURLKHSTAT_FINE,
+ CURLKHSTAT_REJECT, /* reject the connection, return an error */
+ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
+ this causes a CURLE_DEFER error but otherwise the
+ connection will be left intact etc */
+ CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
+};
+
+/* this is the set of status codes pass in to the callback */
+enum curl_khmatch {
+ CURLKHMATCH_OK, /* match */
+ CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
+ CURLKHMATCH_MISSING, /* no matching host/key found */
+ CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */
+};
+
+typedef int
+ (*curl_sshkeycallback) (CURL *easy, /* easy handle */
+ const struct curl_khkey *knownkey, /* known */
+ const struct curl_khkey *foundkey, /* found */
+ enum curl_khmatch, /* libcurl's view on the keys */
+ void *clientp); /* custom pointer passed from app */
+
+/* parameter for the CURLOPT_USE_SSL option */
+typedef enum {
+ CURLUSESSL_NONE, /* do not attempt to use SSL */
+ CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */
+ CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
+ CURLUSESSL_ALL, /* SSL for all communication or fail */
+ CURLUSESSL_LAST /* not an option, never use */
+} curl_usessl;
+
+/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
+
+/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
+ name of improving interoperability with older servers. Some SSL libraries
+ have introduced work-arounds for this flaw but those work-arounds sometimes
+ make the SSL communication fail. To regain functionality with those broken
+ servers, a user can this way allow the vulnerability back. */
+#define CURLSSLOPT_ALLOW_BEAST (1<<0)
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2009 */
+
+#define CURLFTPSSL_NONE CURLUSESSL_NONE
+#define CURLFTPSSL_TRY CURLUSESSL_TRY
+#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
+#define CURLFTPSSL_ALL CURLUSESSL_ALL
+#define CURLFTPSSL_LAST CURLUSESSL_LAST
+#define curl_ftpssl curl_usessl
+#endif /*!CURL_NO_OLDIES*/
+
+/* parameter for the CURLOPT_FTP_SSL_CCC option */
+typedef enum {
+ CURLFTPSSL_CCC_NONE, /* do not send CCC */
+ CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
+ CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */
+ CURLFTPSSL_CCC_LAST /* not an option, never use */
+} curl_ftpccc;
+
+/* parameter for the CURLOPT_FTPSSLAUTH option */
+typedef enum {
+ CURLFTPAUTH_DEFAULT, /* let libcurl decide */
+ CURLFTPAUTH_SSL, /* use "AUTH SSL" */
+ CURLFTPAUTH_TLS, /* use "AUTH TLS" */
+ CURLFTPAUTH_LAST /* not an option, never use */
+} curl_ftpauth;
+
+/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
+typedef enum {
+ CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */
+ CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD
+ again if MKD succeeded, for SFTP this does
+ similar magic */
+ CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
+ again even if MKD failed! */
+ CURLFTP_CREATE_DIR_LAST /* not an option, never use */
+} curl_ftpcreatedir;
+
+/* parameter for the CURLOPT_FTP_FILEMETHOD option */
+typedef enum {
+ CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
+ CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */
+ CURLFTPMETHOD_NOCWD, /* no CWD at all */
+ CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+ CURLFTPMETHOD_LAST /* not an option, never use */
+} curl_ftpmethod;
+
+/* bitmask defines for CURLOPT_HEADEROPT */
+#define CURLHEADER_UNIFIED 0
+#define CURLHEADER_SEPARATE (1<<0)
+
+/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+#define CURLPROTO_HTTP (1<<0)
+#define CURLPROTO_HTTPS (1<<1)
+#define CURLPROTO_FTP (1<<2)
+#define CURLPROTO_FTPS (1<<3)
+#define CURLPROTO_SCP (1<<4)
+#define CURLPROTO_SFTP (1<<5)
+#define CURLPROTO_TELNET (1<<6)
+#define CURLPROTO_LDAP (1<<7)
+#define CURLPROTO_LDAPS (1<<8)
+#define CURLPROTO_DICT (1<<9)
+#define CURLPROTO_FILE (1<<10)
+#define CURLPROTO_TFTP (1<<11)
+#define CURLPROTO_IMAP (1<<12)
+#define CURLPROTO_IMAPS (1<<13)
+#define CURLPROTO_POP3 (1<<14)
+#define CURLPROTO_POP3S (1<<15)
+#define CURLPROTO_SMTP (1<<16)
+#define CURLPROTO_SMTPS (1<<17)
+#define CURLPROTO_RTSP (1<<18)
+#define CURLPROTO_RTMP (1<<19)
+#define CURLPROTO_RTMPT (1<<20)
+#define CURLPROTO_RTMPE (1<<21)
+#define CURLPROTO_RTMPTE (1<<22)
+#define CURLPROTO_RTMPS (1<<23)
+#define CURLPROTO_RTMPTS (1<<24)
+#define CURLPROTO_GOPHER (1<<25)
+#define CURLPROTO_SMB (1<<26)
+#define CURLPROTO_SMBS (1<<27)
+#define CURLPROTO_ALL (~0) /* enable everything */
+
+/* long may be 32 or 64 bits, but we should never depend on anything else
+ but 32 */
+#define CURLOPTTYPE_LONG 0
+#define CURLOPTTYPE_OBJECTPOINT 10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_OFF_T 30000
+
+/* name is uppercase CURLOPT_<name>,
+ type is one of the defined CURLOPTTYPE_<type>
+ number is unique identifier */
+#ifdef CINIT
+#undef CINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLOPT_/**/name = type + number
+#endif
+
+/*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+typedef enum {
+ /* This is the FILE * or void * the regular output should be written to. */
+ CINIT(WRITEDATA, OBJECTPOINT, 1),
+
+ /* The full URL to get/put */
+ CINIT(URL, OBJECTPOINT, 2),
+
+ /* Port number to connect to, if other than default. */
+ CINIT(PORT, LONG, 3),
+
+ /* Name of proxy to use. */
+ CINIT(PROXY, OBJECTPOINT, 4),
+
+ /* "user:password;options" to use when fetching. */
+ CINIT(USERPWD, OBJECTPOINT, 5),
+
+ /* "user:password" to use with proxy. */
+ CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
+
+ /* Range to get, specified as an ASCII string. */
+ CINIT(RANGE, OBJECTPOINT, 7),
+
+ /* not used */
+
+ /* Specified file stream to upload from (use as input): */
+ CINIT(READDATA, OBJECTPOINT, 9),
+
+ /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+ * bytes big. If this is not used, error messages go to stderr instead: */
+ CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+ /* Function that will be called to store the output (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+ /* Function that will be called to read the input (instead of fread). The
+ * parameters will use fread() syntax, make sure to follow them. */
+ CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+
+ /* Time-out the read operation after this amount of seconds */
+ CINIT(TIMEOUT, LONG, 13),
+
+ /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+ * how large the file being sent really is. That allows better error
+ * checking and better verifies that the upload was successful. -1 means
+ * unknown size.
+ *
+ * For large file support, there is also a _LARGE version of the key
+ * which takes an off_t type, allowing platforms with larger off_t
+ * sizes to handle larger files. See below for INFILESIZE_LARGE.
+ */
+ CINIT(INFILESIZE, LONG, 14),
+
+ /* POST static input fields. */
+ CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+ /* Set the referrer page (needed by some CGIs) */
+ CINIT(REFERER, OBJECTPOINT, 16),
+
+ /* Set the FTP PORT string (interface name, named or numerical IP address)
+ Use i.e '-' to use default address. */
+ CINIT(FTPPORT, OBJECTPOINT, 17),
+
+ /* Set the User-Agent string (examined by some CGIs) */
+ CINIT(USERAGENT, OBJECTPOINT, 18),
+
+ /* If the download receives less than "low speed limit" bytes/second
+ * during "low speed time" seconds, the operations is aborted.
+ * You could i.e if you have a pretty high speed connection, abort if
+ * it is less than 2000 bytes/sec during 20 seconds.
+ */
+
+ /* Set the "low speed limit" */
+ CINIT(LOW_SPEED_LIMIT, LONG, 19),
+
+ /* Set the "low speed time" */
+ CINIT(LOW_SPEED_TIME, LONG, 20),
+
+ /* Set the continuation offset.
+ *
+ * Note there is also a _LARGE version of this key which uses
+ * off_t types, allowing for large file offsets on platforms which
+ * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE.
+ */
+ CINIT(RESUME_FROM, LONG, 21),
+
+ /* Set cookie in request: */
+ CINIT(COOKIE, OBJECTPOINT, 22),
+
+ /* This points to a linked list of headers, struct curl_slist kind. This
+ list is also used for RTSP (in spite of its name) */
+ CINIT(HTTPHEADER, OBJECTPOINT, 23),
+
+ /* This points to a linked list of post entries, struct curl_httppost */
+ CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+ /* name of the file keeping your private SSL-certificate */
+ CINIT(SSLCERT, OBJECTPOINT, 25),
+
+ /* password for the SSL or SSH private key */
+ CINIT(KEYPASSWD, OBJECTPOINT, 26),
+
+ /* send TYPE parameter? */
+ CINIT(CRLF, LONG, 27),
+
+ /* send linked-list of QUOTE commands */
+ CINIT(QUOTE, OBJECTPOINT, 28),
+
+ /* send FILE * or void * to store headers to, if you use a callback it
+ is simply passed to the callback unmodified */
+ CINIT(HEADERDATA, OBJECTPOINT, 29),
+
+ /* point to a file to read the initial cookies from, also enables
+ "cookie awareness" */
+ CINIT(COOKIEFILE, OBJECTPOINT, 31),
+
+ /* What version to specifically try to use.
+ See CURL_SSLVERSION defines below. */
+ CINIT(SSLVERSION, LONG, 32),
+
+ /* What kind of HTTP time condition to use, see defines */
+ CINIT(TIMECONDITION, LONG, 33),
+
+ /* Time to use with the above condition. Specified in number of seconds
+ since 1 Jan 1970 */
+ CINIT(TIMEVALUE, LONG, 34),
+
+ /* 35 = OBSOLETE */
+
+ /* Custom request, for customizing the get command like
+ HTTP: DELETE, TRACE and others
+ FTP: to use a different list command
+ */
+ CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
+
+ /* HTTP request, for odd commands like DELETE, TRACE and others */
+ CINIT(STDERR, OBJECTPOINT, 37),
+
+ /* 38 is not used */
+
+ /* send linked-list of post-transfer QUOTE commands */
+ CINIT(POSTQUOTE, OBJECTPOINT, 39),
+
+ CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+
+ CINIT(VERBOSE, LONG, 41), /* talk a lot */
+ CINIT(HEADER, LONG, 42), /* throw the header out too */
+ CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
+ CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */
+ CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */
+ CINIT(UPLOAD, LONG, 46), /* this is an upload */
+ CINIT(POST, LONG, 47), /* HTTP POST method */
+ CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */
+
+ CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */
+
+ /* Specify whether to read the user+password from the .netrc or the URL.
+ * This must be one of the CURL_NETRC_* enums below. */
+ CINIT(NETRC, LONG, 51),
+
+ CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
+
+ CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+ CINIT(PUT, LONG, 54), /* HTTP PUT */
+
+ /* 55 = OBSOLETE */
+
+ /* DEPRECATED
+ * Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_progress_callback
+ * prototype defines. */
+ CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+ /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
+ callbacks */
+ CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+
+ /* We want the referrer field set automatically when following locations */
+ CINIT(AUTOREFERER, LONG, 58),
+
+ /* Port of the proxy, can be set in the proxy string as well with:
+ "[host]:[port]" */
+ CINIT(PROXYPORT, LONG, 59),
+
+ /* size of the POST input data, if strlen() is not good to use */
+ CINIT(POSTFIELDSIZE, LONG, 60),
+
+ /* tunnel non-http operations through a HTTP proxy */
+ CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+ /* Set the interface string to use as outgoing network interface */
+ CINIT(INTERFACE, OBJECTPOINT, 62),
+
+ /* Set the krb4/5 security level, this also enables krb4/5 awareness. This
+ * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
+ * is set but doesn't match one of these, 'private' will be used. */
+ CINIT(KRBLEVEL, OBJECTPOINT, 63),
+
+ /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+ CINIT(SSL_VERIFYPEER, LONG, 64),
+
+ /* The CApath or CAfile used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAINFO, OBJECTPOINT, 65),
+
+ /* 66 = OBSOLETE */
+ /* 67 = OBSOLETE */
+
+ /* Maximum number of http redirects to follow */
+ CINIT(MAXREDIRS, LONG, 68),
+
+ /* Pass a long set to 1 to get the date of the requested document (if
+ possible)! Pass a zero to shut it off. */
+ CINIT(FILETIME, LONG, 69),
+
+ /* This points to a linked list of telnet options */
+ CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
+
+ /* Max amount of cached alive connections */
+ CINIT(MAXCONNECTS, LONG, 71),
+
+ CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+
+ /* 73 = OBSOLETE */
+
+ /* Set to explicitly use a new connection for the upcoming transfer.
+ Do not use this unless you're absolutely sure of this, as it makes the
+ operation slower and is less friendly for the network. */
+ CINIT(FRESH_CONNECT, LONG, 74),
+
+ /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+ when done. Do not use this unless you're absolutely sure of this, as it
+ makes the operation slower and is less friendly for the network. */
+ CINIT(FORBID_REUSE, LONG, 75),
+
+ /* Set to a file name that contains random data for libcurl to use to
+ seed the random engine when doing SSL connects. */
+ CINIT(RANDOM_FILE, OBJECTPOINT, 76),
+
+ /* Set to the Entropy Gathering Daemon socket pathname */
+ CINIT(EGDSOCKET, OBJECTPOINT, 77),
+
+ /* Time-out connect operations after this amount of seconds, if connects are
+ OK within this time, then fine... This only aborts the connect phase. */
+ CINIT(CONNECTTIMEOUT, LONG, 78),
+
+ /* Function that will be called to store headers (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+ /* Set this to force the HTTP request to get back to GET. Only really usable
+ if POST, PUT or a custom request have been used first.
+ */
+ CINIT(HTTPGET, LONG, 80),
+
+ /* Set if we should verify the Common name from the peer certificate in ssl
+ * handshake, set 1 to check existence, 2 to ensure that it matches the
+ * provided hostname. */
+ CINIT(SSL_VERIFYHOST, LONG, 81),
+
+ /* Specify which file name to write all known cookies in after completed
+ operation. Set file name to "-" (dash) to make it go to stdout. */
+ CINIT(COOKIEJAR, OBJECTPOINT, 82),
+
+ /* Specify which SSL ciphers to use */
+ CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
+
+ /* Specify which HTTP version to use! This must be set to one of the
+ CURL_HTTP_VERSION* enums set below. */
+ CINIT(HTTP_VERSION, LONG, 84),
+
+ /* Specifically switch on or off the FTP engine's use of the EPSV command. By
+ default, that one will always be attempted before the more traditional
+ PASV command. */
+ CINIT(FTP_USE_EPSV, LONG, 85),
+
+ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+ CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
+
+ /* name of the file keeping your private SSL-key */
+ CINIT(SSLKEY, OBJECTPOINT, 87),
+
+ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+ CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
+
+ /* crypto engine for the SSL-sub system */
+ CINIT(SSLENGINE, OBJECTPOINT, 89),
+
+ /* set the crypto engine for the SSL-sub system as default
+ the param has no meaning...
+ */
+ CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+ /* Non-zero value means to use the global dns cache */
+ CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+
+ /* DNS cache timeout */
+ CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+ /* send linked-list of pre-transfer QUOTE commands */
+ CINIT(PREQUOTE, OBJECTPOINT, 93),
+
+ /* set the debug function */
+ CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+
+ /* set the data for the debug function */
+ CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+ /* mark this as start of a cookie session */
+ CINIT(COOKIESESSION, LONG, 96),
+
+ /* The CApath directory used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAPATH, OBJECTPOINT, 97),
+
+ /* Instruct libcurl to use a smaller receive buffer */
+ CINIT(BUFFERSIZE, LONG, 98),
+
+ /* Instruct libcurl to not use any signal/alarm handlers, even when using
+ timeouts. This option is useful for multi-threaded applications.
+ See libcurl-the-guide for more background information. */
+ CINIT(NOSIGNAL, LONG, 99),
+
+ /* Provide a CURLShare for mutexing non-ts data */
+ CINIT(SHARE, OBJECTPOINT, 100),
+
+ /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+ CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+ CINIT(PROXYTYPE, LONG, 101),
+
+ /* Set the Accept-Encoding string. Use this to tell a server you would like
+ the response to be compressed. Before 7.21.6, this was known as
+ CURLOPT_ENCODING */
+ CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102),
+
+ /* Set pointer to private data */
+ CINIT(PRIVATE, OBJECTPOINT, 103),
+
+ /* Set aliases for HTTP 200 in the HTTP Response header */
+ CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
+
+ /* Continue to send authentication (user+password) when following locations,
+ even when hostname changed. This can potentially send off the name
+ and password to whatever host the server decides. */
+ CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+ /* Specifically switch on or off the FTP engine's use of the EPRT command (
+ it also disables the LPRT attempt). By default, those ones will always be
+ attempted before the good old traditional PORT command. */
+ CINIT(FTP_USE_EPRT, LONG, 106),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_USERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(HTTPAUTH, LONG, 107),
+
+ /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
+ in second argument. The function must be matching the
+ curl_ssl_ctx_callback proto. */
+ CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+
+ /* Set the userdata for the ssl context callback function's third
+ argument */
+ CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+
+ /* FTP Option that causes missing dirs to be created on the remote server.
+ In 7.19.4 we introduced the convenience enums for this option using the
+ CURLFTP_CREATE_DIR prefix.
+ */
+ CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(PROXYAUTH, LONG, 111),
+
+ /* FTP option that changes the timeout, in seconds, associated with
+ getting a response. This is different from transfer timeout time and
+ essentially places a demand on the FTP server to acknowledge commands
+ in a timely manner. */
+ CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
+#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+
+ /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+ tell libcurl to resolve names to those IP versions only. This only has
+ affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+ CINIT(IPRESOLVE, LONG, 113),
+
+ /* Set this option to limit the size of a file that will be downloaded from
+ an HTTP or FTP server.
+
+ Note there is also _LARGE version which adds large file support for
+ platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */
+ CINIT(MAXFILESIZE, LONG, 114),
+
+ /* See the comment for INFILESIZE above, but in short, specifies
+ * the size of the file being uploaded. -1 means unknown.
+ */
+ CINIT(INFILESIZE_LARGE, OFF_T, 115),
+
+ /* Sets the continuation offset. There is also a LONG version of this;
+ * look above for RESUME_FROM.
+ */
+ CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+
+ /* Sets the maximum size of data that will be downloaded from
+ * an HTTP or FTP server. See MAXFILESIZE above for the LONG version.
+ */
+ CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+ /* Set this option to the file name of your .netrc file you want libcurl
+ to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+ a poor attempt to find the user's home directory and check for a .netrc
+ file in there. */
+ CINIT(NETRC_FILE, OBJECTPOINT, 118),
+
+ /* Enable SSL/TLS for FTP, pick one of:
+ CURLUSESSL_TRY - try using SSL, proceed anyway otherwise
+ CURLUSESSL_CONTROL - SSL for the control connection or fail
+ CURLUSESSL_ALL - SSL for all communication or fail
+ */
+ CINIT(USE_SSL, LONG, 119),
+
+ /* The _LARGE version of the standard POSTFIELDSIZE option */
+ CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+ /* Enable/disable the TCP Nagle algorithm */
+ CINIT(TCP_NODELAY, LONG, 121),
+
+ /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 123 OBSOLETE. Gone in 7.16.0 */
+ /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 127 OBSOLETE. Gone in 7.16.0 */
+ /* 128 OBSOLETE. Gone in 7.16.0 */
+
+ /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
+ can be used to change libcurl's default action which is to first try
+ "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
+ response has been received.
+
+ Available parameters are:
+ CURLFTPAUTH_DEFAULT - let libcurl decide
+ CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
+ CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
+ */
+ CINIT(FTPSSLAUTH, LONG, 129),
+
+ CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+ CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+ /* 132 OBSOLETE. Gone in 7.16.0 */
+ /* 133 OBSOLETE. Gone in 7.16.0 */
+
+ /* zero terminated string for pass on to the FTP server when asked for
+ "account" info */
+ CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
+
+ /* feed cookies into cookie engine */
+ CINIT(COOKIELIST, OBJECTPOINT, 135),
+
+ /* ignore Content-Length */
+ CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+ /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+ response. Typically used for FTP-SSL purposes but is not restricted to
+ that. libcurl will then instead use the same IP address it used for the
+ control connection. */
+ CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+
+ /* Select "file method" to use when doing FTP, see the curl_ftpmethod
+ above. */
+ CINIT(FTP_FILEMETHOD, LONG, 138),
+
+ /* Local port number to bind the socket to */
+ CINIT(LOCALPORT, LONG, 139),
+
+ /* Number of ports to try, including the first one set with LOCALPORT.
+ Thus, setting it to 1 will make no additional attempts but the first.
+ */
+ CINIT(LOCALPORTRANGE, LONG, 140),
+
+ /* no transfer, set up connection and let application use the socket by
+ extracting it with CURLINFO_LASTSOCKET */
+ CINIT(CONNECT_ONLY, LONG, 141),
+
+ /* Function that will be called to convert from the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+
+ /* Function that will be called to convert to the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+
+ /* Function that will be called to convert from UTF8
+ (instead of using the iconv calls in libcurl)
+ Note that this is used only for SSL certificate processing */
+ CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+ /* if the connection proceeds too quickly then need to slow it down */
+ /* limit-rate: maximum number of bytes per second to send or receive */
+ CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+ CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+ /* Pointer to command string to send if USER/PASS fails. */
+ CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
+
+ /* callback function for setting socket options */
+ CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
+ CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+
+ /* set to 0 to disable session ID re-use for this transfer, default is
+ enabled (== 1) */
+ CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+
+ /* allowed SSH authentication methods */
+ CINIT(SSH_AUTH_TYPES, LONG, 151),
+
+ /* Used by scp/sftp to do public/private key authentication */
+ CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
+ CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
+
+ /* Send CCC (Clear Command Channel) after authentication */
+ CINIT(FTP_SSL_CCC, LONG, 154),
+
+ /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
+ CINIT(TIMEOUT_MS, LONG, 155),
+ CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+
+ /* set to zero to disable the libcurl's decoding and thus pass the raw body
+ data to the application even when it is encoded/compressed */
+ CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
+ CINIT(HTTP_CONTENT_DECODING, LONG, 158),
+
+ /* Permission used when creating new files and directories on the remote
+ server for protocols that support it, SFTP/SCP/FILE */
+ CINIT(NEW_FILE_PERMS, LONG, 159),
+ CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+
+ /* Set the behaviour of POST when redirecting. Values must be set to one
+ of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
+ CINIT(POSTREDIR, LONG, 161),
+
+ /* used by scp/sftp to verify the host's public key */
+ CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
+
+ /* Callback function for opening socket (instead of socket(2)). Optionally,
+ callback is able change the address or refuse to connect returning
+ CURL_SOCKET_BAD. The callback should have type
+ curl_opensocket_callback */
+ CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
+ CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+
+ /* POST volatile input fields. */
+ CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+
+ /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
+ CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+
+ /* Callback function for seeking in the input stream */
+ CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+ CINIT(SEEKDATA, OBJECTPOINT, 168),
+
+ /* CRL file */
+ CINIT(CRLFILE, OBJECTPOINT, 169),
+
+ /* Issuer certificate */
+ CINIT(ISSUERCERT, OBJECTPOINT, 170),
+
+ /* (IPv6) Address scope */
+ CINIT(ADDRESS_SCOPE, LONG, 171),
+
+ /* Collect certificate chain info and allow it to get retrievable with
+ CURLINFO_CERTINFO after the transfer is complete. */
+ CINIT(CERTINFO, LONG, 172),
+
+ /* "name" and "pwd" to use when fetching. */
+ CINIT(USERNAME, OBJECTPOINT, 173),
+ CINIT(PASSWORD, OBJECTPOINT, 174),
+
+ /* "name" and "pwd" to use with Proxy when fetching. */
+ CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
+ CINIT(PROXYPASSWORD, OBJECTPOINT, 176),
+
+ /* Comma separated list of hostnames defining no-proxy zones. These should
+ match both hostnames directly, and hostnames within a domain. For
+ example, local.com will match local.com and www.local.com, but NOT
+ notlocal.com or www.notlocal.com. For compatibility with other
+ implementations of this, .local.com will be considered to be the same as
+ local.com. A single * is the only valid wildcard, and effectively
+ disables the use of proxy. */
+ CINIT(NOPROXY, OBJECTPOINT, 177),
+
+ /* block size for TFTP transfers */
+ CINIT(TFTP_BLKSIZE, LONG, 178),
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179),
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+ CINIT(PROTOCOLS, LONG, 181),
+
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ CINIT(REDIR_PROTOCOLS, LONG, 182),
+
+ /* set the SSH knownhost file name to use */
+ CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183),
+
+ /* set the SSH host key callback, must point to a curl_sshkeycallback
+ function */
+ CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+
+ /* set the SSH host key callback custom pointer */
+ CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+
+ /* set the SMTP mail originator */
+ CINIT(MAIL_FROM, OBJECTPOINT, 186),
+
+ /* set the SMTP mail receiver(s) */
+ CINIT(MAIL_RCPT, OBJECTPOINT, 187),
+
+ /* FTP: send PRET before PASV */
+ CINIT(FTP_USE_PRET, LONG, 188),
+
+ /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
+ CINIT(RTSP_REQUEST, LONG, 189),
+
+ /* The RTSP session identifier */
+ CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190),
+
+ /* The RTSP stream URI */
+ CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191),
+
+ /* The Transport: header to use in RTSP requests */
+ CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192),
+
+ /* Manually initialize the client RTSP CSeq for this handle */
+ CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
+
+ /* Manually initialize the server RTSP CSeq for this handle */
+ CINIT(RTSP_SERVER_CSEQ, LONG, 194),
+
+ /* The stream to pass to INTERLEAVEFUNCTION. */
+ CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
+
+ /* Let the application define a custom write method for RTP data */
+ CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
+
+ /* Turn on wildcard matching */
+ CINIT(WILDCARDMATCH, LONG, 197),
+
+ /* Directory matching callback called before downloading of an
+ individual file (chunk) started */
+ CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
+
+ /* Directory matching callback called after the file (chunk)
+ was downloaded, or skipped */
+ CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
+
+ /* Change match (fnmatch-like) callback for wildcard matching */
+ CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
+
+ /* Let the application define custom chunk data pointer */
+ CINIT(CHUNK_DATA, OBJECTPOINT, 201),
+
+ /* FNMATCH_FUNCTION user pointer */
+ CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
+
+ /* send linked-list of name:port:address sets */
+ CINIT(RESOLVE, OBJECTPOINT, 203),
+
+ /* Set a username for authenticated TLS */
+ CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204),
+
+ /* Set a password for authenticated TLS */
+ CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205),
+
+ /* Set authentication type for authenticated TLS */
+ CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206),
+
+ /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
+ compressed transfer-encoded responses. Set to 0 to disable the use of TE:
+ in outgoing requests. The current default is 0, but it might change in a
+ future libcurl release.
+
+ libcurl will ask for the compressed methods it knows of, and if that
+ isn't any, it will not ask for transfer-encoding at all even if this
+ option is set to 1.
+
+ */
+ CINIT(TRANSFER_ENCODING, LONG, 207),
+
+ /* Callback function for closing socket (instead of close(2)). The callback
+ should have type curl_closesocket_callback */
+ CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
+ CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
+
+ /* allow GSSAPI credential delegation */
+ CINIT(GSSAPI_DELEGATION, LONG, 210),
+
+ /* Set the name servers to use for DNS resolution */
+ CINIT(DNS_SERVERS, OBJECTPOINT, 211),
+
+ /* Time-out accept operations (currently for FTP only) after this amount
+ of miliseconds. */
+ CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
+
+ /* Set TCP keepalive */
+ CINIT(TCP_KEEPALIVE, LONG, 213),
+
+ /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
+ CINIT(TCP_KEEPIDLE, LONG, 214),
+ CINIT(TCP_KEEPINTVL, LONG, 215),
+
+ /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
+ CINIT(SSL_OPTIONS, LONG, 216),
+
+ /* Set the SMTP auth originator */
+ CINIT(MAIL_AUTH, OBJECTPOINT, 217),
+
+ /* Enable/disable SASL initial response */
+ CINIT(SASL_IR, LONG, 218),
+
+ /* Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_xferinfo_callback
+ * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
+ CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
+
+ /* The XOAUTH2 bearer token */
+ CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
+
+ /* Set the interface string to use as outgoing network
+ * interface for DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
+
+ /* Set the local IPv4 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
+
+ /* Set the local IPv4 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
+
+ /* Set authentication options directly */
+ CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
+
+ /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_NPN, LONG, 225),
+
+ /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_ALPN, LONG, 226),
+
+ /* Time to wait for a response to a HTTP request containing an
+ * Expect: 100-continue header before sending the data anyway. */
+ CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
+
+ /* This points to a linked list of headers used for proxy requests only,
+ struct curl_slist kind */
+ CINIT(PROXYHEADER, OBJECTPOINT, 228),
+
+ /* Pass in a bitmask of "header options" */
+ CINIT(HEADEROPT, LONG, 229),
+
+ /* The public key in DER form used to validate the peer public key
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(PINNEDPUBLICKEY, OBJECTPOINT, 230),
+
+ /* Path to Unix domain socket */
+ CINIT(UNIX_SOCKET_PATH, OBJECTPOINT, 231),
+
+ /* Set if we should verify the certificate status. */
+ CINIT(SSL_VERIFYSTATUS, LONG, 232),
+
+ /* Set if we should enable TLS false start. */
+ CINIT(SSL_FALSESTART, LONG, 233),
+
+ /* Do not squash dot-dot sequences */
+ CINIT(PATH_AS_IS, LONG, 234),
+
+ CURLOPT_LASTENTRY /* the last unused */
+} CURLoption;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2011 */
+
+/* This was added in version 7.19.1 */
+#define CURLOPT_POST301 CURLOPT_POSTREDIR
+
+/* These are scheduled to disappear by 2009 */
+
+/* The following were added in 7.17.0 */
+#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_FTPAPPEND CURLOPT_APPEND
+#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
+#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
+
+/* The following were added earlier */
+
+#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+
+#else
+/* This is set if CURL_NO_OLDIES is defined at compile-time */
+#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
+#endif
+
+
+ /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+ name resolves addresses using more than one IP protocol version, this
+ option might be handy to force libcurl to use a specific IP version. */
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+ versions that your system allows */
+#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */
+#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */
+
+ /* three convenient "aliases" that follow the name scheme better */
+#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
+
+ /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
+enum {
+ CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
+ like the library to choose the best possible
+ for us! */
+ CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
+ CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
+ CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */
+
+ CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+};
+
+/*
+ * Public API enums for RTSP requests
+ */
+enum {
+ CURL_RTSPREQ_NONE, /* first in list */
+ CURL_RTSPREQ_OPTIONS,
+ CURL_RTSPREQ_DESCRIBE,
+ CURL_RTSPREQ_ANNOUNCE,
+ CURL_RTSPREQ_SETUP,
+ CURL_RTSPREQ_PLAY,
+ CURL_RTSPREQ_PAUSE,
+ CURL_RTSPREQ_TEARDOWN,
+ CURL_RTSPREQ_GET_PARAMETER,
+ CURL_RTSPREQ_SET_PARAMETER,
+ CURL_RTSPREQ_RECORD,
+ CURL_RTSPREQ_RECEIVE,
+ CURL_RTSPREQ_LAST /* last in list */
+};
+
+ /* These enums are for use with the CURLOPT_NETRC option. */
+enum CURL_NETRC_OPTION {
+ CURL_NETRC_IGNORED, /* The .netrc will never be read.
+ * This is the default. */
+ CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
+ * to one in the .netrc. */
+ CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
+ * Unless one is set programmatically, the .netrc
+ * will be queried. */
+ CURL_NETRC_LAST
+};
+
+enum {
+ CURL_SSLVERSION_DEFAULT,
+ CURL_SSLVERSION_TLSv1, /* TLS 1.x */
+ CURL_SSLVERSION_SSLv2,
+ CURL_SSLVERSION_SSLv3,
+ CURL_SSLVERSION_TLSv1_0,
+ CURL_SSLVERSION_TLSv1_1,
+ CURL_SSLVERSION_TLSv1_2,
+
+ CURL_SSLVERSION_LAST /* never use, keep last */
+};
+
+enum CURL_TLSAUTH {
+ CURL_TLSAUTH_NONE,
+ CURL_TLSAUTH_SRP,
+ CURL_TLSAUTH_LAST /* never use, keep last */
+};
+
+/* symbols to use with CURLOPT_POSTREDIR.
+ CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
+ can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
+ | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
+
+#define CURL_REDIR_GET_ALL 0
+#define CURL_REDIR_POST_301 1
+#define CURL_REDIR_POST_302 2
+#define CURL_REDIR_POST_303 4
+#define CURL_REDIR_POST_ALL \
+ (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
+
+typedef enum {
+ CURL_TIMECOND_NONE,
+
+ CURL_TIMECOND_IFMODSINCE,
+ CURL_TIMECOND_IFUNMODSINCE,
+ CURL_TIMECOND_LASTMOD,
+
+ CURL_TIMECOND_LAST
+} curl_TimeCond;
+
+
+/* curl_strequal() and curl_strnequal() are subject for removal in a future
+ libcurl, see lib/README.curlx for details */
+CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
+CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+
+/* name is uppercase CURLFORM_<name> */
+#ifdef CFINIT
+#undef CFINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CFINIT(name) CURLFORM_ ## name
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define CFINIT(name) CURLFORM_/**/name
+#endif
+
+typedef enum {
+ CFINIT(NOTHING), /********* the first one is unused ************/
+
+ /* */
+ CFINIT(COPYNAME),
+ CFINIT(PTRNAME),
+ CFINIT(NAMELENGTH),
+ CFINIT(COPYCONTENTS),
+ CFINIT(PTRCONTENTS),
+ CFINIT(CONTENTSLENGTH),
+ CFINIT(FILECONTENT),
+ CFINIT(ARRAY),
+ CFINIT(OBSOLETE),
+ CFINIT(FILE),
+
+ CFINIT(BUFFER),
+ CFINIT(BUFFERPTR),
+ CFINIT(BUFFERLENGTH),
+
+ CFINIT(CONTENTTYPE),
+ CFINIT(CONTENTHEADER),
+ CFINIT(FILENAME),
+ CFINIT(END),
+ CFINIT(OBSOLETE2),
+
+ CFINIT(STREAM),
+
+ CURLFORM_LASTENTRY /* the last unused */
+} CURLformoption;
+
+#undef CFINIT /* done */
+
+/* structure to be used as parameter for CURLFORM_ARRAY */
+struct curl_forms {
+ CURLformoption option;
+ const char *value;
+};
+
+/* use this for multipart formpost building */
+/* Returns code for curl_formadd()
+ *
+ * Returns:
+ * CURL_FORMADD_OK on success
+ * CURL_FORMADD_MEMORY if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
+ * CURL_FORMADD_NULL if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated
+ * CURL_FORMADD_MEMORY if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
+ *
+ ***************************************************************************/
+typedef enum {
+ CURL_FORMADD_OK, /* first, no error */
+
+ CURL_FORMADD_MEMORY,
+ CURL_FORMADD_OPTION_TWICE,
+ CURL_FORMADD_NULL,
+ CURL_FORMADD_UNKNOWN_OPTION,
+ CURL_FORMADD_INCOMPLETE,
+ CURL_FORMADD_ILLEGAL_ARRAY,
+ CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+
+ CURL_FORMADD_LAST /* last */
+} CURLFORMcode;
+
+/*
+ * NAME curl_formadd()
+ *
+ * DESCRIPTION
+ *
+ * Pretty advanced function for building multi-part formposts. Each invoke
+ * adds one part that together construct a full post. Then use
+ * CURLOPT_HTTPPOST to send it off to libcurl.
+ */
+CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...);
+
+/*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to
+ * curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on
+ * success.
+ */
+typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
+ size_t len);
+
+/*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+ * the curl_formget_callback function.
+ * Returns 0 on success.
+ */
+CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append);
+/*
+ * NAME curl_formfree()
+ *
+ * DESCRIPTION
+ *
+ * Free a multipart formpost previously built with curl_formadd().
+ */
+CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+
+/*
+ * NAME curl_getenv()
+ *
+ * DESCRIPTION
+ *
+ * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
+ * complete. DEPRECATED - see lib/README.curlx
+ */
+CURL_EXTERN char *curl_getenv(const char *variable);
+
+/*
+ * NAME curl_version()
+ *
+ * DESCRIPTION
+ *
+ * Returns a static ascii string of the libcurl version.
+ */
+CURL_EXTERN char *curl_version(void);
+
+/*
+ * NAME curl_easy_escape()
+ *
+ * DESCRIPTION
+ *
+ * Escapes URL strings (converts all letters consider illegal in URLs to their
+ * %XX versions). This function returns a new allocated string or NULL if an
+ * error occurred.
+ */
+CURL_EXTERN char *curl_easy_escape(CURL *handle,
+ const char *string,
+ int length);
+
+/* the previous version: */
+CURL_EXTERN char *curl_escape(const char *string,
+ int length);
+
+
+/*
+ * NAME curl_easy_unescape()
+ *
+ * DESCRIPTION
+ *
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * versions). This function returns a new allocated string or NULL if an error
+ * occurred.
+ * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
+ * converted into the host encoding.
+ */
+CURL_EXTERN char *curl_easy_unescape(CURL *handle,
+ const char *string,
+ int length,
+ int *outlength);
+
+/* the previous version */
+CURL_EXTERN char *curl_unescape(const char *string,
+ int length);
+
+/*
+ * NAME curl_free()
+ *
+ * DESCRIPTION
+ *
+ * Provided for de-allocation in the same translation unit that did the
+ * allocation. Added in libcurl 7.10
+ */
+CURL_EXTERN void curl_free(void *p);
+
+/*
+ * NAME curl_global_init()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() should be invoked exactly once for each application that
+ * uses libcurl and before any call of other libcurl functions.
+ *
+ * This function is not thread-safe!
+ */
+CURL_EXTERN CURLcode curl_global_init(long flags);
+
+/*
+ * NAME curl_global_init_mem()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() or curl_global_init_mem() should be invoked exactly once
+ * for each application that uses libcurl. This function can be used to
+ * initialize libcurl and set user defined memory management callback
+ * functions. Users can implement memory management routines to check for
+ * memory leaks, check for mis-use of the curl library etc. User registered
+ * callback routines with be invoked by this library instead of the system
+ * memory management routines like malloc, free etc.
+ */
+CURL_EXTERN CURLcode curl_global_init_mem(long flags,
+ curl_malloc_callback m,
+ curl_free_callback f,
+ curl_realloc_callback r,
+ curl_strdup_callback s,
+ curl_calloc_callback c);
+
+/*
+ * NAME curl_global_cleanup()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_cleanup() should be invoked exactly once for each application
+ * that uses libcurl
+ */
+CURL_EXTERN void curl_global_cleanup(void);
+
+/* linked-list structure for the CURLOPT_QUOTE option (and other) */
+struct curl_slist {
+ char *data;
+ struct curl_slist *next;
+};
+
+/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+ const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist.
+ */
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+
+/*
+ * NAME curl_getdate()
+ *
+ * DESCRIPTION
+ *
+ * Returns the time, in seconds since 1 Jan 1970 of the time string given in
+ * the first argument. The time argument in the second parameter is unused
+ * and should be set to NULL.
+ */
+CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
+
+/* info about the certificate chain, only for OpenSSL builds. Asked
+ for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+struct curl_certinfo {
+ int num_of_certs; /* number of certificates with information */
+ struct curl_slist **certinfo; /* for each index in this array, there's a
+ linked list with textual information in the
+ format "name: value" */
+};
+
+/* enum for the different supported SSL backends */
+typedef enum {
+ CURLSSLBACKEND_NONE = 0,
+ CURLSSLBACKEND_OPENSSL = 1,
+ CURLSSLBACKEND_GNUTLS = 2,
+ CURLSSLBACKEND_NSS = 3,
+ CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
+ CURLSSLBACKEND_GSKIT = 5,
+ CURLSSLBACKEND_POLARSSL = 6,
+ CURLSSLBACKEND_CYASSL = 7,
+ CURLSSLBACKEND_SCHANNEL = 8,
+ CURLSSLBACKEND_DARWINSSL = 9,
+ CURLSSLBACKEND_AXTLS = 10
+} curl_sslbackend;
+
+/* Information about the SSL library used and the respective internal SSL
+ handle, which can be used to obtain further information regarding the
+ connection. Asked for with CURLINFO_TLS_SESSION. */
+struct curl_tlssessioninfo {
+ curl_sslbackend backend;
+ void *internals;
+};
+
+#define CURLINFO_STRING 0x100000
+#define CURLINFO_LONG 0x200000
+#define CURLINFO_DOUBLE 0x300000
+#define CURLINFO_SLIST 0x400000
+#define CURLINFO_MASK 0x0fffff
+#define CURLINFO_TYPEMASK 0xf00000
+
+typedef enum {
+ CURLINFO_NONE, /* first, never use this */
+ CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
+ CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
+ CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
+ CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
+ CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
+ CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+ CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
+ CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
+ CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
+ CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
+ CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
+ CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
+ CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
+ CURLINFO_FILETIME = CURLINFO_LONG + 14,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
+ CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
+ CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+ CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
+ CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
+ CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
+ CURLINFO_PRIVATE = CURLINFO_STRING + 21,
+ CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
+ CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
+ CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
+ CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
+ CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
+ CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
+ CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
+ CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
+ CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
+ CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
+ CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
+ CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
+ CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
+ CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
+ CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
+ CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
+ CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
+ CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
+ CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
+ CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
+ CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
+ CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
+ /* Fill in new entries below here! */
+
+ CURLINFO_LASTONE = 43
+} CURLINFO;
+
+/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+ CURLINFO_HTTP_CODE */
+#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+typedef enum {
+ CURLCLOSEPOLICY_NONE, /* first, never use this */
+
+ CURLCLOSEPOLICY_OLDEST,
+ CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+ CURLCLOSEPOLICY_LEAST_TRAFFIC,
+ CURLCLOSEPOLICY_SLOWEST,
+ CURLCLOSEPOLICY_CALLBACK,
+
+ CURLCLOSEPOLICY_LAST /* last, never use this */
+} curl_closepolicy;
+
+#define CURL_GLOBAL_SSL (1<<0)
+#define CURL_GLOBAL_WIN32 (1<<1)
+#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+#define CURL_GLOBAL_NOTHING 0
+#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
+#define CURL_GLOBAL_ACK_EINTR (1<<2)
+
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different data locks for a single share */
+typedef enum {
+ CURL_LOCK_DATA_NONE = 0,
+ /* CURL_LOCK_DATA_SHARE is used internally to say that
+ * the locking is just made to change the internal state of the share
+ * itself.
+ */
+ CURL_LOCK_DATA_SHARE,
+ CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_DATA_DNS,
+ CURL_LOCK_DATA_SSL_SESSION,
+ CURL_LOCK_DATA_CONNECT,
+ CURL_LOCK_DATA_LAST
+} curl_lock_data;
+
+/* Different lock access types */
+typedef enum {
+ CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */
+ CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+ CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+ CURL_LOCK_ACCESS_LAST /* never use */
+} curl_lock_access;
+
+typedef void (*curl_lock_function)(CURL *handle,
+ curl_lock_data data,
+ curl_lock_access locktype,
+ void *userptr);
+typedef void (*curl_unlock_function)(CURL *handle,
+ curl_lock_data data,
+ void *userptr);
+
+typedef void CURLSH;
+
+typedef enum {
+ CURLSHE_OK, /* all is fine */
+ CURLSHE_BAD_OPTION, /* 1 */
+ CURLSHE_IN_USE, /* 2 */
+ CURLSHE_INVALID, /* 3 */
+ CURLSHE_NOMEM, /* 4 out of memory */
+ CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
+ CURLSHE_LAST /* never use */
+} CURLSHcode;
+
+typedef enum {
+ CURLSHOPT_NONE, /* don't use */
+ CURLSHOPT_SHARE, /* specify a data type to share */
+ CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
+ CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */
+ CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+ CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock
+ callback functions */
+ CURLSHOPT_LAST /* never use */
+} CURLSHoption;
+
+CURL_EXTERN CURLSH *curl_share_init(void);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+
+/****************************************************************************
+ * Structures for querying information about the curl library at runtime.
+ */
+
+typedef enum {
+ CURLVERSION_FIRST,
+ CURLVERSION_SECOND,
+ CURLVERSION_THIRD,
+ CURLVERSION_FOURTH,
+ CURLVERSION_LAST /* never actually use this */
+} CURLversion;
+
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+ basically all programs ever that want to get version information. It is
+ meant to be a built-in version number for what kind of struct the caller
+ expects. If the struct ever changes, we redefine the NOW to another enum
+ from above. */
+#define CURLVERSION_NOW CURLVERSION_FOURTH
+
+typedef struct {
+ CURLversion age; /* age of the returned struct */
+ const char *version; /* LIBCURL_VERSION */
+ unsigned int version_num; /* LIBCURL_VERSION_NUM */
+ const char *host; /* OS/host/cpu/machine when configured */
+ int features; /* bitmask, see defines below */
+ const char *ssl_version; /* human readable string */
+ long ssl_version_num; /* not used anymore, always 0 */
+ const char *libz_version; /* human readable string */
+ /* protocols is terminated by an entry with a NULL protoname */
+ const char * const *protocols;
+
+ /* The fields below this were added in CURLVERSION_SECOND */
+ const char *ares;
+ int ares_num;
+
+ /* This field was added in CURLVERSION_THIRD */
+ const char *libidn;
+
+ /* These field were added in CURLVERSION_FOURTH */
+
+ /* Same as '_libiconv_version' if built with HAVE_ICONV */
+ int iconv_ver_num;
+
+ const char *libssh_version; /* human readable string */
+
+} curl_version_info_data;
+
+#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
+#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported
+ (deprecated) */
+#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
+#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
+#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
+#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported
+ (deprecated) */
+#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */
+#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */
+#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */
+#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */
+#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are
+ supported */
+#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */
+#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */
+#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */
+#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
+#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper
+ is suported */
+#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
+#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */
+#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */
+#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
+
+ /*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+
+/*
+ * NAME curl_easy_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_strerror function may be used to turn a CURLcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+
+/*
+ * NAME curl_share_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_share_strerror function may be used to turn a CURLSHcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+
+/*
+ * NAME curl_easy_pause()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_pause function pauses or unpauses transfers. Select the new
+ * state by setting the bitmask, use the convenience defines below.
+ *
+ */
+CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
+
+#define CURLPAUSE_RECV (1<<0)
+#define CURLPAUSE_RECV_CONT (0)
+
+#define CURLPAUSE_SEND (1<<2)
+#define CURLPAUSE_SEND_CONT (0)
+
+#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND)
+#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* unfortunately, the easy.h and multi.h include files need options and info
+ stuff before they can be included! */
+#include "easy.h" /* nothing in curl is fun without the easy stuff */
+#include "multi.h"
+
+/* the typechecker doesn't work in C++ (yet) */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+ ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
+ !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
+#include "typecheck-gcc.h"
+#else
+#if defined(__STDC__) && (__STDC__ >= 1)
+/* This preprocessor magic that replaces a call with the exact same call is
+ only done to make sure application authors pass exactly three arguments
+ to these functions. */
+#if !defined(BUILDING_LIBCURL)
+//#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
+//#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
+//#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+//#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+#endif
+#endif /* __STDC__ >= 1 */
+#endif /* gcc >= 4.3 && !__cplusplus */
+
+#endif /* __CURL_CURL_H */
diff --git a/libcurl/src/include/curl/curlbuild.h b/libcurl/src/include/curl/curlbuild.h
new file mode 100644
index 0000000..9937bd0
--- /dev/null
+++ b/libcurl/src/include/curl/curlbuild.h
@@ -0,0 +1,599 @@
+#ifndef __CURL_CURLBUILD_H
+#define __CURL_CURLBUILD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * See file include/curl/curlbuild.h.in, run configure, and forget
+ * that this file exists it is only used for non-configure systems.
+ * But you can keep reading if you want ;-)
+ *
+ */
+
+/* ================================================================ */
+/* NOTES FOR NON-CONFIGURE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * If you think that something actually needs to be changed, adjusted
+ * or fixed in this file, then, report it on the libcurl development
+ * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * Try to keep one section per platform, compiler and architecture,
+ * otherwise, if an existing section is reused for a different one and
+ * later on the original is adjusted, probably the piggybacking one can
+ * be adversely changed.
+ *
+ * In order to differentiate between platforms/compilers/architectures
+ * use only compiler built in predefined preprocessor symbols.
+ *
+ * This header file shall only export symbols which are 'curl' or 'CURL'
+ * prefixed, otherwise public name space would be polluted.
+ *
+ * NOTE 2:
+ * -------
+ *
+ * For any given platform/compiler curl_off_t must be typedef'ed to a
+ * 64-bit wide signed integral data type. The width of this data type
+ * must remain constant and independent of any possible large file
+ * support settings.
+ *
+ * As an exception to the above, curl_off_t shall be typedef'ed to a
+ * 32-bit wide signed integral data type if there is no 64-bit type.
+ *
+ * As a general rule, curl_off_t shall not be mapped to off_t. This
+ * rule shall only be violated if off_t is the only 64-bit data type
+ * available and the size of off_t is independent of large file support
+ * settings. Keep your build on the safe side avoiding an off_t gating.
+ * If you have a 64-bit off_t then take for sure that another 64-bit
+ * data type exists, dig deeper and you will find it.
+ *
+ * NOTE 3:
+ * -------
+ *
+ * Right now you might be staring at file include/curl/curlbuild.h.dist or
+ * at file include/curl/curlbuild.h, this is due to the following reason:
+ * file include/curl/curlbuild.h.dist is renamed to include/curl/curlbuild.h
+ * when the libcurl source code distribution archive file is created.
+ *
+ * File include/curl/curlbuild.h.dist is not included in the distribution
+ * archive. File include/curl/curlbuild.h is not present in the git tree.
+ *
+ * The distributed include/curl/curlbuild.h file is only intended to be used
+ * on systems which can not run the also distributed configure script.
+ *
+ * On systems capable of running the configure script, the configure process
+ * will overwrite the distributed include/curl/curlbuild.h file with one that
+ * is suitable and specific to the library being configured and built, which
+ * is generated from the include/curl/curlbuild.h.in template file.
+ *
+ * If you check out from git on a non-configure platform, you must run the
+ * appropriate buildconf* script to set up curlbuild.h and other local files.
+ *
+ */
+
+/* ================================================================ */
+/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
+/* ================================================================ */
+
+#ifdef CURL_SIZEOF_LONG
+# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_T
+# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_TU
+# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+#endif
+
+#ifdef CURL_FORMAT_OFF_T
+# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_OFF_T
+# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_T
+# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_TU
+# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+#endif
+
+/* ================================================================ */
+/* EXTERNAL INTERFACE SETTINGS FOR NON-CONFIGURE SYSTEMS ONLY */
+/* ================================================================ */
+
+#if defined(__DJGPP__) || defined(__GO32__)
+# if defined(__DJGPP__) && (__DJGPP__ > 1)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SALFORDC__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__BORLANDC__)
+# if (__BORLANDC__ < 0x520)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__TURBOC__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__WATCOMC__)
+# if defined(__386__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__POCC__)
+# if (__POCC__ < 280)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# elif defined(_MSC_VER)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__LCC__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SYMBIAN32__)
+# if defined(__EABI__) /* Treat all ARM compilers equally */
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__CW32__)
+# pragma longlong on
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__VC32__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MWERKS__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(_WIN32_WCE)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MINGW32__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__VMS)
+# if defined(__VAX)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__OS400__)
+# if defined(__ILEC400__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(__MVS__)
+# if defined(__IBMC__) || defined(__IBMCPP__)
+# if defined(_ILP32)
+# define CURL_SIZEOF_LONG 4
+# elif defined(_LP64)
+# define CURL_SIZEOF_LONG 8
+# endif
+# if defined(_LONG_LONG)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(__370__)
+# if defined(__IBMC__) || defined(__IBMCPP__)
+# if defined(_ILP32)
+# define CURL_SIZEOF_LONG 4
+# elif defined(_LP64)
+# define CURL_SIZEOF_LONG 8
+# endif
+# if defined(_LONG_LONG)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(TPF)
+# define CURL_SIZEOF_LONG 8
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+/* ===================================== */
+/* KEEP MSVC THE PENULTIMATE ENTRY */
+/* ===================================== */
+
+#elif defined(_MSC_VER)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_OFF_T "%I64d"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 4
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__EMSCRIPTEN__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+/* ===================================== */
+/* KEEP GENERIC GCC THE LAST ENTRY */
+/* ===================================== */
+
+#elif defined(__GNUC__)
+# if defined(__ILP32__) || \
+ defined(__i386__) || defined(__ppc__) || defined(__arm__) || defined(__sparc__)
+# define CURL_SIZEOF_LONG 4
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_FORMAT_OFF_T "%lld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__LP64__) || \
+ defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__)
+# define CURL_SIZEOF_LONG 8
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_FORMAT_OFF_T "%ld"
+# define CURL_SIZEOF_CURL_OFF_T 8
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_SIZEOF_CURL_SOCKLEN_T 4
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+#else
+# error "Unknown non-configure build target!"
+ Error Compilation_aborted_Unknown_non_configure_build_target
+#endif
+
+/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
+/* sys/types.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
+/* sys/socket.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+/* Data type definition of curl_socklen_t. */
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+ typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+#endif
+
+/* Data type definition of curl_off_t. */
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+ typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+#endif
+
+#endif /* __CURL_CURLBUILD_H */
diff --git a/libcurl/src/include/curl/curlbuild.h.cmake b/libcurl/src/include/curl/curlbuild.h.cmake
new file mode 100644
index 0000000..60bc7a7
--- /dev/null
+++ b/libcurl/src/include/curl/curlbuild.h.cmake
@@ -0,0 +1,197 @@
+#ifndef __CURL_CURLBUILD_H
+#define __CURL_CURLBUILD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * If you think that something actually needs to be changed, adjusted
+ * or fixed in this file, then, report it on the libcurl development
+ * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * This header file shall only export symbols which are 'curl' or 'CURL'
+ * prefixed, otherwise public name space would be polluted.
+ *
+ * NOTE 2:
+ * -------
+ *
+ * Right now you might be staring at file include/curl/curlbuild.h.in or
+ * at file include/curl/curlbuild.h, this is due to the following reason:
+ *
+ * On systems capable of running the configure script, the configure process
+ * will overwrite the distributed include/curl/curlbuild.h file with one that
+ * is suitable and specific to the library being configured and built, which
+ * is generated from the include/curl/curlbuild.h.in template file.
+ *
+ */
+
+/* ================================================================ */
+/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
+/* ================================================================ */
+
+#ifdef CURL_SIZEOF_LONG
+#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_T
+#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_TU
+#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+#endif
+
+#ifdef CURL_FORMAT_OFF_T
+#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_OFF_T
+#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_T
+#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_TU
+#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+#endif
+
+/* ================================================================ */
+/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
+/* ================================================================ */
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file ws2tcpip.h must be included by the external interface. */
+#cmakedefine CURL_PULL_WS2TCPIP_H
+#ifdef CURL_PULL_WS2TCPIP_H
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/types.h must be included by the external interface. */
+#cmakedefine CURL_PULL_SYS_TYPES_H
+#ifdef CURL_PULL_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file stdint.h must be included by the external interface. */
+#cmakedefine CURL_PULL_STDINT_H
+#ifdef CURL_PULL_STDINT_H
+# include <stdint.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file inttypes.h must be included by the external interface. */
+#cmakedefine CURL_PULL_INTTYPES_H
+#ifdef CURL_PULL_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/socket.h must be included by the external interface. */
+#cmakedefine CURL_PULL_SYS_SOCKET_H
+#ifdef CURL_PULL_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/poll.h must be included by the external interface. */
+#cmakedefine CURL_PULL_SYS_POLL_H
+#ifdef CURL_PULL_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+
+/* The size of `long', as computed by sizeof. */
+#define CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG}
+
+/* Integral data type used for curl_socklen_t. */
+#define CURL_TYPEOF_CURL_SOCKLEN_T ${CURL_TYPEOF_CURL_SOCKLEN_T}
+
+/* The size of `curl_socklen_t', as computed by sizeof. */
+#define CURL_SIZEOF_CURL_SOCKLEN_T ${CURL_SIZEOF_CURL_SOCKLEN_T}
+
+/* Data type definition of curl_socklen_t. */
+typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+
+/* Signed integral data type used for curl_off_t. */
+#define CURL_TYPEOF_CURL_OFF_T ${CURL_TYPEOF_CURL_OFF_T}
+
+/* Data type definition of curl_off_t. */
+typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+
+/* curl_off_t formatting string directive without "%" conversion specifier. */
+#define CURL_FORMAT_CURL_OFF_T "${CURL_FORMAT_CURL_OFF_T}"
+
+/* unsigned curl_off_t formatting string without "%" conversion specifier. */
+#define CURL_FORMAT_CURL_OFF_TU "${CURL_FORMAT_CURL_OFF_TU}"
+
+/* curl_off_t formatting string directive with "%" conversion specifier. */
+#define CURL_FORMAT_OFF_T "${CURL_FORMAT_OFF_T}"
+
+/* The size of `curl_off_t', as computed by sizeof. */
+#define CURL_SIZEOF_CURL_OFF_T ${CURL_SIZEOF_CURL_OFF_T}
+
+/* curl_off_t constant suffix. */
+#define CURL_SUFFIX_CURL_OFF_T ${CURL_SUFFIX_CURL_OFF_T}
+
+/* unsigned curl_off_t constant suffix. */
+#define CURL_SUFFIX_CURL_OFF_TU ${CURL_SUFFIX_CURL_OFF_TU}
+
+#endif /* __CURL_CURLBUILD_H */
diff --git a/libcurl/src/include/curl/curlbuild.h.in b/libcurl/src/include/curl/curlbuild.h.in
new file mode 100644
index 0000000..e29f195
--- /dev/null
+++ b/libcurl/src/include/curl/curlbuild.h.in
@@ -0,0 +1,197 @@
+#ifndef __CURL_CURLBUILD_H
+#define __CURL_CURLBUILD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * If you think that something actually needs to be changed, adjusted
+ * or fixed in this file, then, report it on the libcurl development
+ * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * This header file shall only export symbols which are 'curl' or 'CURL'
+ * prefixed, otherwise public name space would be polluted.
+ *
+ * NOTE 2:
+ * -------
+ *
+ * Right now you might be staring at file include/curl/curlbuild.h.in or
+ * at file include/curl/curlbuild.h, this is due to the following reason:
+ *
+ * On systems capable of running the configure script, the configure process
+ * will overwrite the distributed include/curl/curlbuild.h file with one that
+ * is suitable and specific to the library being configured and built, which
+ * is generated from the include/curl/curlbuild.h.in template file.
+ *
+ */
+
+/* ================================================================ */
+/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
+/* ================================================================ */
+
+#ifdef CURL_SIZEOF_LONG
+#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_T
+#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_TU
+#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+#endif
+
+#ifdef CURL_FORMAT_OFF_T
+#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_OFF_T
+#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_T
+#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_TU
+#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+#endif
+
+/* ================================================================ */
+/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
+/* ================================================================ */
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file ws2tcpip.h must be included by the external interface. */
+#undef CURL_PULL_WS2TCPIP_H
+#ifdef CURL_PULL_WS2TCPIP_H
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/types.h must be included by the external interface. */
+#undef CURL_PULL_SYS_TYPES_H
+#ifdef CURL_PULL_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file stdint.h must be included by the external interface. */
+#undef CURL_PULL_STDINT_H
+#ifdef CURL_PULL_STDINT_H
+# include <stdint.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file inttypes.h must be included by the external interface. */
+#undef CURL_PULL_INTTYPES_H
+#ifdef CURL_PULL_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/socket.h must be included by the external interface. */
+#undef CURL_PULL_SYS_SOCKET_H
+#ifdef CURL_PULL_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/poll.h must be included by the external interface. */
+#undef CURL_PULL_SYS_POLL_H
+#ifdef CURL_PULL_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+
+/* The size of `long', as computed by sizeof. */
+#undef CURL_SIZEOF_LONG
+
+/* Integral data type used for curl_socklen_t. */
+#undef CURL_TYPEOF_CURL_SOCKLEN_T
+
+/* The size of `curl_socklen_t', as computed by sizeof. */
+#undef CURL_SIZEOF_CURL_SOCKLEN_T
+
+/* Data type definition of curl_socklen_t. */
+typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+
+/* Signed integral data type used for curl_off_t. */
+#undef CURL_TYPEOF_CURL_OFF_T
+
+/* Data type definition of curl_off_t. */
+typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+
+/* curl_off_t formatting string directive without "%" conversion specifier. */
+#undef CURL_FORMAT_CURL_OFF_T
+
+/* unsigned curl_off_t formatting string without "%" conversion specifier. */
+#undef CURL_FORMAT_CURL_OFF_TU
+
+/* curl_off_t formatting string directive with "%" conversion specifier. */
+#undef CURL_FORMAT_OFF_T
+
+/* The size of `curl_off_t', as computed by sizeof. */
+#undef CURL_SIZEOF_CURL_OFF_T
+
+/* curl_off_t constant suffix. */
+#undef CURL_SUFFIX_CURL_OFF_T
+
+/* unsigned curl_off_t constant suffix. */
+#undef CURL_SUFFIX_CURL_OFF_TU
+
+#endif /* __CURL_CURLBUILD_H */
diff --git a/libcurl/src/include/curl/curlrules.h b/libcurl/src/include/curl/curlrules.h
new file mode 100644
index 0000000..7c2ede3
--- /dev/null
+++ b/libcurl/src/include/curl/curlrules.h
@@ -0,0 +1,262 @@
+#ifndef __CURL_CURLRULES_H
+#define __CURL_CURLRULES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* COMPILE TIME SANITY CHECKS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * All checks done in this file are intentionally placed in a public
+ * header file which is pulled by curl/curl.h when an application is
+ * being built using an already built libcurl library. Additionally
+ * this file is also included and used when building the library.
+ *
+ * If compilation fails on this file it is certainly sure that the
+ * problem is elsewhere. It could be a problem in the curlbuild.h
+ * header file, or simply that you are using different compilation
+ * settings than those used to build the library.
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * Do not deactivate any check, these are done to make sure that the
+ * library is properly built and used.
+ *
+ * You can find further help on the libcurl development mailing list:
+ * http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * NOTE 2
+ * ------
+ *
+ * Some of the following compile time checks are based on the fact
+ * that the dimension of a constant array can not be a negative one.
+ * In this way if the compile time verification fails, the compilation
+ * will fail issuing an error. The error description wording is compiler
+ * dependent but it will be quite similar to one of the following:
+ *
+ * "negative subscript or subscript is too large"
+ * "array must have at least one element"
+ * "-1 is an illegal array size"
+ * "size of array is negative"
+ *
+ * If you are building an application which tries to use an already
+ * built libcurl library and you are getting this kind of errors on
+ * this file, it is a clear indication that there is a mismatch between
+ * how the library was built and how you are trying to use it for your
+ * application. Your already compiled or binary library provider is the
+ * only one who can give you the details you need to properly use it.
+ */
+
+/*
+ * Verify that some macros are actually defined.
+ */
+
+#ifndef CURL_SIZEOF_LONG
+# error "CURL_SIZEOF_LONG definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
+# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
+# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_OFF_T
+# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_T
+# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_TU
+# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
+#endif
+
+#ifndef CURL_FORMAT_OFF_T
+# error "CURL_FORMAT_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_OFF_T
+# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_T
+# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_TU
+# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
+#endif
+
+/*
+ * Macros private to this header file.
+ */
+
+#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
+
+#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
+
+/*
+ * Verify that the size previously defined and expected for long
+ * is the same as the one reported by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_01__
+ [CurlchkszEQ(long, CURL_SIZEOF_LONG)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_off_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_02__
+ [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
+
+/*
+ * Verify at compile time that the size of curl_off_t as reported
+ * by sizeof() is greater or equal than the one reported for long
+ * for the current compilation.
+ */
+
+typedef char
+ __curl_rule_03__
+ [CurlchkszGE(curl_off_t, long)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_socklen_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_04__
+ [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
+
+/*
+ * Verify at compile time that the size of curl_socklen_t as reported
+ * by sizeof() is greater or equal than the one reported for int for
+ * the current compilation.
+ */
+
+typedef char
+ __curl_rule_05__
+ [CurlchkszGE(curl_socklen_t, int)];
+
+/* ================================================================ */
+/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
+/* ================================================================ */
+
+/*
+ * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
+ * these to be visible and exported by the external libcurl interface API,
+ * while also making them visible to the library internals, simply including
+ * curl_setup.h, without actually needing to include curl.h internally.
+ * If some day this section would grow big enough, all this should be moved
+ * to its own header file.
+ */
+
+/*
+ * Figure out if we can use the ## preprocessor operator, which is supported
+ * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
+ * or __cplusplus so we need to carefully check for them too.
+ */
+
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+ defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+ defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
+ defined(__ILEC400__)
+ /* This compiler is believed to have an ISO compatible preprocessor */
+#define CURL_ISOCPP
+#else
+ /* This compiler is believed NOT to have an ISO compatible preprocessor */
+#undef CURL_ISOCPP
+#endif
+
+/*
+ * Macros for minimum-width signed and unsigned curl_off_t integer constants.
+ */
+
+#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
+# define __CURL_OFF_T_C_HLPR2(x) x
+# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
+#else
+# ifdef CURL_ISOCPP
+# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
+# else
+# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
+# endif
+# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
+#endif
+
+/*
+ * Get rid of macros private to this header file.
+ */
+
+#undef CurlchkszEQ
+#undef CurlchkszGE
+
+/*
+ * Get rid of macros not intended to exist beyond this point.
+ */
+
+#undef CURL_PULL_WS2TCPIP_H
+#undef CURL_PULL_SYS_TYPES_H
+#undef CURL_PULL_SYS_SOCKET_H
+#undef CURL_PULL_SYS_POLL_H
+#undef CURL_PULL_STDINT_H
+#undef CURL_PULL_INTTYPES_H
+
+#undef CURL_TYPEOF_CURL_SOCKLEN_T
+#undef CURL_TYPEOF_CURL_OFF_T
+
+#ifdef CURL_NO_OLDIES
+#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
+#endif
+
+#endif /* __CURL_CURLRULES_H */
diff --git a/libcurl/src/include/curl/curlver.h b/libcurl/src/include/curl/curlver.h
new file mode 100644
index 0000000..7976c1f
--- /dev/null
+++ b/libcurl/src/include/curl/curlver.h
@@ -0,0 +1,69 @@
+#ifndef __CURL_CURLVER_H
+#define __CURL_CURLVER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This header file contains nothing but libcurl version info, generated by
+ a script at release-time. This was made its own header file in 7.11.2 */
+
+/* This is the global package copyright */
+#define LIBCURL_COPYRIGHT "1996 - 2015 Daniel Stenberg, <daniel@haxx.se>."
+
+/* This is the version number of the libcurl package from which this header
+ file origins: */
+#define LIBCURL_VERSION "7.42.1"
+
+/* The numeric version number is also available "in parts" by using these
+ defines: */
+#define LIBCURL_VERSION_MAJOR 7
+#define LIBCURL_VERSION_MINOR 42
+#define LIBCURL_VERSION_PATCH 1
+
+/* This is the numeric version of the libcurl version number, meant for easier
+ parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+ always follow this syntax:
+
+ 0xXXYYZZ
+
+ Where XX, YY and ZZ are the main version, release and patch numbers in
+ hexadecimal (using 8 bits each). All three numbers are always represented
+ using two digits. 1.2 would appear as "0x010200" while version 9.11.7
+ appears as "0x090b07".
+
+ This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+ and it is always a greater number in a more recent release. It makes
+ comparisons with greater than and less than work.
+*/
+#define LIBCURL_VERSION_NUM 0x072a01
+
+/*
+ * This is the date and time when the full source package was created. The
+ * timestamp is not stored in git, as the timestamp is properly set in the
+ * tarballs by the maketgz script.
+ *
+ * The format of the date should follow this template:
+ *
+ * "Mon Feb 12 11:35:33 UTC 2007"
+ */
+#define LIBCURL_TIMESTAMP "Wed Apr 29 06:07:13 UTC 2015"
+
+#endif /* __CURL_CURLVER_H */
diff --git a/libcurl/src/include/curl/easy.h b/libcurl/src/include/curl/easy.h
new file mode 100644
index 0000000..c1e3e76
--- /dev/null
+++ b/libcurl/src/include/curl/easy.h
@@ -0,0 +1,102 @@
+#ifndef __CURL_EASY_H
+#define __CURL_EASY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN CURL *curl_easy_init(void);
+CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+CURL_EXTERN void curl_easy_cleanup(CURL *curl);
+
+/*
+ * NAME curl_easy_getinfo()
+ *
+ * DESCRIPTION
+ *
+ * Request internal information from the curl session with this function. The
+ * third argument MUST be a pointer to a long, a pointer to a char * or a
+ * pointer to a double (as the documentation describes elsewhere). The data
+ * pointed to will be filled in accordingly and can be relied upon only if the
+ * function returns CURLE_OK. This function is intended to get used *AFTER* a
+ * performed transfer, all results from this function are undefined until the
+ * transfer is completed.
+ */
+CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
+
+
+/*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+ * options, internal state info and things like persistent connections cannot
+ * be transferred. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+
+/*
+ * NAME curl_easy_reset()
+ *
+ * DESCRIPTION
+ *
+ * Re-initializes a CURL handle to the default values. This puts back the
+ * handle to the same state as it was in when it was just created.
+ *
+ * It does keep: live connections, the Session ID cache, the DNS cache and the
+ * cookies.
+ */
+CURL_EXTERN void curl_easy_reset(CURL *curl);
+
+/*
+ * NAME curl_easy_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *n);
+
+/*
+ * NAME curl_easy_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libcurl/src/include/curl/mprintf.h b/libcurl/src/include/curl/mprintf.h
new file mode 100644
index 0000000..c6b0d76
--- /dev/null
+++ b/libcurl/src/include/curl/mprintf.h
@@ -0,0 +1,74 @@
+#ifndef __CURL_MPRINTF_H
+#define __CURL_MPRINTF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <stdarg.h>
+#include <stdio.h> /* needed for FILE */
+
+#include "curl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN int curl_mprintf(const char *format, ...);
+CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
+CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
+CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
+ const char *format, ...);
+CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
+CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
+CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
+CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
+ const char *format, va_list args);
+CURL_EXTERN char *curl_maprintf(const char *format, ...);
+CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
+
+#ifdef _MPRINTF_REPLACE
+# undef printf
+# undef fprintf
+# undef sprintf
+# undef vsprintf
+# undef snprintf
+# undef vprintf
+# undef vfprintf
+# undef vsnprintf
+# undef aprintf
+# undef vaprintf
+# define printf curl_mprintf
+# define fprintf curl_mfprintf
+# define sprintf curl_msprintf
+# define vsprintf curl_mvsprintf
+# define snprintf curl_msnprintf
+# define vprintf curl_mvprintf
+# define vfprintf curl_mvfprintf
+# define vsnprintf curl_mvsnprintf
+# define aprintf curl_maprintf
+# define vaprintf curl_mvaprintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CURL_MPRINTF_H */
diff --git a/libcurl/src/include/curl/multi.h b/libcurl/src/include/curl/multi.h
new file mode 100644
index 0000000..d5776b3
--- /dev/null
+++ b/libcurl/src/include/curl/multi.h
@@ -0,0 +1,400 @@
+#ifndef __CURL_MULTI_H
+#define __CURL_MULTI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ This is an "external" header file. Don't give away any internals here!
+
+ GOALS
+
+ o Enable a "pull" interface. The application that uses libcurl decides where
+ and when to ask libcurl to get/send data.
+
+ o Enable multiple simultaneous transfers in the same thread without making it
+ complicated for the application.
+
+ o Enable the application to select() on its own file descriptors and curl's
+ file descriptors simultaneous easily.
+
+*/
+
+/*
+ * This header file should not really need to include "curl.h" since curl.h
+ * itself includes this file and we expect user applications to do #include
+ * <curl/curl.h> without the need for especially including multi.h.
+ *
+ * For some reason we added this include here at one point, and rather than to
+ * break existing (wrongly written) libcurl applications, we leave it as-is
+ * but with this warning attached.
+ */
+#include "curl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void CURLM;
+
+typedef enum {
+ CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+ curl_multi_socket*() soon */
+ CURLM_OK,
+ CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
+ CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+ CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
+ CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
+ CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
+ CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
+ CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
+ attempted to get added - again */
+ CURLM_LAST
+} CURLMcode;
+
+/* just to make code nicer when using curl_multi_socket() you can now check
+ for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+ curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
+typedef enum {
+ CURLMSG_NONE, /* first, not used */
+ CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+ the CURLcode of the transfer */
+ CURLMSG_LAST /* last, not used */
+} CURLMSG;
+
+struct CURLMsg {
+ CURLMSG msg; /* what this message means */
+ CURL *easy_handle; /* the handle it concerns */
+ union {
+ void *whatever; /* message-specific data */
+ CURLcode result; /* return code for transfer */
+ } data;
+};
+typedef struct CURLMsg CURLMsg;
+
+/* Based on poll(2) structure and values.
+ * We don't use pollfd and POLL* constants explicitly
+ * to cover platforms without poll(). */
+#define CURL_WAIT_POLLIN 0x0001
+#define CURL_WAIT_POLLPRI 0x0002
+#define CURL_WAIT_POLLOUT 0x0004
+
+struct curl_waitfd {
+ curl_socket_t fd;
+ short events;
+ short revents; /* not supported yet */
+};
+
+/*
+ * Name: curl_multi_init()
+ *
+ * Desc: inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+CURL_EXTERN CURLM *curl_multi_init(void);
+
+/*
+ * Name: curl_multi_add_handle()
+ *
+ * Desc: add a standard curl handle to the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_remove_handle()
+ *
+ * Desc: removes a curl handle from the multi stack again
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_fdset()
+ *
+ * Desc: Ask curl for its fd_set sets. The app can use these to select() or
+ * poll() on. We want curl_multi_perform() called as soon as one of
+ * them are ready.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+
+/*
+ * Name: curl_multi_wait()
+ *
+ * Desc: Poll on all fds within a CURLM set as well as any
+ * additional fds passed to the function.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret);
+
+ /*
+ * Name: curl_multi_perform()
+ *
+ * Desc: When the app thinks there's data available for curl it calls this
+ * function to read/write whatever there is right now. This returns
+ * as soon as the reads and writes are done. This function does not
+ * require that there actually is data available for reading or that
+ * data can be written, it can be called just in case. It returns
+ * the number of handles that still transfer data in the second
+ * argument's integer-pointer.
+ *
+ * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+ * returns errors etc regarding the whole multi stack. There might
+ * still have occurred problems on invidual transfers even when this
+ * returns OK.
+ */
+CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+ int *running_handles);
+
+ /*
+ * Name: curl_multi_cleanup()
+ *
+ * Desc: Cleans up and removes a whole multi stack. It does not free or
+ * touch any individual easy handles in any way. We need to define
+ * in what state those handles will be if this function is called
+ * in the middle of a transfer.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+
+/*
+ * Name: curl_multi_info_read()
+ *
+ * Desc: Ask the multi handle if there's any messages/informationals from
+ * the individual transfers. Messages include informationals such as
+ * error code from the transfer or just the fact that a transfer is
+ * completed. More details on these should be written down as well.
+ *
+ * Repeated calls to this function will return a new struct each
+ * time, until a special "end of msgs" struct is returned as a signal
+ * that there is no more to get at this point.
+ *
+ * The data the returned pointer points to will not survive calling
+ * curl_multi_cleanup().
+ *
+ * The 'CURLMsg' struct is meant to be very simple and only contain
+ * very basic informations. If more involved information is wanted,
+ * we will provide the particular "transfer handle" in that struct
+ * and that should/could/would be used in subsequent
+ * curl_easy_getinfo() calls (or similar). The point being that we
+ * must never expose complex structs to applications, as then we'll
+ * undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ * of structs. It also writes the number of messages left in the
+ * queue (after this read) in the integer the second argument points
+ * to.
+ */
+CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
+ int *msgs_in_queue);
+
+/*
+ * Name: curl_multi_strerror()
+ *
+ * Desc: The curl_multi_strerror function may be used to turn a CURLMcode
+ * value into the equivalent human readable error string. This is
+ * useful for printing meaningful error messages.
+ *
+ * Returns: A pointer to a zero-terminated error message.
+ */
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+
+/*
+ * Name: curl_multi_socket() and
+ * curl_multi_socket_all()
+ *
+ * Desc: An alternative version of curl_multi_perform() that allows the
+ * application to pass in one of the file descriptors that have been
+ * detected to have "action" on them and let libcurl perform.
+ * See man page for details.
+ */
+#define CURL_POLL_NONE 0
+#define CURL_POLL_IN 1
+#define CURL_POLL_OUT 2
+#define CURL_POLL_INOUT 3
+#define CURL_POLL_REMOVE 4
+
+#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
+
+#define CURL_CSELECT_IN 0x01
+#define CURL_CSELECT_OUT 0x02
+#define CURL_CSELECT_ERR 0x04
+
+typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int what, /* see above */
+ void *userp, /* private callback
+ pointer */
+ void *socketp); /* private socket
+ pointer */
+/*
+ * Name: curl_multi_timer_callback
+ *
+ * Desc: Called by libcurl whenever the library detects a change in the
+ * maximum number of milliseconds the app is allowed to wait before
+ * curl_multi_socket() or curl_multi_perform() must be called
+ * (to allow libcurl's timed events to take place).
+ *
+ * Returns: The callback should return zero.
+ */
+typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
+ long timeout_ms, /* see above */
+ void *userp); /* private callback
+ pointer */
+
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
+ curl_socket_t s,
+ int ev_bitmask,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+ int *running_handles);
+
+#if !defined(CURL_ALLOW_OLD_MULTI_SOCKET) && !defined(BUILDING_LIBCURL)
+/* This macro below was added in 7.16.3 to push users who recompile to use
+ the new curl_multi_socket_action() instead of the old curl_multi_socket()
+*/
+#undef curl_multi_socket
+#define curl_multi_socket(x,y,z) sk_expand(curl_multi_socket_action)(x,y,0,z)
+#endif
+
+/*
+ * Name: curl_multi_timeout()
+ *
+ * Desc: Returns the maximum number of milliseconds the app is allowed to
+ * wait before curl_multi_socket() or curl_multi_perform() must be
+ * called (to allow libcurl's timed events to take place).
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+ long *milliseconds);
+
+#undef CINIT /* re-using the same name as in curl.h */
+
+#ifdef CURL_ISOCPP
+#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
+#endif
+
+typedef enum {
+ /* This is the socket callback function pointer */
+ CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+
+ /* This is the argument passed to the socket callback */
+ CINIT(SOCKETDATA, OBJECTPOINT, 2),
+
+ /* set to 1 to enable pipelining for this multi handle */
+ CINIT(PIPELINING, LONG, 3),
+
+ /* This is the timer callback function pointer */
+ CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+
+ /* This is the argument passed to the timer callback */
+ CINIT(TIMERDATA, OBJECTPOINT, 5),
+
+ /* maximum number of entries in the connection cache */
+ CINIT(MAXCONNECTS, LONG, 6),
+
+ /* maximum number of (pipelining) connections to one host */
+ CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
+
+ /* maximum number of requests in a pipeline */
+ CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
+
+ /* a connection with a content-length longer than this
+ will not be considered for pipelining */
+ CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
+
+ /* a connection with a chunk length longer than this
+ will not be considered for pipelining */
+ CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
+
+ /* a list of site names(+port) that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
+
+ /* a list of server types that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
+
+ /* maximum number of open connections in total */
+ CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
+
+ CURLMOPT_LASTENTRY /* the last unused */
+} CURLMoption;
+
+
+/*
+ * Name: curl_multi_setopt()
+ *
+ * Desc: Sets options for the multi handle.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+ CURLMoption option, ...);
+
+
+/*
+ * Name: curl_multi_assign()
+ *
+ * Desc: This function sets an association in the multi handle between the
+ * given socket and a private pointer of the application. This is
+ * (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd, void *sockp);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/libcurl/src/include/curl/stdcheaders.h b/libcurl/src/include/curl/stdcheaders.h
new file mode 100644
index 0000000..ad82ef6
--- /dev/null
+++ b/libcurl/src/include/curl/stdcheaders.h
@@ -0,0 +1,33 @@
+#ifndef __STDC_HEADERS_H
+#define __STDC_HEADERS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <sys/types.h>
+
+size_t fread (void *, size_t, size_t, FILE *);
+size_t fwrite (const void *, size_t, size_t, FILE *);
+
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size_t);
+
+#endif /* __STDC_HEADERS_H */
diff --git a/libcurl/src/include/curl/typecheck-gcc.h b/libcurl/src/include/curl/typecheck-gcc.h
new file mode 100644
index 0000000..69d41a2
--- /dev/null
+++ b/libcurl/src/include/curl/typecheck-gcc.h
@@ -0,0 +1,610 @@
+#ifndef __CURL_TYPECHECK_GCC_H
+#define __CURL_TYPECHECK_GCC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* wraps curl_easy_setopt() with typechecking */
+
+/* To add a new kind of warning, add an
+ * if(_curl_is_sometype_option(_curl_opt))
+ * if(!_curl_is_sometype(value))
+ * _curl_easy_setopt_err_sometype();
+ * block and define _curl_is_sometype_option, _curl_is_sometype and
+ * _curl_easy_setopt_err_sometype below
+ *
+ * NOTE: We use two nested 'if' statements here instead of the && operator, in
+ * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
+ * when compiling with -Wlogical-op.
+ *
+ * To add an option that uses the same type as an existing option, you'll just
+ * need to extend the appropriate _curl_*_option macro
+ */
+#define curl_easy_setopt(handle, option, value) \
+__extension__ ({ \
+ __typeof__ (option) _curl_opt = option; \
+ if(__builtin_constant_p(_curl_opt)) { \
+ if(_curl_is_long_option(_curl_opt)) \
+ if(!_curl_is_long(value)) \
+ _curl_easy_setopt_err_long(); \
+ if(_curl_is_off_t_option(_curl_opt)) \
+ if(!_curl_is_off_t(value)) \
+ _curl_easy_setopt_err_curl_off_t(); \
+ if(_curl_is_string_option(_curl_opt)) \
+ if(!_curl_is_string(value)) \
+ _curl_easy_setopt_err_string(); \
+ if(_curl_is_write_cb_option(_curl_opt)) \
+ if(!_curl_is_write_cb(value)) \
+ _curl_easy_setopt_err_write_callback(); \
+ if((_curl_opt) == CURLOPT_READFUNCTION) \
+ if(!_curl_is_read_cb(value)) \
+ _curl_easy_setopt_err_read_cb(); \
+ if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
+ if(!_curl_is_ioctl_cb(value)) \
+ _curl_easy_setopt_err_ioctl_cb(); \
+ if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
+ if(!_curl_is_sockopt_cb(value)) \
+ _curl_easy_setopt_err_sockopt_cb(); \
+ if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
+ if(!_curl_is_opensocket_cb(value)) \
+ _curl_easy_setopt_err_opensocket_cb(); \
+ if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
+ if(!_curl_is_progress_cb(value)) \
+ _curl_easy_setopt_err_progress_cb(); \
+ if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
+ if(!_curl_is_debug_cb(value)) \
+ _curl_easy_setopt_err_debug_cb(); \
+ if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
+ if(!_curl_is_ssl_ctx_cb(value)) \
+ _curl_easy_setopt_err_ssl_ctx_cb(); \
+ if(_curl_is_conv_cb_option(_curl_opt)) \
+ if(!_curl_is_conv_cb(value)) \
+ _curl_easy_setopt_err_conv_cb(); \
+ if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
+ if(!_curl_is_seek_cb(value)) \
+ _curl_easy_setopt_err_seek_cb(); \
+ if(_curl_is_cb_data_option(_curl_opt)) \
+ if(!_curl_is_cb_data(value)) \
+ _curl_easy_setopt_err_cb_data(); \
+ if((_curl_opt) == CURLOPT_ERRORBUFFER) \
+ if(!_curl_is_error_buffer(value)) \
+ _curl_easy_setopt_err_error_buffer(); \
+ if((_curl_opt) == CURLOPT_STDERR) \
+ if(!_curl_is_FILE(value)) \
+ _curl_easy_setopt_err_FILE(); \
+ if(_curl_is_postfields_option(_curl_opt)) \
+ if(!_curl_is_postfields(value)) \
+ _curl_easy_setopt_err_postfields(); \
+ if((_curl_opt) == CURLOPT_HTTPPOST) \
+ if(!_curl_is_arr((value), struct curl_httppost)) \
+ _curl_easy_setopt_err_curl_httpost(); \
+ if(_curl_is_slist_option(_curl_opt)) \
+ if(!_curl_is_arr((value), struct curl_slist)) \
+ _curl_easy_setopt_err_curl_slist(); \
+ if((_curl_opt) == CURLOPT_SHARE) \
+ if(!_curl_is_ptr((value), CURLSH)) \
+ _curl_easy_setopt_err_CURLSH(); \
+ } \
+ curl_easy_setopt(handle, _curl_opt, value); \
+})
+
+/* wraps curl_easy_getinfo() with typechecking */
+/* FIXME: don't allow const pointers */
+#define curl_easy_getinfo(handle, info, arg) \
+__extension__ ({ \
+ __typeof__ (info) _curl_info = info; \
+ if(__builtin_constant_p(_curl_info)) { \
+ if(_curl_is_string_info(_curl_info)) \
+ if(!_curl_is_arr((arg), char *)) \
+ _curl_easy_getinfo_err_string(); \
+ if(_curl_is_long_info(_curl_info)) \
+ if(!_curl_is_arr((arg), long)) \
+ _curl_easy_getinfo_err_long(); \
+ if(_curl_is_double_info(_curl_info)) \
+ if(!_curl_is_arr((arg), double)) \
+ _curl_easy_getinfo_err_double(); \
+ if(_curl_is_slist_info(_curl_info)) \
+ if(!_curl_is_arr((arg), struct curl_slist *)) \
+ _curl_easy_getinfo_err_curl_slist(); \
+ } \
+ curl_easy_getinfo(handle, _curl_info, arg); \
+})
+
+/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
+ * for now just make sure that the functions are called with three
+ * arguments
+ */
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+
+
+/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
+ * functions */
+
+/* To define a new warning, use _CURL_WARNING(identifier, "message") */
+#define _CURL_WARNING(id, message) \
+ static void __attribute__((__warning__(message))) \
+ __attribute__((__unused__)) __attribute__((__noinline__)) \
+ id(void) { __asm__(""); }
+
+_CURL_WARNING(_curl_easy_setopt_err_long,
+ "curl_easy_setopt expects a long argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
+ "curl_easy_setopt expects a curl_off_t argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_string,
+ "curl_easy_setopt expects a "
+ "string (char* or char[]) argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_write_callback,
+ "curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_read_cb,
+ "curl_easy_setopt expects a curl_read_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
+ "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
+ "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
+ "curl_easy_setopt expects a "
+ "curl_opensocket_callback argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
+ "curl_easy_setopt expects a curl_progress_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
+ "curl_easy_setopt expects a curl_debug_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
+ "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
+ "curl_easy_setopt expects a curl_conv_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
+ "curl_easy_setopt expects a curl_seek_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_cb_data,
+ "curl_easy_setopt expects a "
+ "private data pointer as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
+ "curl_easy_setopt expects a "
+ "char buffer of CURL_ERROR_SIZE as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_FILE,
+ "curl_easy_setopt expects a FILE* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_postfields,
+ "curl_easy_setopt expects a void* or char* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
+ "curl_easy_setopt expects a struct curl_httppost* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
+ "curl_easy_setopt expects a struct curl_slist* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
+ "curl_easy_setopt expects a CURLSH* argument for this option")
+
+_CURL_WARNING(_curl_easy_getinfo_err_string,
+ "curl_easy_getinfo expects a pointer to char * for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_long,
+ "curl_easy_getinfo expects a pointer to long for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_double,
+ "curl_easy_getinfo expects a pointer to double for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+ "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+
+/* groups of curl_easy_setops options that take the same type of argument */
+
+/* To add a new option to one of the groups, just add
+ * (option) == CURLOPT_SOMETHING
+ * to the or-expression. If the option takes a long or curl_off_t, you don't
+ * have to do anything
+ */
+
+/* evaluates to true if option takes a long argument */
+#define _curl_is_long_option(option) \
+ (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
+
+#define _curl_is_off_t_option(option) \
+ ((option) > CURLOPTTYPE_OFF_T)
+
+/* evaluates to true if option takes a char* argument */
+#define _curl_is_string_option(option) \
+ ((option) == CURLOPT_URL || \
+ (option) == CURLOPT_PROXY || \
+ (option) == CURLOPT_INTERFACE || \
+ (option) == CURLOPT_NETRC_FILE || \
+ (option) == CURLOPT_USERPWD || \
+ (option) == CURLOPT_USERNAME || \
+ (option) == CURLOPT_PASSWORD || \
+ (option) == CURLOPT_PROXYUSERPWD || \
+ (option) == CURLOPT_PROXYUSERNAME || \
+ (option) == CURLOPT_PROXYPASSWORD || \
+ (option) == CURLOPT_NOPROXY || \
+ (option) == CURLOPT_ACCEPT_ENCODING || \
+ (option) == CURLOPT_REFERER || \
+ (option) == CURLOPT_USERAGENT || \
+ (option) == CURLOPT_COOKIE || \
+ (option) == CURLOPT_COOKIEFILE || \
+ (option) == CURLOPT_COOKIEJAR || \
+ (option) == CURLOPT_COOKIELIST || \
+ (option) == CURLOPT_FTPPORT || \
+ (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_FTP_ACCOUNT || \
+ (option) == CURLOPT_RANGE || \
+ (option) == CURLOPT_CUSTOMREQUEST || \
+ (option) == CURLOPT_SSLCERT || \
+ (option) == CURLOPT_SSLCERTTYPE || \
+ (option) == CURLOPT_SSLKEY || \
+ (option) == CURLOPT_SSLKEYTYPE || \
+ (option) == CURLOPT_KEYPASSWD || \
+ (option) == CURLOPT_SSLENGINE || \
+ (option) == CURLOPT_CAINFO || \
+ (option) == CURLOPT_CAPATH || \
+ (option) == CURLOPT_RANDOM_FILE || \
+ (option) == CURLOPT_EGDSOCKET || \
+ (option) == CURLOPT_SSL_CIPHER_LIST || \
+ (option) == CURLOPT_KRBLEVEL || \
+ (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
+ (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
+ (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
+ (option) == CURLOPT_CRLFILE || \
+ (option) == CURLOPT_ISSUERCERT || \
+ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
+ (option) == CURLOPT_SSH_KNOWNHOSTS || \
+ (option) == CURLOPT_MAIL_FROM || \
+ (option) == CURLOPT_RTSP_SESSION_ID || \
+ (option) == CURLOPT_RTSP_STREAM_URI || \
+ (option) == CURLOPT_RTSP_TRANSPORT || \
+ (option) == CURLOPT_XOAUTH2_BEARER || \
+ (option) == CURLOPT_DNS_SERVERS || \
+ (option) == CURLOPT_DNS_INTERFACE || \
+ (option) == CURLOPT_DNS_LOCAL_IP4 || \
+ (option) == CURLOPT_DNS_LOCAL_IP6 || \
+ (option) == CURLOPT_LOGIN_OPTIONS || \
+ 0)
+
+/* evaluates to true if option takes a curl_write_callback argument */
+#define _curl_is_write_cb_option(option) \
+ ((option) == CURLOPT_HEADERFUNCTION || \
+ (option) == CURLOPT_WRITEFUNCTION)
+
+/* evaluates to true if option takes a curl_conv_callback argument */
+#define _curl_is_conv_cb_option(option) \
+ ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
+
+/* evaluates to true if option takes a data argument to pass to a callback */
+#define _curl_is_cb_data_option(option) \
+ ((option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_READDATA || \
+ (option) == CURLOPT_IOCTLDATA || \
+ (option) == CURLOPT_SOCKOPTDATA || \
+ (option) == CURLOPT_OPENSOCKETDATA || \
+ (option) == CURLOPT_PROGRESSDATA || \
+ (option) == CURLOPT_HEADERDATA || \
+ (option) == CURLOPT_DEBUGDATA || \
+ (option) == CURLOPT_SSL_CTX_DATA || \
+ (option) == CURLOPT_SEEKDATA || \
+ (option) == CURLOPT_PRIVATE || \
+ (option) == CURLOPT_SSH_KEYDATA || \
+ (option) == CURLOPT_INTERLEAVEDATA || \
+ (option) == CURLOPT_CHUNK_DATA || \
+ (option) == CURLOPT_FNMATCH_DATA || \
+ 0)
+
+/* evaluates to true if option takes a POST data argument (void* or char*) */
+#define _curl_is_postfields_option(option) \
+ ((option) == CURLOPT_POSTFIELDS || \
+ (option) == CURLOPT_COPYPOSTFIELDS || \
+ 0)
+
+/* evaluates to true if option takes a struct curl_slist * argument */
+#define _curl_is_slist_option(option) \
+ ((option) == CURLOPT_HTTPHEADER || \
+ (option) == CURLOPT_HTTP200ALIASES || \
+ (option) == CURLOPT_QUOTE || \
+ (option) == CURLOPT_POSTQUOTE || \
+ (option) == CURLOPT_PREQUOTE || \
+ (option) == CURLOPT_TELNETOPTIONS || \
+ (option) == CURLOPT_MAIL_RCPT || \
+ 0)
+
+/* groups of curl_easy_getinfo infos that take the same type of argument */
+
+/* evaluates to true if info expects a pointer to char * argument */
+#define _curl_is_string_info(info) \
+ (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+
+/* evaluates to true if info expects a pointer to long argument */
+#define _curl_is_long_info(info) \
+ (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+/* evaluates to true if info expects a pointer to double argument */
+#define _curl_is_double_info(info) \
+ (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+/* true if info expects a pointer to struct curl_slist * argument */
+#define _curl_is_slist_info(info) \
+ (CURLINFO_SLIST < (info))
+
+
+/* typecheck helpers -- check whether given expression has requested type*/
+
+/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
+ */
+
+/* XXX: should evaluate to true iff expr is a pointer */
+#define _curl_is_any_ptr(expr) \
+ (sizeof(expr) == sizeof(void*))
+
+/* evaluates to true if expr is NULL */
+/* XXX: must not evaluate expr, so this check is not accurate */
+#define _curl_is_NULL(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
+
+/* evaluates to true if expr is type*, const type* or NULL */
+#define _curl_is_ptr(expr, type) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), type *) || \
+ __builtin_types_compatible_p(__typeof__(expr), const type *))
+
+/* evaluates to true if expr is one of type[], type*, NULL or const type* */
+#define _curl_is_arr(expr, type) \
+ (_curl_is_ptr((expr), type) || \
+ __builtin_types_compatible_p(__typeof__(expr), type []))
+
+/* evaluates to true if expr is a string */
+#define _curl_is_string(expr) \
+ (_curl_is_arr((expr), char) || \
+ _curl_is_arr((expr), signed char) || \
+ _curl_is_arr((expr), unsigned char))
+
+/* evaluates to true if expr is a long (no matter the signedness)
+ * XXX: for now, int is also accepted (and therefore short and char, which
+ * are promoted to int when passed to a variadic function) */
+#define _curl_is_long(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), long) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed long) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
+ __builtin_types_compatible_p(__typeof__(expr), int) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed int) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
+ __builtin_types_compatible_p(__typeof__(expr), short) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed short) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
+ __builtin_types_compatible_p(__typeof__(expr), char) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed char) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned char))
+
+/* evaluates to true if expr is of type curl_off_t */
+#define _curl_is_off_t(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
+
+/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
+/* XXX: also check size of an char[] array? */
+#define _curl_is_error_buffer(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), char *) || \
+ __builtin_types_compatible_p(__typeof__(expr), char[]))
+
+/* evaluates to true if expr is of type (const) void* or (const) FILE* */
+#if 0
+#define _curl_is_cb_data(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_ptr((expr), FILE))
+#else /* be less strict */
+#define _curl_is_cb_data(expr) \
+ _curl_is_any_ptr(expr)
+#endif
+
+/* evaluates to true if expr is of type FILE* */
+#define _curl_is_FILE(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), FILE *))
+
+/* evaluates to true if expr can be passed as POST data (void* or char*) */
+#define _curl_is_postfields(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_arr((expr), char))
+
+/* FIXME: the whole callback checking is messy...
+ * The idea is to tolerate char vs. void and const vs. not const
+ * pointers in arguments at least
+ */
+/* helper: __builtin_types_compatible_p distinguishes between functions and
+ * function pointers, hide it */
+#define _curl_callback_compatible(func, type) \
+ (__builtin_types_compatible_p(__typeof__(func), type) || \
+ __builtin_types_compatible_p(__typeof__(func), type*))
+
+/* evaluates to true if expr is of type curl_read_callback or "similar" */
+#define _curl_is_read_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
+ _curl_callback_compatible((expr), _curl_read_callback1) || \
+ _curl_callback_compatible((expr), _curl_read_callback2) || \
+ _curl_callback_compatible((expr), _curl_read_callback3) || \
+ _curl_callback_compatible((expr), _curl_read_callback4) || \
+ _curl_callback_compatible((expr), _curl_read_callback5) || \
+ _curl_callback_compatible((expr), _curl_read_callback6))
+typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
+typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_write_callback or "similar" */
+#define _curl_is_write_cb(expr) \
+ (_curl_is_read_cb(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
+ _curl_callback_compatible((expr), _curl_write_callback1) || \
+ _curl_callback_compatible((expr), _curl_write_callback2) || \
+ _curl_callback_compatible((expr), _curl_write_callback3) || \
+ _curl_callback_compatible((expr), _curl_write_callback4) || \
+ _curl_callback_compatible((expr), _curl_write_callback5) || \
+ _curl_callback_compatible((expr), _curl_write_callback6))
+typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
+ const void*);
+typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
+typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
+ const void*);
+typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
+#define _curl_is_ioctl_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback1) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback2) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback3) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback4))
+typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
+typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
+typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
+typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
+
+/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
+#define _curl_is_sockopt_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback1) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback2))
+typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
+ curlsocktype);
+
+/* evaluates to true if expr is of type curl_opensocket_callback or
+ "similar" */
+#define _curl_is_opensocket_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
+ _curl_callback_compatible((expr), _curl_opensocket_callback1) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback2) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback3) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback4))
+typedef curl_socket_t (_curl_opensocket_callback1)
+ (void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback2)
+ (void *, curlsocktype, const struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback3)
+ (const void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback4)
+ (const void *, curlsocktype, const struct curl_sockaddr *);
+
+/* evaluates to true if expr is of type curl_progress_callback or "similar" */
+#define _curl_is_progress_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
+ _curl_callback_compatible((expr), _curl_progress_callback1) || \
+ _curl_callback_compatible((expr), _curl_progress_callback2))
+typedef int (_curl_progress_callback1)(void *,
+ double, double, double, double);
+typedef int (_curl_progress_callback2)(const void *,
+ double, double, double, double);
+
+/* evaluates to true if expr is of type curl_debug_callback or "similar" */
+#define _curl_is_debug_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
+ _curl_callback_compatible((expr), _curl_debug_callback1) || \
+ _curl_callback_compatible((expr), _curl_debug_callback2) || \
+ _curl_callback_compatible((expr), _curl_debug_callback3) || \
+ _curl_callback_compatible((expr), _curl_debug_callback4) || \
+ _curl_callback_compatible((expr), _curl_debug_callback5) || \
+ _curl_callback_compatible((expr), _curl_debug_callback6) || \
+ _curl_callback_compatible((expr), _curl_debug_callback7) || \
+ _curl_callback_compatible((expr), _curl_debug_callback8))
+typedef int (_curl_debug_callback1) (CURL *,
+ curl_infotype, char *, size_t, void *);
+typedef int (_curl_debug_callback2) (CURL *,
+ curl_infotype, char *, size_t, const void *);
+typedef int (_curl_debug_callback3) (CURL *,
+ curl_infotype, const char *, size_t, void *);
+typedef int (_curl_debug_callback4) (CURL *,
+ curl_infotype, const char *, size_t, const void *);
+typedef int (_curl_debug_callback5) (CURL *,
+ curl_infotype, unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback6) (CURL *,
+ curl_infotype, unsigned char *, size_t, const void *);
+typedef int (_curl_debug_callback7) (CURL *,
+ curl_infotype, const unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback8) (CURL *,
+ curl_infotype, const unsigned char *, size_t, const void *);
+
+/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
+/* this is getting even messier... */
+#define _curl_is_ssl_ctx_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
+typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
+#ifdef HEADER_SSL_H
+/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
+ * this will of course break if we're included before OpenSSL headers...
+ */
+typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+ const void *);
+#else
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
+#endif
+
+/* evaluates to true if expr is of type curl_conv_callback or "similar" */
+#define _curl_is_conv_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
+ _curl_callback_compatible((expr), _curl_conv_callback1) || \
+ _curl_callback_compatible((expr), _curl_conv_callback2) || \
+ _curl_callback_compatible((expr), _curl_conv_callback3) || \
+ _curl_callback_compatible((expr), _curl_conv_callback4))
+typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
+typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
+typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
+typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
+
+/* evaluates to true if expr is of type curl_seek_callback or "similar" */
+#define _curl_is_seek_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
+ _curl_callback_compatible((expr), _curl_seek_callback1) || \
+ _curl_callback_compatible((expr), _curl_seek_callback2))
+typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
+typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
+
+
+#endif /* __CURL_TYPECHECK_GCC_H */
diff --git a/libcurl/src/lib/amigaos.c b/libcurl/src/lib/amigaos.c
new file mode 100644
index 0000000..10783b2
--- /dev/null
+++ b/libcurl/src/lib/amigaos.c
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(__AMIGA__) && !defined(__ixemul__)
+
+#include <amitcp/socketbasetags.h>
+
+#include "amigaos.h"
+
+struct Library *SocketBase = NULL;
+extern int errno, h_errno;
+
+#ifdef __libnix__
+#include <stabs.h>
+void __request(const char *msg);
+#else
+# define __request( msg ) Printf( msg "\n\a")
+#endif
+
+CURL_STATIC void Curl_amiga_cleanup()
+{
+ if(SocketBase) {
+ CloseLibrary(SocketBase);
+ SocketBase = NULL;
+ }
+}
+
+CURL_STATIC bool Curl_amiga_init()
+{
+ if(!SocketBase)
+ SocketBase = OpenLibrary("bsdsocket.library", 4);
+
+ if(!SocketBase) {
+ __request("No TCP/IP Stack running!");
+ return FALSE;
+ }
+
+ if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
+ SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
+ TAG_DONE)) {
+ __request("SocketBaseTags ERROR");
+ return FALSE;
+ }
+
+#ifndef __libnix__
+ atexit(Curl_amiga_cleanup);
+#endif
+
+ return TRUE;
+}
+
+#ifdef __libnix__
+ADD2EXIT(Curl_amiga_cleanup, -50);
+#endif
+
+#endif /* __AMIGA__ && ! __ixemul__ */
diff --git a/libcurl/src/lib/amigaos.h b/libcurl/src/lib/amigaos.h
new file mode 100644
index 0000000..7e61cab
--- /dev/null
+++ b/libcurl/src/lib/amigaos.h
@@ -0,0 +1,39 @@
+#ifndef HEADER_CURL_AMIGAOS_H
+#define HEADER_CURL_AMIGAOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(__AMIGA__) && !defined(__ixemul__)
+
+CURL_STATIC bool Curl_amiga_init();
+CURL_STATIC void Curl_amiga_cleanup();
+
+#else
+
+#define Curl_amiga_init() 1
+#define Curl_amiga_cleanup() Curl_nop_stmt
+
+#endif
+
+#endif /* HEADER_CURL_AMIGAOS_H */
+
diff --git a/libcurl/src/lib/arpa_telnet.h b/libcurl/src/lib/arpa_telnet.h
new file mode 100644
index 0000000..098d9a9
--- /dev/null
+++ b/libcurl/src/lib/arpa_telnet.h
@@ -0,0 +1,104 @@
+#ifndef HEADER_CURL_ARPA_TELNET_H
+#define HEADER_CURL_ARPA_TELNET_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_TELNET
+/*
+ * Telnet option defines. Add more here if in need.
+ */
+#define CURL_TELOPT_BINARY 0 /* binary 8bit data */
+#define CURL_TELOPT_ECHO 1 /* just echo! */
+#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */
+#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */
+#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */
+#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */
+#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
+
+#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */
+#define CURL_NEW_ENV_VAR 0
+#define CURL_NEW_ENV_VALUE 1
+
+/*
+ * The telnet options represented as strings
+ */
+static const char * const telnetoptions[]=
+{
+ "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD",
+ "NAME", "STATUS", "TIMING MARK", "RCTE",
+ "NAOL", "NAOP", "NAOCRD", "NAOHTS",
+ "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD",
+ "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+ "DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION",
+ "TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING",
+ "TTYLOC", "3270 REGIME", "X3 PAD", "NAWS",
+ "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
+ "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
+};
+
+#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
+
+#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
+#define CURL_TELOPT(x) telnetoptions[x]
+
+#define CURL_NTELOPTS 40
+
+/*
+ * First some defines
+ */
+#define CURL_xEOF 236 /* End Of File */
+#define CURL_SE 240 /* Sub negotiation End */
+#define CURL_NOP 241 /* No OPeration */
+#define CURL_DM 242 /* Data Mark */
+#define CURL_GA 249 /* Go Ahead, reverse the line */
+#define CURL_SB 250 /* SuBnegotiation */
+#define CURL_WILL 251 /* Our side WILL use this option */
+#define CURL_WONT 252 /* Our side WON'T use this option */
+#define CURL_DO 253 /* DO use this option! */
+#define CURL_DONT 254 /* DON'T use this option! */
+#define CURL_IAC 255 /* Interpret As Command */
+
+/*
+ * Then those numbers represented as strings:
+ */
+static const char * const telnetcmds[]=
+{
+ "EOF", "SUSP", "ABORT", "EOR", "SE",
+ "NOP", "DMARK", "BRK", "IP", "AO",
+ "AYT", "EC", "EL", "GA", "SB",
+ "WILL", "WONT", "DO", "DONT", "IAC"
+};
+
+#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */
+#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */
+
+#define CURL_TELQUAL_IS 0
+#define CURL_TELQUAL_SEND 1
+#define CURL_TELQUAL_INFO 2
+#define CURL_TELQUAL_NAME 3
+
+#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
+ ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
+#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
+
+#endif /* CURL_DISABLE_TELNET */
+
+#endif /* HEADER_CURL_ARPA_TELNET_H */
diff --git a/libcurl/src/lib/asyn-ares.c b/libcurl/src/lib/asyn-ares.c
new file mode 100644
index 0000000..4819a09
--- /dev/null
+++ b/libcurl/src/lib/asyn-ares.c
@@ -0,0 +1,691 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+/***********************************************************************
+ * Only for ares-enabled builds
+ * And only for functions that fulfill the asynch resolver backend API
+ * as defined in asyn.h, nothing else belongs in this file!
+ **********************************************************************/
+
+#ifdef CURLRES_ARES
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "multiif.h"
+#include "inet_pton.h"
+#include "connect.h"
+#include "select.h"
+#include "progress.h"
+#include "curl_printf.h"
+
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+# define CARES_STATICLIB
+# endif
+# include <ares.h>
+# include <ares_version.h> /* really old c-ares didn't include this by
+ itself */
+
+#if ARES_VERSION >= 0x010500
+/* c-ares 1.5.0 or later, the callback proto is modified */
+#define HAVE_CARES_CALLBACK_TIMEOUTS 1
+#endif
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+struct ResolverResults {
+ int num_pending; /* number of ares_gethostbyname() requests */
+ Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
+ int last_status;
+};
+
+/*
+ * Curl_resolver_global_init() - the generic low-level asynchronous name
+ * resolve API. Called from curl_global_init() to initialize global resolver
+ * environment. Initializes ares library.
+ */
+CURL_STATIC int Curl_resolver_global_init(void)
+{
+#ifdef CARES_HAVE_ARES_LIBRARY_INIT
+ if(ares_library_init(ARES_LIB_INIT_ALL)) {
+ return CURLE_FAILED_INIT;
+ }
+#endif
+ return CURLE_OK;
+}
+
+/*
+ * Curl_resolver_global_cleanup()
+ *
+ * Called from curl_global_cleanup() to destroy global resolver environment.
+ * Deinitializes ares library.
+ */
+CURL_STATIC void Curl_resolver_global_cleanup(void)
+{
+#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
+ ares_library_cleanup();
+#endif
+}
+
+/*
+ * Curl_resolver_init()
+ *
+ * Called from curl_easy_init() -> Curl_open() to initialize resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Fills the passed pointer by the initialized ares_channel.
+ */
+CURL_STATIC CURLcode Curl_resolver_init(void **resolver)
+{
+ int status = ares_init((ares_channel*)resolver);
+ if(status != ARES_SUCCESS) {
+ if(status == ARES_ENOMEM)
+ return CURLE_OUT_OF_MEMORY;
+ else
+ return CURLE_FAILED_INIT;
+ }
+ return CURLE_OK;
+ /* make sure that all other returns from this function should destroy the
+ ares channel before returning error! */
+}
+
+/*
+ * Curl_resolver_cleanup()
+ *
+ * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Destroys the ares channel.
+ */
+CURL_STATIC void Curl_resolver_cleanup(void *resolver)
+{
+ ares_destroy((ares_channel)resolver);
+}
+
+/*
+ * Curl_resolver_duphandle()
+ *
+ * Called from curl_easy_duphandle() to duplicate resolver URL-state specific
+ * environment ('resolver' member of the UrlState structure). Duplicates the
+ * 'from' ares channel and passes the resulting channel to the 'to' pointer.
+ */
+CURL_STATIC int Curl_resolver_duphandle(void **to, void *from)
+{
+ /* Clone the ares channel for the new handle */
+ if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from))
+ return CURLE_FAILED_INIT;
+ return CURLE_OK;
+}
+
+static void destroy_async_data (struct Curl_async *async);
+
+/*
+ * Cancel all possibly still on-going resolves for this connection.
+ */
+CURL_STATIC void Curl_resolver_cancel(struct connectdata *conn)
+{
+ if(conn->data && conn->data->state.resolver)
+ ares_cancel((ares_channel)conn->data->state.resolver);
+ destroy_async_data(&conn->async);
+}
+
+/*
+ * destroy_async_data() cleans up async resolver data.
+ */
+static void destroy_async_data (struct Curl_async *async)
+{
+ free(async->hostname);
+
+ if(async->os_specific) {
+ struct ResolverResults *res = (struct ResolverResults *)async->os_specific;
+ if(res) {
+ if(res->temp_ai) {
+ Curl_freeaddrinfo(res->temp_ai);
+ res->temp_ai = NULL;
+ }
+ free(res);
+ }
+ async->os_specific = NULL;
+ }
+
+ async->hostname = NULL;
+}
+
+/*
+ * Curl_resolver_getsock() is called when someone from the outside world
+ * (using curl_multi_fdset()) wants to get our fd_set setup and we're talking
+ * with ares. The caller must make sure that this function is only called when
+ * we have a working ares channel.
+ *
+ * Returns: sockets-in-use-bitmap
+ */
+
+CURL_STATIC int Curl_resolver_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+
+{
+ struct timeval maxtime;
+ struct timeval timebuf;
+ struct timeval *timeout;
+ long milli;
+ int max = ares_getsock((ares_channel)conn->data->state.resolver,
+ (ares_socket_t *)socks, numsocks);
+
+ maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
+ maxtime.tv_usec = 0;
+
+ timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime,
+ &timebuf);
+ milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
+ if(milli == 0)
+ milli += 10;
+ Curl_expire_latest(conn->data, milli);
+
+ return max;
+}
+
+/*
+ * waitperform()
+ *
+ * 1) Ask ares what sockets it currently plays with, then
+ * 2) wait for the timeout period to check for action on ares' sockets.
+ * 3) tell ares to act on all the sockets marked as "with action"
+ *
+ * return number of sockets it worked on
+ */
+
+static int waitperform(struct connectdata *conn, int timeout_ms)
+{
+ struct SessionHandle *data = conn->data;
+ int nfds;
+ int bitmask;
+ ares_socket_t socks[ARES_GETSOCK_MAXNUM];
+ struct pollfd pfd[ARES_GETSOCK_MAXNUM];
+ int i;
+ int num = 0;
+
+ bitmask = ares_getsock((ares_channel)data->state.resolver, socks,
+ ARES_GETSOCK_MAXNUM);
+
+ for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
+ pfd[i].events = 0;
+ pfd[i].revents = 0;
+ if(ARES_GETSOCK_READABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLRDNORM|POLLIN;
+ }
+ if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLWRNORM|POLLOUT;
+ }
+ if(pfd[i].events != 0)
+ num++;
+ else
+ break;
+ }
+
+ if(num)
+ nfds = Curl_poll(pfd, num, timeout_ms);
+ else
+ nfds = 0;
+
+ if(!nfds)
+ /* Call ares_process() unconditonally here, even if we simply timed out
+ above, as otherwise the ares name resolve won't timeout! */
+ ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD,
+ ARES_SOCKET_BAD);
+ else {
+ /* move through the descriptors and ask for processing on them */
+ for(i=0; i < num; i++)
+ ares_process_fd((ares_channel)data->state.resolver,
+ pfd[i].revents & (POLLRDNORM|POLLIN)?
+ pfd[i].fd:ARES_SOCKET_BAD,
+ pfd[i].revents & (POLLWRNORM|POLLOUT)?
+ pfd[i].fd:ARES_SOCKET_BAD);
+ }
+ return nfds;
+}
+
+/*
+ * Curl_resolver_is_resolved() is called repeatedly to check if a previous
+ * name resolve request has completed. It should also make sure to time-out if
+ * the operation seems to take too long.
+ *
+ * Returns normal CURLcode errors.
+ */
+CURL_STATIC CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dns)
+{
+ struct SessionHandle *data = conn->data;
+ struct ResolverResults *res = (struct ResolverResults *)
+ conn->async.os_specific;
+ CURLcode result = CURLE_OK;
+
+ *dns = NULL;
+
+ waitperform(conn, 0);
+
+ if(res && !res->num_pending) {
+ (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+ /* temp_ai ownership is moved to the connection, so we need not free-up
+ them */
+ res->temp_ai = NULL;
+ if(!conn->async.dns) {
+ failf(data, "Could not resolve: %s (%s)",
+ conn->async.hostname, ares_strerror(conn->async.status));
+ result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else
+ *dns = conn->async.dns;
+
+ destroy_async_data(&conn->async);
+ }
+
+ return result;
+}
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
+ */
+CURL_STATIC CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+ struct Curl_dns_entry **entry)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ long timeout;
+ struct timeval now = Curl_tvnow();
+ struct Curl_dns_entry *temp_entry;
+
+ timeout = Curl_timeleft(data, &now, TRUE);
+ if(!timeout)
+ timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
+
+ /* Wait for the name resolve query to complete. */
+ for(;;) {
+ struct timeval *tvp, tv, store;
+ long timediff;
+ int itimeout;
+ int timeout_ms;
+
+ itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
+
+ store.tv_sec = itimeout/1000;
+ store.tv_usec = (itimeout%1000)*1000;
+
+ tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv);
+
+ /* use the timeout period ares returned to us above if less than one
+ second is left, otherwise just use 1000ms to make sure the progress
+ callback gets called frequent enough */
+ if(!tvp->tv_sec)
+ timeout_ms = (int)(tvp->tv_usec/1000);
+ else
+ timeout_ms = 1000;
+
+ waitperform(conn, timeout_ms);
+ Curl_resolver_is_resolved(conn, &temp_entry);
+
+ if(conn->async.done)
+ break;
+
+ if(Curl_pgrsUpdate(conn)) {
+ result = CURLE_ABORTED_BY_CALLBACK;
+ timeout = -1; /* trigger the cancel below */
+ }
+ else {
+ struct timeval now2 = Curl_tvnow();
+ timediff = Curl_tvdiff(now2, now); /* spent time */
+ timeout -= timediff?timediff:1; /* always deduct at least 1 */
+ now = now2; /* for next loop */
+ }
+
+ if(timeout < 0) {
+ /* our timeout, so we cancel the ares operation */
+ ares_cancel((ares_channel)data->state.resolver);
+ break;
+ }
+ }
+
+ /* Operation complete, if the lookup was successful we now have the entry
+ in the cache. */
+ if(entry)
+ *entry = conn->async.dns;
+
+ if(result)
+ /* close the connection, since we can't return failure here without
+ cleaning up this connection properly.
+ TODO: remove this action from here, it is not a name resolver decision.
+ */
+ connclose(conn, "c-ares resolve failed");
+
+ return result;
+}
+
+/* Connects results to the list */
+static void compound_results(struct ResolverResults *res,
+ Curl_addrinfo *ai)
+{
+ Curl_addrinfo *ai_tail;
+ if(!ai)
+ return;
+ ai_tail = ai;
+
+ while(ai_tail->ai_next)
+ ai_tail = ai_tail->ai_next;
+
+ /* Add the new results to the list of old results. */
+ ai_tail->ai_next = res->temp_ai;
+ res->temp_ai = ai;
+}
+
+/*
+ * ares_query_completed_cb() is the callback that ares will call when
+ * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
+ * when using ares, is completed either successfully or with failure.
+ */
+static void query_completed_cb(void *arg, /* (struct connectdata *) */
+ int status,
+#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
+ int timeouts,
+#endif
+ struct hostent *hostent)
+{
+ struct connectdata *conn = (struct connectdata *)arg;
+ struct ResolverResults *res;
+
+#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
+ (void)timeouts; /* ignored */
+#endif
+
+ if(ARES_EDESTRUCTION == status)
+ /* when this ares handle is getting destroyed, the 'arg' pointer may not
+ be valid so only defer it when we know the 'status' says its fine! */
+ return;
+
+ res = (struct ResolverResults *)conn->async.os_specific;
+ res->num_pending--;
+
+ if(CURL_ASYNC_SUCCESS == status) {
+ Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+ if(ai) {
+ compound_results(res, ai);
+ }
+ }
+ /* A successful result overwrites any previous error */
+ if(res->last_status != ARES_SUCCESS)
+ res->last_status = status;
+}
+
+/*
+ * Curl_resolver_getaddrinfo() - when using ares
+ *
+ * Returns name information about the given hostname and port number. If
+ * successful, the 'hostent' is returned and the forth argument will point to
+ * memory we need to free after use. That memory *MUST* be freed with
+ * Curl_freeaddrinfo(), nothing else.
+ */
+CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ char *bufp;
+ struct SessionHandle *data = conn->data;
+ struct in_addr in;
+ int family = PF_INET;
+#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+ struct in6_addr in6;
+#endif /* CURLRES_IPV6 */
+
+ *waitp = 0; /* default to synchronous response */
+
+ /* First check if this is an IPv4 address string */
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+ }
+
+#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+ /* Otherwise, check if this is an IPv6 address string */
+ if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0)
+ /* This must be an IPv6 address literal. */
+ return Curl_ip2addr(AF_INET6, &in6, hostname, port);
+
+ switch(conn->ip_version) {
+ default:
+#if ARES_VERSION >= 0x010601
+ family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
+ c-ares versions this just falls through and defaults
+ to PF_INET */
+ break;
+#endif
+ case CURL_IPRESOLVE_V4:
+ family = PF_INET;
+ break;
+ case CURL_IPRESOLVE_V6:
+ family = PF_INET6;
+ break;
+ }
+#endif /* CURLRES_IPV6 */
+
+ bufp = strdup(hostname);
+ if(bufp) {
+ struct ResolverResults *res = NULL;
+ free(conn->async.hostname);
+ conn->async.hostname = bufp;
+ conn->async.port = port;
+ conn->async.done = FALSE; /* not done */
+ conn->async.status = 0; /* clear */
+ conn->async.dns = NULL; /* clear */
+ res = calloc(sizeof(struct ResolverResults), 1);
+ if(!res) {
+ free(conn->async.hostname);
+ conn->async.hostname = NULL;
+ return NULL;
+ }
+ conn->async.os_specific = res;
+
+ /* initial status - failed */
+ res->last_status = ARES_ENOTFOUND;
+#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+ if(family == PF_UNSPEC) {
+ if(Curl_ipv6works()) {
+ res->num_pending = 2;
+
+ /* areschannel is already setup in the Curl_open() function */
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname,
+ PF_INET, query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname,
+ PF_INET6, query_completed_cb, conn);
+ }
+ else {
+ res->num_pending = 1;
+
+ /* areschannel is already setup in the Curl_open() function */
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname,
+ PF_INET, query_completed_cb, conn);
+ }
+ }
+ else
+#endif /* CURLRES_IPV6 */
+ {
+ res->num_pending = 1;
+
+ /* areschannel is already setup in the Curl_open() function */
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname, family,
+ query_completed_cb, conn);
+ }
+
+ *waitp = 1; /* expect asynchronous response */
+ }
+ return NULL; /* no struct yet */
+}
+
+CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data,
+ char *servers)
+{
+ CURLcode result = CURLE_NOT_BUILT_IN;
+ int ares_result;
+
+ /* If server is NULL or empty, this would purge all DNS servers
+ * from ares library, which will cause any and all queries to fail.
+ * So, just return OK if none are configured and don't actually make
+ * any changes to c-ares. This lets c-ares use it's defaults, which
+ * it gets from the OS (for instance from /etc/resolv.conf on Linux).
+ */
+ if(!(servers && servers[0]))
+ return CURLE_OK;
+
+#if (ARES_VERSION >= 0x010704)
+ ares_result = ares_set_servers_csv(data->state.resolver, servers);
+ switch(ares_result) {
+ case ARES_SUCCESS:
+ result = CURLE_OK;
+ break;
+ case ARES_ENOMEM:
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ case ARES_ENOTINITIALIZED:
+ case ARES_ENODATA:
+ case ARES_EBADSTR:
+ default:
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ break;
+ }
+#else /* too old c-ares version! */
+ (void)data;
+ (void)(ares_result);
+#endif
+ return result;
+}
+
+CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf)
+{
+#if (ARES_VERSION >= 0x010704)
+ if(!interf)
+ interf = "";
+
+ ares_set_local_dev((ares_channel)data->state.resolver, interf);
+
+ return CURLE_OK;
+#else /* c-ares version too old! */
+ (void)data;
+ (void)interf;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4)
+{
+#if (ARES_VERSION >= 0x010704)
+ struct in_addr a4;
+
+ if((!local_ip4) || (local_ip4[0] == 0)) {
+ a4.s_addr = 0; /* disabled: do not bind to a specific address */
+ }
+ else {
+ if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+
+ ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr));
+
+ return CURLE_OK;
+#else /* c-ares version too old! */
+ (void)data;
+ (void)local_ip4;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6)
+{
+#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6)
+ unsigned char a6[INET6_ADDRSTRLEN];
+
+ if((!local_ip6) || (local_ip6[0] == 0)) {
+ /* disabled: do not bind to a specific address */
+ memset(a6, 0, sizeof(a6));
+ }
+ else {
+ if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+
+ ares_set_local_ip6((ares_channel)data->state.resolver, a6);
+
+ return CURLE_OK;
+#else /* c-ares version too old! */
+ (void)data;
+ (void)local_ip6;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+#endif /* CURLRES_ARES */
diff --git a/libcurl/src/lib/asyn-thread.c b/libcurl/src/lib/asyn-thread.c
new file mode 100644
index 0000000..3737bff
--- /dev/null
+++ b/libcurl/src/lib/asyn-thread.c
@@ -0,0 +1,698 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if defined(USE_THREADS_POSIX)
+# ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+# endif
+#elif defined(USE_THREADS_WIN32)
+# ifdef HAVE_PROCESS_H
+# include <process.h>
+# endif
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#ifdef HAVE_GETADDRINFO
+# define RESOLVER_ENOMEM EAI_MEMORY
+#else
+# define RESOLVER_ENOMEM ENOMEM
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "multiif.h"
+#include "inet_pton.h"
+#include "inet_ntop.h"
+#include "curl_threads.h"
+#include "connect.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for threaded name resolves builds
+ **********************************************************************/
+#ifdef CURLRES_THREADED
+
+/*
+ * Curl_resolver_global_init()
+ * Called from curl_global_init() to initialize global resolver environment.
+ * Does nothing here.
+ */
+CURL_STATIC int Curl_resolver_global_init(void)
+{
+ return CURLE_OK;
+}
+
+/*
+ * Curl_resolver_global_cleanup()
+ * Called from curl_global_cleanup() to destroy global resolver environment.
+ * Does nothing here.
+ */
+CURL_STATIC void Curl_resolver_global_cleanup(void)
+{
+}
+
+/*
+ * Curl_resolver_init()
+ * Called from curl_easy_init() -> Curl_open() to initialize resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Does nothing here.
+ */
+CURL_STATIC CURLcode Curl_resolver_init(void **resolver)
+{
+ (void)resolver;
+ return CURLE_OK;
+}
+
+/*
+ * Curl_resolver_cleanup()
+ * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Does nothing here.
+ */
+CURL_STATIC void Curl_resolver_cleanup(void *resolver)
+{
+ (void)resolver;
+}
+
+/*
+ * Curl_resolver_duphandle()
+ * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
+ * environment ('resolver' member of the UrlState structure). Does nothing
+ * here.
+ */
+CURL_STATIC int Curl_resolver_duphandle(void **to, void *from)
+{
+ (void)to;
+ (void)from;
+ return CURLE_OK;
+}
+
+static void destroy_async_data(struct Curl_async *);
+
+/*
+ * Cancel all possibly still on-going resolves for this connection.
+ */
+CURL_STATIC void Curl_resolver_cancel(struct connectdata *conn)
+{
+ destroy_async_data(&conn->async);
+}
+
+/* This function is used to init a threaded resolve */
+static bool init_resolve_thread(struct connectdata *conn,
+ const char *hostname, int port,
+ const struct addrinfo *hints);
+
+
+/* Data for synchronization between resolver thread and its parent */
+struct thread_sync_data {
+ curl_mutex_t * mtx;
+ int done;
+
+ char * hostname; /* hostname to resolve, Curl_async.hostname
+ duplicate */
+ int port;
+ int sock_error;
+ Curl_addrinfo *res;
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints;
+#endif
+ struct thread_data *td; /* for thread-self cleanup */
+};
+
+struct thread_data {
+ curl_thread_t thread_hnd;
+ unsigned int poll_interval;
+ long interval_end;
+ struct thread_sync_data tsd;
+};
+
+static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
+{
+ return &(((struct thread_data *)conn->async.os_specific)->tsd);
+}
+
+#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd);
+
+/* Destroy resolver thread synchronization data */
+static
+void destroy_thread_sync_data(struct thread_sync_data * tsd)
+{
+ if(tsd->mtx) {
+ Curl_mutex_destroy(tsd->mtx);
+ free(tsd->mtx);
+ }
+
+ free(tsd->hostname);
+
+ if(tsd->res)
+ Curl_freeaddrinfo(tsd->res);
+
+ memset(tsd, 0, sizeof(*tsd));
+}
+
+/* Initialize resolver thread synchronization data */
+static
+int init_thread_sync_data(struct thread_data * td,
+ const char * hostname,
+ int port,
+ const struct addrinfo *hints)
+{
+ struct thread_sync_data *tsd = &td->tsd;
+
+ memset(tsd, 0, sizeof(*tsd));
+
+ tsd->td = td;
+ tsd->port = port;
+#ifdef HAVE_GETADDRINFO
+ DEBUGASSERT(hints);
+ tsd->hints = *hints;
+#else
+ (void) hints;
+#endif
+
+ tsd->mtx = malloc(sizeof(curl_mutex_t));
+ if(tsd->mtx == NULL)
+ goto err_exit;
+
+ Curl_mutex_init(tsd->mtx);
+
+ tsd->sock_error = CURL_ASYNC_SUCCESS;
+
+ /* Copying hostname string because original can be destroyed by parent
+ * thread during gethostbyname execution.
+ */
+ tsd->hostname = strdup(hostname);
+ if(!tsd->hostname)
+ goto err_exit;
+
+ return 1;
+
+ err_exit:
+ /* Memory allocation failed */
+ destroy_thread_sync_data(tsd);
+ return 0;
+}
+
+static int getaddrinfo_complete(struct connectdata *conn)
+{
+ struct thread_sync_data *tsd = conn_thread_sync_data(conn);
+ int rc;
+
+ rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res);
+ /* The tsd->res structure has been copied to async.dns and perhaps the DNS
+ cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
+ */
+ tsd->res = NULL;
+
+ return rc;
+}
+
+
+#ifdef HAVE_GETADDRINFO
+
+/*
+ * getaddrinfo_thread() resolves a name and then exits.
+ *
+ * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
+ * and wait on it.
+ */
+static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
+{
+ struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
+ struct thread_data *td = tsd->td;
+ char service[12];
+ int rc;
+
+ snprintf(service, sizeof(service), "%d", tsd->port);
+
+ rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
+
+ if(rc != 0) {
+ tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
+ if(tsd->sock_error == 0)
+ tsd->sock_error = RESOLVER_ENOMEM;
+ }
+
+ Curl_mutex_acquire(tsd->mtx);
+ if(tsd->done) {
+ /* too late, gotta clean up the mess */
+ Curl_mutex_release(tsd->mtx);
+ destroy_thread_sync_data(tsd);
+ free(td);
+ }
+ else {
+ tsd->done = 1;
+ Curl_mutex_release(tsd->mtx);
+ }
+
+ return 0;
+}
+
+#else /* HAVE_GETADDRINFO */
+
+/*
+ * gethostbyname_thread() resolves a name and then exits.
+ */
+static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
+{
+ struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
+ struct thread_data *td = tsd->td;
+
+ tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
+
+ if(!tsd->res) {
+ tsd->sock_error = SOCKERRNO;
+ if(tsd->sock_error == 0)
+ tsd->sock_error = RESOLVER_ENOMEM;
+ }
+
+ Curl_mutex_acquire(tsd->mtx);
+ if(tsd->done) {
+ /* too late, gotta clean up the mess */
+ Curl_mutex_release(tsd->mtx);
+ destroy_thread_sync_data(tsd);
+ free(td);
+ }
+ else {
+ tsd->done = 1;
+ Curl_mutex_release(tsd->mtx);
+ }
+
+ return 0;
+}
+
+#endif /* HAVE_GETADDRINFO */
+
+/*
+ * destroy_async_data() cleans up async resolver data and thread handle.
+ */
+static void destroy_async_data (struct Curl_async *async)
+{
+ if(async->os_specific) {
+ struct thread_data *td = (struct thread_data*) async->os_specific;
+ int done;
+
+ /*
+ * if the thread is still blocking in the resolve syscall, detach it and
+ * let the thread do the cleanup...
+ */
+ Curl_mutex_acquire(td->tsd.mtx);
+ done = td->tsd.done;
+ td->tsd.done = 1;
+ Curl_mutex_release(td->tsd.mtx);
+
+ if(!done) {
+ Curl_thread_destroy(td->thread_hnd);
+ }
+ else {
+ if(td->thread_hnd != curl_thread_t_null)
+ Curl_thread_join(&td->thread_hnd);
+
+ destroy_thread_sync_data(&td->tsd);
+
+ free(async->os_specific);
+ }
+ }
+ async->os_specific = NULL;
+
+ free(async->hostname);
+ async->hostname = NULL;
+}
+
+/*
+ * init_resolve_thread() starts a new thread that performs the actual
+ * resolve. This function returns before the resolve is done.
+ *
+ * Returns FALSE in case of failure, otherwise TRUE.
+ */
+static bool init_resolve_thread (struct connectdata *conn,
+ const char *hostname, int port,
+ const struct addrinfo *hints)
+{
+ struct thread_data *td = calloc(1, sizeof(struct thread_data));
+ int err = RESOLVER_ENOMEM;
+
+ conn->async.os_specific = (void*) td;
+ if(!td)
+ goto err_exit;
+
+ conn->async.port = port;
+ conn->async.done = FALSE;
+ conn->async.status = 0;
+ conn->async.dns = NULL;
+ td->thread_hnd = curl_thread_t_null;
+
+ if(!init_thread_sync_data(td, hostname, port, hints))
+ goto err_exit;
+
+ free(conn->async.hostname);
+ conn->async.hostname = strdup(hostname);
+ if(!conn->async.hostname)
+ goto err_exit;
+
+#ifdef HAVE_GETADDRINFO
+ td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
+#else
+ td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
+#endif
+
+ if(!td->thread_hnd) {
+#ifndef _WIN32_WCE
+ err = errno;
+#endif
+ goto err_exit;
+ }
+
+ return TRUE;
+
+ err_exit:
+ destroy_async_data(&conn->async);
+
+ SET_ERRNO(err);
+
+ return FALSE;
+}
+
+/*
+ * resolver_error() calls failf() with the appropriate message after a resolve
+ * error
+ */
+
+static CURLcode resolver_error(struct connectdata *conn)
+{
+ const char *host_or_proxy;
+ CURLcode result;
+
+ if(conn->bits.httpproxy) {
+ host_or_proxy = "proxy";
+ result = CURLE_COULDNT_RESOLVE_PROXY;
+ }
+ else {
+ host_or_proxy = "host";
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ failf(conn->data, "Could not resolve %s: %s", host_or_proxy,
+ conn->async.hostname);
+
+ return result;
+}
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * This is the version for resolves-in-a-thread.
+ */
+CURL_STATIC CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+ struct Curl_dns_entry **entry)
+{
+ struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(conn && td);
+
+ /* wait for the thread to resolve the name */
+ if(Curl_thread_join(&td->thread_hnd))
+ result = getaddrinfo_complete(conn);
+ else
+ DEBUGASSERT(0);
+
+ conn->async.done = TRUE;
+
+ if(entry)
+ *entry = conn->async.dns;
+
+ if(!conn->async.dns)
+ /* a name was not resolved, report error */
+ result = resolver_error(conn);
+
+ destroy_async_data(&conn->async);
+
+ if(!conn->async.dns)
+ connclose(conn, "asynch resolve failed");
+
+ return result;
+}
+
+/*
+ * Curl_resolver_is_resolved() is called repeatedly to check if a previous
+ * name resolve request has completed. It should also make sure to time-out if
+ * the operation seems to take too long.
+ */
+CURL_STATIC CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **entry)
+{
+ struct SessionHandle *data = conn->data;
+ struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ int done = 0;
+
+ *entry = NULL;
+
+ if(!td) {
+ DEBUGASSERT(td);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ Curl_mutex_acquire(td->tsd.mtx);
+ done = td->tsd.done;
+ Curl_mutex_release(td->tsd.mtx);
+
+ if(done) {
+ getaddrinfo_complete(conn);
+
+ if(!conn->async.dns) {
+ CURLcode result = resolver_error(conn);
+ destroy_async_data(&conn->async);
+ return result;
+ }
+ destroy_async_data(&conn->async);
+ *entry = conn->async.dns;
+ }
+ else {
+ /* poll for name lookup done with exponential backoff up to 250ms */
+ long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
+ if(elapsed < 0)
+ elapsed = 0;
+
+ if(td->poll_interval == 0)
+ /* Start at 1ms poll interval */
+ td->poll_interval = 1;
+ else if(elapsed >= td->interval_end)
+ /* Back-off exponentially if last interval expired */
+ td->poll_interval *= 2;
+
+ if(td->poll_interval > 250)
+ td->poll_interval = 250;
+
+ td->interval_end = elapsed + td->poll_interval;
+ Curl_expire(conn->data, td->poll_interval);
+ }
+
+ return CURLE_OK;
+}
+
+CURL_STATIC int Curl_resolver_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return 0;
+}
+
+#ifndef HAVE_GETADDRINFO
+/*
+ * Curl_getaddrinfo() - for platforms without getaddrinfo
+ */
+CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct in_addr in;
+
+ *waitp = 0; /* default to synchronous response */
+
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+
+ /* fire up a new resolver thread! */
+ if(init_resolve_thread(conn, hostname, port, NULL)) {
+ *waitp = 1; /* expect asynchronous response */
+ return NULL;
+ }
+
+ /* fall-back to blocking version */
+ return Curl_ipv4_resolve_r(hostname, port);
+}
+
+#else /* !HAVE_GETADDRINFO */
+
+/*
+ * Curl_resolver_getaddrinfo() - for getaddrinfo
+ */
+CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct addrinfo hints;
+ struct in_addr in;
+ Curl_addrinfo *res;
+ int error;
+ char sbuf[12];
+ int pf = PF_INET;
+#ifdef CURLRES_IPV6
+ struct in6_addr in6;
+#endif /* CURLRES_IPV6 */
+
+ *waitp = 0; /* default to synchronous response */
+
+ /* First check if this is an IPv4 address string */
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+
+#ifdef CURLRES_IPV6
+ /* check if this is an IPv6 address string */
+ if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0)
+ /* This is an IPv6 address literal */
+ return Curl_ip2addr(AF_INET6, &in6, hostname, port);
+
+ /*
+ * Check if a limited name resolve has been requested.
+ */
+ switch(conn->ip_version) {
+ case CURL_IPRESOLVE_V4:
+ pf = PF_INET;
+ break;
+ case CURL_IPRESOLVE_V6:
+ pf = PF_INET6;
+ break;
+ default:
+ pf = PF_UNSPEC;
+ break;
+ }
+
+ if((pf != PF_INET) && !Curl_ipv6works())
+ /* The stack seems to be a non-IPv6 one */
+ pf = PF_INET;
+
+#endif /* CURLRES_IPV6 */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pf;
+ hints.ai_socktype = conn->socktype;
+
+ snprintf(sbuf, sizeof(sbuf), "%d", port);
+
+ /* fire up a new resolver thread! */
+ if(init_resolve_thread(conn, hostname, port, &hints)) {
+ *waitp = 1; /* expect asynchronous response */
+ return NULL;
+ }
+
+ /* fall-back to blocking version */
+ infof(conn->data, "init_resolve_thread() failed for %s; %s\n",
+ hostname, Curl_strerror(conn, ERRNO));
+
+ error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
+ if(error) {
+ infof(conn->data, "getaddrinfo() failed for %s:%d; %s\n",
+ hostname, port, Curl_strerror(conn, SOCKERRNO));
+ return NULL;
+ }
+ return res;
+}
+
+#endif /* !HAVE_GETADDRINFO */
+
+CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data,
+ char *servers)
+{
+ (void)data;
+ (void)servers;
+ return CURLE_NOT_BUILT_IN;
+
+}
+
+CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf)
+{
+ (void)data;
+ (void)interf;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4)
+{
+ (void)data;
+ (void)local_ip4;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6)
+{
+ (void)data;
+ (void)local_ip6;
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* CURLRES_THREADED */
diff --git a/libcurl/src/lib/asyn.h b/libcurl/src/lib/asyn.h
new file mode 100644
index 0000000..36e7c53
--- /dev/null
+++ b/libcurl/src/lib/asyn.h
@@ -0,0 +1,168 @@
+#ifndef HEADER_CURL_ASYN_H
+#define HEADER_CURL_ASYN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "curl_addrinfo.h"
+
+struct addrinfo;
+struct hostent;
+struct SessionHandle;
+struct connectdata;
+struct Curl_dns_entry;
+
+/*
+ * This header defines all functions in the internal asynch resolver interface.
+ * All asynch resolvers need to provide these functions.
+ * asyn-ares.c and asyn-thread.c are the current implementations of asynch
+ * resolver backends.
+ */
+
+/*
+ * Curl_resolver_global_init()
+ *
+ * Called from curl_global_init() to initialize global resolver environment.
+ * Returning anything else than CURLE_OK fails curl_global_init().
+ */
+CURL_STATIC int Curl_resolver_global_init(void);
+
+/*
+ * Curl_resolver_global_cleanup()
+ * Called from curl_global_cleanup() to destroy global resolver environment.
+ */
+CURL_STATIC void Curl_resolver_global_cleanup(void);
+
+/*
+ * Curl_resolver_init()
+ * Called from curl_easy_init() -> Curl_open() to initialize resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Should fill the passed pointer by the initialized handler.
+ * Returning anything else than CURLE_OK fails curl_easy_init() with the
+ * correspondent code.
+ */
+CURL_STATIC CURLcode Curl_resolver_init(void **resolver);
+
+/*
+ * Curl_resolver_cleanup()
+ * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Should destroy the handler and free all resources connected to
+ * it.
+ */
+CURL_STATIC void Curl_resolver_cleanup(void *resolver);
+
+/*
+ * Curl_resolver_duphandle()
+ * Called from curl_easy_duphandle() to duplicate resolver URL-state specific
+ * environment ('resolver' member of the UrlState structure). Should
+ * duplicate the 'from' handle and pass the resulting handle to the 'to'
+ * pointer. Returning anything else than CURLE_OK causes failed
+ * curl_easy_duphandle() call.
+ */
+CURL_STATIC int Curl_resolver_duphandle(void **to, void *from);
+
+/*
+ * Curl_resolver_cancel().
+ *
+ * It is called from inside other functions to cancel currently performing
+ * resolver request. Should also free any temporary resources allocated to
+ * perform a request.
+ */
+CURL_STATIC void Curl_resolver_cancel(struct connectdata *conn);
+
+/* Curl_resolver_getsock()
+ *
+ * This function is called from the multi_getsock() function. 'sock' is a
+ * pointer to an array to hold the file descriptors, with 'numsock' being the
+ * size of that array (in number of entries). This function is supposed to
+ * return bitmask indicating what file descriptors (referring to array indexes
+ * in the 'sock' array) to wait for, read/write.
+ */
+CURL_STATIC int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock,
+ int numsocks);
+
+/*
+ * Curl_resolver_is_resolved()
+ *
+ * Called repeatedly to check if a previous name resolve request has
+ * completed. It should also make sure to time-out if the operation seems to
+ * take too long.
+ *
+ * Returns normal CURLcode errors.
+ */
+CURL_STATIC CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dns);
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
+
+ */
+CURL_STATIC CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+ struct Curl_dns_entry **dnsentry);
+
+/*
+ * Curl_resolver_getaddrinfo() - when using this resolver
+ *
+ * Returns name information about the given hostname and port number. If
+ * successful, the 'hostent' is returned and the forth argument will point to
+ * memory we need to free after use. That memory *MUST* be freed with
+ * Curl_freeaddrinfo(), nothing else.
+ *
+ * Each resolver backend must of course make sure to return data in the
+ * correct format to comply with this.
+ */
+CURL_STATIC Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
+
+#ifndef CURLRES_ASYNCH
+/* convert these functions if an asynch resolver isn't used */
+#define Curl_resolver_cancel(x) Curl_nop_stmt
+#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
+#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
+#define Curl_resolver_getsock(x,y,z) 0
+#define Curl_resolver_duphandle(x,y) CURLE_OK
+#define Curl_resolver_init(x) CURLE_OK
+#define Curl_resolver_global_init() CURLE_OK
+#define Curl_resolver_global_cleanup() Curl_nop_stmt
+#define Curl_resolver_cleanup(x) Curl_nop_stmt
+#endif
+
+#ifdef CURLRES_ASYNCH
+#define Curl_resolver_asynch() 1
+#else
+#define Curl_resolver_asynch() 0
+#endif
+
+
+/********** end of generic resolver interface functions *****************/
+#endif /* HEADER_CURL_ASYN_H */
diff --git a/libcurl/src/lib/base64.c b/libcurl/src/lib/base64.c
new file mode 100644
index 0000000..ff51c2d
--- /dev/null
+++ b/libcurl/src/lib/base64.c
@@ -0,0 +1,309 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Base64 encoding/decoding */
+
+#include "curl_setup.h"
+#include "curl_printf.h"
+#include "urldata.h" /* for the SessionHandle definition */
+#include "warnless.h"
+#include "curl_base64.h"
+#include "non-ascii.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* ---- Base64 Encoding/Decoding Table --- */
+static const char base64[]=
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
+ section 5 */
+static const char base64url[]=
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+static size_t decodeQuantum(unsigned char *dest, const char *src)
+{
+ size_t padding = 0;
+ const char *s, *p;
+ unsigned long i, x = 0;
+
+ for(i = 0, s = src; i < 4; i++, s++) {
+ unsigned long v = 0;
+
+ if(*s == '=') {
+ x = (x << 6);
+ padding++;
+ }
+ else {
+ p = base64;
+
+ while(*p && (*p != *s)) {
+ v++;
+ p++;
+ }
+
+ if(*p == *s)
+ x = (x << 6) + v;
+ else
+ return 0;
+ }
+ }
+
+ if(padding < 1)
+ dest[2] = curlx_ultouc(x & 0xFFUL);
+
+ x >>= 8;
+ if(padding < 2)
+ dest[1] = curlx_ultouc(x & 0xFFUL);
+
+ x >>= 8;
+ dest[0] = curlx_ultouc(x & 0xFFUL);
+
+ return 3 - padding;
+}
+
+/*
+ * Curl_base64_decode()
+ *
+ * Given a base64 NUL-terminated string at src, decode it and return a
+ * pointer in *outptr to a newly allocated memory area holding decoded
+ * data. Size of decoded data is returned in variable pointed by outlen.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When decoded data length is 0, returns NULL in *outptr.
+ *
+ * @unittest: 1302
+ */
+CURL_STATIC CURLcode Curl_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen)
+{
+ size_t srclen = 0;
+ size_t length = 0;
+ size_t padding = 0;
+ size_t i;
+ size_t numQuantums;
+ size_t rawlen = 0;
+ unsigned char *pos;
+ unsigned char *newstr;
+
+ *outptr = NULL;
+ *outlen = 0;
+ srclen = strlen(src);
+
+ /* Check the length of the input string is valid */
+ if(!srclen || srclen % 4)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Find the position of any = padding characters */
+ while((src[length] != '=') && src[length])
+ length++;
+
+ /* A maximum of two = padding characters is allowed */
+ if(src[length] == '=') {
+ padding++;
+ if(src[length + 1] == '=')
+ padding++;
+ }
+
+ /* Check the = padding characters weren't part way through the input */
+ if(length + padding != srclen)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Calculate the number of quantums */
+ numQuantums = srclen / 4;
+
+ /* Calculate the size of the decoded string */
+ rawlen = (numQuantums * 3) - padding;
+
+ /* Allocate our buffer including room for a zero terminator */
+ newstr = malloc(rawlen + 1);
+ if(!newstr)
+ return CURLE_OUT_OF_MEMORY;
+
+ pos = newstr;
+
+ /* Decode the quantums */
+ for(i = 0; i < numQuantums; i++) {
+ size_t result = decodeQuantum(pos, src);
+ if(!result) {
+ free(newstr);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ pos += result;
+ src += 4;
+ }
+
+ /* Zero terminate */
+ *pos = '\0';
+
+ /* Return the decoded data */
+ *outptr = newstr;
+ *outlen = rawlen;
+
+ return CURLE_OK;
+}
+
+static CURLcode base64_encode(const char *table64,
+ struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
+{
+ CURLcode error;
+ unsigned char ibuf[3];
+ unsigned char obuf[4];
+ int i;
+ int inputparts;
+ char *output;
+ char *base64data;
+ char *convbuf = NULL;
+
+ const char *indata = inputbuff;
+
+ *outptr = NULL;
+ *outlen = 0;
+
+ if(0 == insize)
+ insize = strlen(indata);
+
+ base64data = output = malloc(insize*4/3+4);
+ if(NULL == output)
+ return CURLE_OUT_OF_MEMORY;
+
+ /*
+ * The base64 data needs to be created using the network encoding
+ * not the host encoding. And we can't change the actual input
+ * so we copy it to a buffer, translate it, and use that instead.
+ */
+ error = Curl_convert_clone(data, indata, insize, &convbuf);
+ if(error) {
+ free(output);
+ return error;
+ }
+
+ if(convbuf)
+ indata = (char *)convbuf;
+
+ while(insize > 0) {
+ for(i = inputparts = 0; i < 3; i++) {
+ if(insize > 0) {
+ inputparts++;
+ ibuf[i] = (unsigned char) *indata;
+ indata++;
+ insize--;
+ }
+ else
+ ibuf[i] = 0;
+ }
+
+ obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
+ obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
+ ((ibuf[1] & 0xF0) >> 4));
+ obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
+ ((ibuf[2] & 0xC0) >> 6));
+ obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
+
+ switch(inputparts) {
+ case 1: /* only one byte read */
+ snprintf(output, 5, "%c%c==",
+ table64[obuf[0]],
+ table64[obuf[1]]);
+ break;
+ case 2: /* two bytes read */
+ snprintf(output, 5, "%c%c%c=",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]]);
+ break;
+ default:
+ snprintf(output, 5, "%c%c%c%c",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]],
+ table64[obuf[3]] );
+ break;
+ }
+ output += 4;
+ }
+ *output = '\0';
+ *outptr = base64data; /* return pointer to new data, allocated memory */
+
+ free(convbuf);
+
+ *outlen = strlen(base64data); /* return the length of the new data */
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_base64_encode()
+ *
+ * Given a pointer to an input buffer and an input size, encode it and
+ * return a pointer in *outptr to a newly allocated memory area holding
+ * encoded data. Size of encoded data is returned in variable pointed by
+ * outlen.
+ *
+ * Input length of 0 indicates input buffer holds a NUL-terminated string.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When encoded data length is 0, returns NULL in *outptr.
+ *
+ * @unittest: 1302
+ */
+CURL_STATIC CURLcode Curl_base64_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
+{
+ return base64_encode(base64, data, inputbuff, insize, outptr, outlen);
+}
+
+/*
+ * Curl_base64url_encode()
+ *
+ * Given a pointer to an input buffer and an input size, encode it and
+ * return a pointer in *outptr to a newly allocated memory area holding
+ * encoded data. Size of encoded data is returned in variable pointed by
+ * outlen.
+ *
+ * Input length of 0 indicates input buffer holds a NUL-terminated string.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When encoded data length is 0, returns NULL in *outptr.
+ *
+ * @unittest: 1302
+ */
+CURL_STATIC CURLcode Curl_base64url_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
+{
+ return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
+}
+/* ---- End of Base64 Encoding ---- */
diff --git a/libcurl/src/lib/bundles.c b/libcurl/src/lib/bundles.c
new file mode 100644
index 0000000..784e362
--- /dev/null
+++ b/libcurl/src/lib/bundles.c
@@ -0,0 +1,110 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2012-2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "multiif.h"
+#include "bundles.h"
+#include "sendf.h"
+#include "rawstr.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void conn_llist_dtor(void *user, void *element)
+{
+ struct connectdata *data = element;
+ (void)user;
+
+ data->bundle = NULL;
+}
+
+CURL_STATIC CURLcode Curl_bundle_create(struct SessionHandle *data,
+ struct connectbundle **cb_ptr)
+{
+ (void)data;
+ DEBUGASSERT(*cb_ptr == NULL);
+ *cb_ptr = malloc(sizeof(struct connectbundle));
+ if(!*cb_ptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ (*cb_ptr)->num_connections = 0;
+ (*cb_ptr)->server_supports_pipelining = FALSE;
+
+ (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor);
+ if(!(*cb_ptr)->conn_list) {
+ Curl_safefree(*cb_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_bundle_destroy(struct connectbundle *cb_ptr)
+{
+ if(!cb_ptr)
+ return;
+
+ if(cb_ptr->conn_list) {
+ Curl_llist_destroy(cb_ptr->conn_list, NULL);
+ cb_ptr->conn_list = NULL;
+ }
+ free(cb_ptr);
+}
+
+/* Add a connection to a bundle */
+CURL_STATIC CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
+{
+ if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn))
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->bundle = cb_ptr;
+
+ cb_ptr->num_connections++;
+ return CURLE_OK;
+}
+
+/* Remove a connection from a bundle */
+CURL_STATIC int Curl_bundle_remove_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
+{
+ struct curl_llist_element *curr;
+
+ curr = cb_ptr->conn_list->head;
+ while(curr) {
+ if(curr->ptr == conn) {
+ Curl_llist_remove(cb_ptr->conn_list, curr, NULL);
+ cb_ptr->num_connections--;
+ conn->bundle = NULL;
+ return 1; /* we removed a handle */
+ }
+ curr = curr->next;
+ }
+ return 0;
+}
diff --git a/libcurl/src/lib/bundles.h b/libcurl/src/lib/bundles.h
new file mode 100644
index 0000000..af4382c
--- /dev/null
+++ b/libcurl/src/lib/bundles.h
@@ -0,0 +1,45 @@
+#ifndef HEADER_CURL_BUNDLES_H
+#define HEADER_CURL_BUNDLES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct connectbundle {
+ bool server_supports_pipelining; /* TRUE if server supports pipelining,
+ set after first response */
+ size_t num_connections; /* Number of connections in the bundle */
+ struct curl_llist *conn_list; /* The connectdata members of the bundle */
+};
+
+CURL_STATIC CURLcode Curl_bundle_create(struct SessionHandle *data,
+ struct connectbundle **cb_ptr);
+
+CURL_STATIC void Curl_bundle_destroy(struct connectbundle *cb_ptr);
+
+CURL_STATIC CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn);
+
+CURL_STATIC int Curl_bundle_remove_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn);
+
+
+#endif /* HEADER_CURL_BUNDLES_H */
+
diff --git a/libcurl/src/lib/config-amigaos.h b/libcurl/src/lib/config-amigaos.h
new file mode 100644
index 0000000..04b18b7
--- /dev/null
+++ b/libcurl/src/lib/config-amigaos.h
@@ -0,0 +1,166 @@
+#ifndef HEADER_CURL_CONFIG_AMIGAOS_H
+#define HEADER_CURL_CONFIG_AMIGAOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for AmigaOS */
+/* ================================================================ */
+
+#ifdef __AMIGA__ /* Any AmigaOS flavour */
+
+#define HAVE_ARPA_INET_H 1
+#define HAVE_CLOSESOCKET_CAMEL 1
+#define HAVE_ERRNO_H 1
+#define HAVE_GETHOSTBYADDR 1
+#define HAVE_INET_ADDR 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_IOCTLSOCKET_CAMEL 1
+#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
+#define HAVE_LIBCRYPTO 1
+#define HAVE_LIBSSL 1
+#define HAVE_LIBZ 1
+#define HAVE_LONGLONG 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_NETDB_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_NET_IF_H 1
+#define HAVE_OPENSSL_CRYPTO_H 1
+#define HAVE_OPENSSL_ERR_H 1
+#define HAVE_OPENSSL_PEM_H 1
+#define HAVE_OPENSSL_RSA_H 1
+#define HAVE_OPENSSL_SSL_H 1
+#define HAVE_OPENSSL_X509_H 1
+#define HAVE_PERROR 1
+#define HAVE_PWD_H 1
+#define HAVE_RAND_EGD 1
+#define HAVE_RAND_STATUS 1
+#define HAVE_SELECT 1
+#define HAVE_SETJMP_H 1
+#define HAVE_SGTTY_H 1
+#define HAVE_SIGNAL 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_SIG_ATOMIC_T 1
+#define HAVE_SOCKET 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRDUP 1
+#define HAVE_STRFTIME 1
+#define HAVE_STRICMP 1
+#define HAVE_STRINGS_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRSTR 1
+#define HAVE_STRUCT_TIMEVAL 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_SOCKIO_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UNAME 1
+#define HAVE_UNISTD_H 1
+#define HAVE_UTIME 1
+#define HAVE_UTIME_H 1
+#define HAVE_WRITABLE_ARGV 1
+#define HAVE_ZLIB_H 1
+#define HAVE_SYS_IOCTL_H 1
+
+#define NEED_MALLOC_H 1
+
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_SIZE_T 4
+
+#define USE_MANUAL 1
+#define USE_OPENSSL 1
+#define CURL_DISABLE_LDAP 1
+
+#define OS "AmigaOS"
+
+#define PACKAGE "curl"
+#define PACKAGE_BUGREPORT "curl-bug@haxx.se"
+#define PACKAGE_NAME "curl"
+#define PACKAGE_STRING "curl -"
+#define PACKAGE_TARNAME "curl"
+#define PACKAGE_VERSION "-"
+#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt"
+
+#define RETSIGTYPE void
+#define SELECT_TYPE_ARG1 int
+#define SELECT_TYPE_ARG234 (fd_set *)
+#define SELECT_TYPE_ARG5 (struct timeval *)
+
+#define STDC_HEADERS 1
+#define TIME_WITH_SYS_TIME 1
+
+#define in_addr_t int
+
+#ifndef F_OK
+# define F_OK 0
+#endif
+
+#ifndef O_RDONLY
+# define O_RDONLY 0x0000
+#endif
+
+#ifndef LONG_MAX
+# define LONG_MAX 0x7fffffffL
+#endif
+
+#ifndef LONG_MIN
+# define LONG_MIN (-0x7fffffffL-1)
+#endif
+
+#define HAVE_GETNAMEINFO 1
+#define GETNAMEINFO_QUAL_ARG1 const
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+#define GETNAMEINFO_TYPE_ARG2 int
+#define GETNAMEINFO_TYPE_ARG46 size_t
+#define GETNAMEINFO_TYPE_ARG7 int
+
+#define HAVE_RECV 1
+#define RECV_TYPE_ARG1 long
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 long
+#define RECV_TYPE_ARG4 long
+#define RECV_TYPE_RETV long
+
+#define HAVE_RECVFROM 1
+#define RECVFROM_TYPE_ARG1 long
+#define RECVFROM_TYPE_ARG2 char
+#define RECVFROM_TYPE_ARG3 long
+#define RECVFROM_TYPE_ARG4 long
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 long
+#define RECVFROM_TYPE_RETV long
+
+#define HAVE_SEND 1
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV int
+
+#endif /* __AMIGA__ */
+#endif /* HEADER_CURL_CONFIG_AMIGAOS_H */
diff --git a/libcurl/src/lib/config-android-arm.h b/libcurl/src/lib/config-android-arm.h
new file mode 100644
index 0000000..8d64dbe
--- /dev/null
+++ b/libcurl/src/lib/config-android-arm.h
@@ -0,0 +1,1019 @@
+/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+//#define CURL_DISABLE_DICT 1
+
+/* to disable FILE */
+//#define CURL_DISABLE_FILE 1
+
+/* to disable FTP */
+//#define CURL_DISABLE_FTP 1
+
+/* to disable Gopher */
+//#define CURL_DISABLE_GOPHER 1
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable IMAP */
+//#define CURL_DISABLE_IMAP 1
+
+/* to disable LDAP */
+//#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+//#define CURL_DISABLE_LDAPS 1
+
+/* to disable --libcurl C code generation option */
+/* #undef CURL_DISABLE_LIBCURL_OPTION */
+
+/* to disable POP3 */
+//#define CURL_DISABLE_POP3 1
+
+/* to disable proxies */
+/* #undef CURL_DISABLE_PROXY */
+
+/* to disable RTSP */
+//#define CURL_DISABLE_RTSP 1
+
+/* to disable SMB/CIFS */
+/* #undef CURL_DISABLE_SMB */
+
+/* to disable SMTP */
+//#define CURL_DISABLE_SMTP 1
+
+/* to disable TELNET */
+//#define CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+//#define CURL_DISABLE_TFTP 1
+
+/* to disable TLS-SRP authentication */
+/* #undef CURL_DISABLE_TLS_SRP */
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+/* #undef ENABLE_IPV6 */
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 unsigned int
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+/* #undef GETSERVBYPORT_R_ARGS */
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+/* #undef GETSERVBYPORT_R_BUFSIZE */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/* #undef HAVE_ARPA_TFTP_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#define HAVE_CLOCK_GETTIME_MONOTONIC 1
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+/* #undef HAVE_CYASSL_ERROR_SSL_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+/* #undef HAVE_FREEIFADDRS */
+
+/* Define to 1 if you have the fsetxattr function. */
+/* #undef HAVE_FSETXATTR */
+
+/* fsetxattr() takes 5 args */
+/* #undef HAVE_FSETXATTR_5 */
+
+/* fsetxattr() takes 6 args */
+/* #undef HAVE_FSETXATTR_6 */
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the gai_strerror function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#define HAVE_GETADDRINFO_THREADSAFE 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+/* #undef HAVE_GETHOSTBYADDR_R */
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+/* #undef HAVE_GETHOSTBYADDR_R_8 */
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+#define HAVE_GETHOSTBYNAME_R 1
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+#define HAVE_GETHOSTBYNAME_R_6 1
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+/* #undef HAVE_GETIFADDRS */
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+/* #undef HAVE_GETPWUID_R */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the function gnutls_srp_verifier */
+/* #undef HAVE_GNUTLS_SRP */
+
+/* if you have GSS-API libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have GNU GSS */
+/* #undef HAVE_GSSGNU */
+
+/* if you have Heimdal */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have MIT Kerberos */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+/* #undef HAVE_IFADDRS_H */
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#define HAVE_IF_NAMETOINDEX 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+/* #undef HAVE_LDAP_INIT_FD */
+
+/* Use LDAPS implementation */
+#define HAVE_LDAP_SSL 1
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+/* #undef HAVE_LIBRTMP_RTMP_H */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the memrchr function or macro. */
+#define HAVE_MEMRCHR 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#define HAVE_MSG_NOSIGNAL 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#define HAVE_POLL 1
+
+/* If you have a fine poll */
+#define HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* if you have <pthread.h> */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+/* #undef HAVE_SETMODE */
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+/* #undef HAVE_SIGNAL */
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#define HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* if you have the function SRP_Calc_client_key */
+/* #undef HAVE_SSLEAY_SRP */
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+/* #undef HAVE_SSLV2_CLIENT_METHOD */
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/* #undef HAVE_SSL_GET_SHUTDOWN */
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+/* #undef HAVE_SYS_XATTR_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#define HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+/* #undef HAVE_WRITABLE_ARGV */
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_ENABLED */
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_FILE */
+
+/* cpu-machine-OS */
+#define OS "arm-unknown-linux-androideabi"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 unsigned int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 unsigned int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `long long', as computed by sizeof. */
+/* #undef SIZEOF_LONG_LONG */
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 4
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#define STRERROR_R_TYPE_ARG3 size_t
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to enable c-ares support */
+/* #undef USE_ARES */
+
+/* if axTLS is enabled */
+/* #undef USE_AXTLS */
+
+/* if CyaSSL is enabled */
+/* #undef USE_CYASSL */
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+/* #undef USE_DARWINSSL */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if GnuTLS uses nettle as crypto backend */
+/* #undef USE_GNUTLS_NETTLE */
+
+/* if librtmp is in use */
+/* #undef USE_LIBRTMP */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+/* Define to enable metalink support */
+/* #undef USE_METALINK */
+
+/* if nghttp2 is in use */
+/* #undef USE_NGHTTP2 */
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* Use OpenLDAP-specific code */
+/* #undef USE_OPENLDAP */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if PolarSSL is enabled */
+/* #undef USE_POLARSSL */
+
+/* to enable Windows native SSL/TLS support */
+/* #undef USE_SCHANNEL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* if you want POSIX threaded DNS lookup */
+#define USE_THREADS_POSIX 1
+
+/* Use TLS-SRP authentication */
+/* #undef USE_TLS_SRP */
+
+/* Use Unix domain sockets */
+#define USE_UNIX_SOCKETS 1
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+/* #undef USE_WIN32_IDN */
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_SMALL_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+#define VERSION "-"
+
+/* Define to 1 to provide own prototypes. */
+/* #undef WANT_IDN_PROTOTYPES */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
diff --git a/libcurl/src/lib/config-android-x86.h b/libcurl/src/lib/config-android-x86.h
new file mode 100644
index 0000000..84cfed8
--- /dev/null
+++ b/libcurl/src/lib/config-android-x86.h
@@ -0,0 +1,1019 @@
+/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+//#define CURL_DISABLE_DICT 1
+
+/* to disable FILE */
+//#define CURL_DISABLE_FILE 1
+
+/* to disable FTP */
+//#define CURL_DISABLE_FTP 1
+
+/* to disable Gopher */
+//#define CURL_DISABLE_GOPHER 1
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable IMAP */
+//#define CURL_DISABLE_IMAP 1
+
+/* to disable LDAP */
+//#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+//#define CURL_DISABLE_LDAPS 1
+
+/* to disable --libcurl C code generation option */
+/* #undef CURL_DISABLE_LIBCURL_OPTION */
+
+/* to disable POP3 */
+//#define CURL_DISABLE_POP3 1
+
+/* to disable proxies */
+/* #undef CURL_DISABLE_PROXY */
+
+/* to disable RTSP */
+//#define CURL_DISABLE_RTSP 1
+
+/* to disable SMB/CIFS */
+/* #undef CURL_DISABLE_SMB */
+
+/* to disable SMTP */
+//#define CURL_DISABLE_SMTP 1
+
+/* to disable TELNET */
+//#define CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+//#define CURL_DISABLE_TFTP 1
+
+/* to disable TLS-SRP authentication */
+/* #undef CURL_DISABLE_TLS_SRP */
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+/* #undef ENABLE_IPV6 */
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 unsigned int
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+/* #undef GETSERVBYPORT_R_ARGS */
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+/* #undef GETSERVBYPORT_R_BUFSIZE */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/* #undef HAVE_ARPA_TFTP_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#define HAVE_CLOCK_GETTIME_MONOTONIC 1
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+/* #undef HAVE_CYASSL_ERROR_SSL_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+/* #undef HAVE_FREEIFADDRS */
+
+/* Define to 1 if you have the fsetxattr function. */
+/* #undef HAVE_FSETXATTR */
+
+/* fsetxattr() takes 5 args */
+/* #undef HAVE_FSETXATTR_5 */
+
+/* fsetxattr() takes 6 args */
+/* #undef HAVE_FSETXATTR_6 */
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the gai_strerror function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#define HAVE_GETADDRINFO_THREADSAFE 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+/* #undef HAVE_GETHOSTBYADDR_R */
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+/* #undef HAVE_GETHOSTBYADDR_R_8 */
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+#define HAVE_GETHOSTBYNAME_R 1
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+#define HAVE_GETHOSTBYNAME_R_6 1
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+/* #undef HAVE_GETIFADDRS */
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+/* #undef HAVE_GETPWUID_R */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the function gnutls_srp_verifier */
+/* #undef HAVE_GNUTLS_SRP */
+
+/* if you have GSS-API libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have GNU GSS */
+/* #undef HAVE_GSSGNU */
+
+/* if you have Heimdal */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have MIT Kerberos */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+/* #undef HAVE_IFADDRS_H */
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#define HAVE_IF_NAMETOINDEX 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+/* #undef HAVE_LDAP_INIT_FD */
+
+/* Use LDAPS implementation */
+#define HAVE_LDAP_SSL 1
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+/* #undef HAVE_LIBRTMP_RTMP_H */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the memrchr function or macro. */
+#define HAVE_MEMRCHR 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#define HAVE_MSG_NOSIGNAL 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#define HAVE_POLL 1
+
+/* If you have a fine poll */
+#define HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* if you have <pthread.h> */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+/* #undef HAVE_SETMODE */
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+/* #undef HAVE_SIGNAL */
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#define HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* if you have the function SRP_Calc_client_key */
+/* #undef HAVE_SSLEAY_SRP */
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+/* #undef HAVE_SSLV2_CLIENT_METHOD */
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/* #undef HAVE_SSL_GET_SHUTDOWN */
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+/* #undef HAVE_SYS_XATTR_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#define HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+/* #undef HAVE_WRITABLE_ARGV */
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_ENABLED */
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_FILE */
+
+/* cpu-machine-OS */
+#define OS "i686-pc-linux-android"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 unsigned int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 unsigned int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `long long', as computed by sizeof. */
+/* #undef SIZEOF_LONG_LONG */
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 4
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#define STRERROR_R_TYPE_ARG3 size_t
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to enable c-ares support */
+/* #undef USE_ARES */
+
+/* if axTLS is enabled */
+/* #undef USE_AXTLS */
+
+/* if CyaSSL is enabled */
+/* #undef USE_CYASSL */
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+/* #undef USE_DARWINSSL */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if GnuTLS uses nettle as crypto backend */
+/* #undef USE_GNUTLS_NETTLE */
+
+/* if librtmp is in use */
+/* #undef USE_LIBRTMP */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+/* Define to enable metalink support */
+/* #undef USE_METALINK */
+
+/* if nghttp2 is in use */
+/* #undef USE_NGHTTP2 */
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* Use OpenLDAP-specific code */
+/* #undef USE_OPENLDAP */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if PolarSSL is enabled */
+/* #undef USE_POLARSSL */
+
+/* to enable Windows native SSL/TLS support */
+/* #undef USE_SCHANNEL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* if you want POSIX threaded DNS lookup */
+#define USE_THREADS_POSIX 1
+
+/* Use TLS-SRP authentication */
+/* #undef USE_TLS_SRP */
+
+/* Use Unix domain sockets */
+#define USE_UNIX_SOCKETS 1
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+/* #undef USE_WIN32_IDN */
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_SMALL_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+#define VERSION "-"
+
+/* Define to 1 to provide own prototypes. */
+/* #undef WANT_IDN_PROTOTYPES */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
diff --git a/libcurl/src/lib/config-dos.h b/libcurl/src/lib/config-dos.h
new file mode 100644
index 0000000..288bd1d
--- /dev/null
+++ b/libcurl/src/lib/config-dos.h
@@ -0,0 +1,181 @@
+#ifndef HEADER_CURL_CONFIG_DOS_H
+#define HEADER_CURL_CONFIG_DOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/* ================================================================ */
+/* lib/config-dos.h - Hand crafted config file for DOS */
+/* ================================================================ */
+
+#if defined(DJGPP)
+ #define OS "MSDOS/djgpp"
+#elif defined(__HIGHC__)
+ #define OS "MSDOS/HighC"
+#elif defined(__WATCOMC__)
+ #define OS "MSDOS/Watcom"
+#else
+ #define OS "MSDOS/?"
+#endif
+
+#define PACKAGE "curl"
+
+#define HAVE_ARPA_INET_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETNAMEINFO 1
+#define HAVE_GETPROTOBYNAME 1
+#define HAVE_GETTIMEOFDAY 1
+#define HAVE_IO_H 1
+#define HAVE_IOCTL 1
+#define HAVE_IOCTL_FIONBIO 1
+#define HAVE_IOCTLSOCKET 1
+#define HAVE_IOCTLSOCKET_FIONBIO 1
+#define HAVE_LIMITS_H 1
+#define HAVE_LOCALE_H 1
+#define HAVE_LONGLONG 1
+#define HAVE_MEMORY_H 1
+#define HAVE_NETDB_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_NETINET_TCP_H 1
+#define HAVE_NET_IF_H 1
+#define HAVE_PROCESS_H 1
+#define HAVE_RECV 1
+#define HAVE_RECVFROM 1
+#define HAVE_SELECT 1
+#define HAVE_SEND 1
+#define HAVE_SETJMP_H 1
+#define HAVE_SETLOCALE 1
+#define HAVE_SETMODE 1
+#define HAVE_SIGNAL 1
+#define HAVE_SOCKET 1
+#define HAVE_STRDUP 1
+#define HAVE_STRICMP 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRUCT_TIMEVAL 1
+#define HAVE_STRUCT_IN6_ADDR 1
+#define HAVE_SYS_IOCTL_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UNISTD_H 1
+
+#define NEED_MALLOC_H 1
+
+#define RETSIGTYPE void
+#define SIZEOF_INT 4
+#define SIZEOF_LONG_DOUBLE 16
+#define SIZEOF_SHORT 2
+#define SIZEOF_SIZE_T 4
+#define STDC_HEADERS 1
+#define TIME_WITH_SYS_TIME 1
+
+/* Qualifiers for send(), recv(), recvfrom() and getnameinfo(). */
+
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 void *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV int
+
+#define RECV_TYPE_ARG1 int
+#define RECV_TYPE_ARG2 void *
+#define RECV_TYPE_ARG3 int
+#define RECV_TYPE_ARG4 int
+#define RECV_TYPE_RETV int
+
+#define RECVFROM_TYPE_ARG1 int
+#define RECVFROM_TYPE_ARG2 void
+#define RECVFROM_TYPE_ARG3 int
+#define RECVFROM_TYPE_ARG4 int
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 int
+#define RECVFROM_TYPE_RETV int
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+#define GETNAMEINFO_QUAL_ARG1 const
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+#define GETNAMEINFO_TYPE_ARG2 int
+#define GETNAMEINFO_TYPE_ARG46 int
+#define GETNAMEINFO_TYPE_ARG7 int
+
+#define BSD
+
+/* CURLDEBUG definition enables memory tracking */
+/* #define CURLDEBUG */
+
+/* USE_ZLIB on cmd-line */
+#ifdef USE_ZLIB
+ #define HAVE_ZLIB_H 1
+ #define HAVE_LIBZ 1
+#endif
+
+/* USE_OPENSSL on cmd-line */
+#ifdef USE_OPENSSL
+ #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+ #define HAVE_OPENSSL_ENGINE_H 1
+ #define OPENSSL_NO_KRB5 1
+#endif
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+#define in_addr_t u_long
+
+#if defined(__HIGHC__) || \
+ (defined(__GNUC__) && (__GNUC__ < 4))
+ #define ssize_t int
+#endif
+
+#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
+
+/* Target HAVE_x section */
+
+#if defined(DJGPP)
+ #define HAVE_BASENAME 1
+ #define HAVE_STRCASECMP 1
+ #define HAVE_SIGACTION 1
+ #define HAVE_SIGSETJMP 1
+ #define HAVE_SYS_TIME_H 1
+ #define HAVE_TERMIOS_H 1
+ #define HAVE_VARIADIC_MACROS_GCC 1
+
+#elif defined(__WATCOMC__)
+ #define HAVE_STRCASECMP 1
+
+#elif defined(__HIGHC__)
+ #define HAVE_SYS_TIME_H 1
+ #define strerror(e) strerror_s_((e))
+#endif
+
+#ifdef MSDOS /* Watt-32 */
+ #define HAVE_CLOSE_S 1
+#endif
+
+#undef word
+#undef byte
+
+#endif /* HEADER_CURL_CONFIG_DOS_H */
+
diff --git a/libcurl/src/lib/config-emscripten.h b/libcurl/src/lib/config-emscripten.h
new file mode 100644
index 0000000..2122818
--- /dev/null
+++ b/libcurl/src/lib/config-emscripten.h
@@ -0,0 +1,1032 @@
+/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+/* #undef CURL_DISABLE_FTP */
+
+/* to disable Gopher */
+/* #undef CURL_DISABLE_GOPHER */
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable IMAP */
+/* #undef CURL_DISABLE_IMAP */
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable --libcurl C code generation option */
+/* #undef CURL_DISABLE_LIBCURL_OPTION */
+
+/* to disable POP3 */
+/* #undef CURL_DISABLE_POP3 */
+
+/* to disable proxies */
+/* #undef CURL_DISABLE_PROXY */
+
+/* to disable RTSP */
+/* #undef CURL_DISABLE_RTSP */
+
+/* to disable SMB/CIFS */
+/* #undef CURL_DISABLE_SMB */
+
+/* to disable SMTP */
+/* #undef CURL_DISABLE_SMTP */
+
+/* to disable TELNET */
+/* #undef CURL_DISABLE_TELNET */
+
+/* to disable TFTP */
+/* #undef CURL_DISABLE_TFTP */
+
+/* to disable TLS-SRP authentication */
+/* #undef CURL_DISABLE_TLS_SRP */
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+/* #undef ENABLE_IPV6 */
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 size_t
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 socklen_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+#define GETSERVBYPORT_R_ARGS 6
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+#define GETSERVBYPORT_R_BUFSIZE 4096
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+#define HAVE_ARPA_TFTP_H 1
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if using BoringSSL. */
+/* #undef HAVE_BORINGSSL */
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#define HAVE_CLOCK_GETTIME_MONOTONIC 1
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+/* #undef HAVE_CYASSL_ERROR_SSL_H */
+
+/* Define to 1 if you have the `DES_set_odd_parity' function. */
+/* #undef HAVE_DES_SET_ODD_PARITY */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the fsetxattr function. */
+#define HAVE_FSETXATTR 1
+
+/* fsetxattr() takes 5 args */
+#define HAVE_FSETXATTR_5 1
+
+/* fsetxattr() takes 6 args */
+/* #undef HAVE_FSETXATTR_6 */
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the gai_strerror function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#define HAVE_GETADDRINFO_THREADSAFE 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+#define HAVE_GETHOSTBYADDR_R 1
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+#define HAVE_GETHOSTBYADDR_R_8 1
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+#define HAVE_GETHOSTBYNAME_R 1
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+#define HAVE_GETHOSTBYNAME_R_6 1
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#define HAVE_GETPWUID_R 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+#define HAVE_GETSERVBYPORT_R 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the function gnutls_srp_verifier */
+/* #undef HAVE_GNUTLS_SRP */
+
+/* if you have GSS-API libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have GNU GSS */
+/* #undef HAVE_GSSGNU */
+
+/* if you have Heimdal */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have MIT Kerberos */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#define HAVE_IF_NAMETOINDEX 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+/* #undef HAVE_LDAP_INIT_FD */
+
+/* Use LDAPS implementation */
+#define HAVE_LDAP_SSL 1
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if using libressl. */
+/* #undef HAVE_LIBRESSL */
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+/* #undef HAVE_LIBRTMP_RTMP_H */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the memrchr function or macro. */
+/* #undef HAVE_MEMRCHR */
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#define HAVE_MSG_NOSIGNAL 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#define HAVE_POLL 1
+
+/* If you have a fine poll */
+#define HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* if you have <pthread.h> */
+/* #undef HAVE_PTHREAD_H */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+/* #undef HAVE_SETMODE */
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#define HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* if you have the function SRP_Calc_client_key */
+/* #undef HAVE_SSLEAY_SRP */
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+/* #undef HAVE_SSLV2_CLIENT_METHOD */
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/* #undef HAVE_SSL_GET_SHUTDOWN */
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+#define HAVE_STROPTS_H 1
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#define HAVE_SYS_XATTR_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#define HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#define HAVE_WRITABLE_ARGV 1
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_ENABLED */
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_FILE */
+
+/* cpu-machine-OS */
+#define OS "x86_64-unknown-linux-gnu"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV ssize_t
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV ssize_t
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `long long', as computed by sizeof. */
+/* #undef SIZEOF_LONG_LONG */
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 8
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#define STRERROR_R_TYPE_ARG3 size_t
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to enable c-ares support */
+/* #undef USE_ARES */
+
+/* if axTLS is enabled */
+/* #undef USE_AXTLS */
+
+/* if CyaSSL is enabled */
+/* #undef USE_CYASSL */
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+/* #undef USE_DARWINSSL */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if GnuTLS uses nettle as crypto backend */
+/* #undef USE_GNUTLS_NETTLE */
+
+/* if librtmp is in use */
+/* #undef USE_LIBRTMP */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+/* Define to enable metalink support */
+/* #undef USE_METALINK */
+
+/* if nghttp2 is in use */
+/* #undef USE_NGHTTP2 */
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* Use OpenLDAP-specific code */
+/* #undef USE_OPENLDAP */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if PolarSSL is enabled */
+/* #undef USE_POLARSSL */
+
+/* to enable Windows native SSL/TLS support */
+/* #undef USE_SCHANNEL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* if you want POSIX threaded DNS lookup */
+/* #undef USE_THREADS_POSIX */
+
+/* Use TLS-SRP authentication */
+/* #undef USE_TLS_SRP */
+
+/* Use Unix domain sockets */
+#define USE_UNIX_SOCKETS 1
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+/* #undef USE_WIN32_IDN */
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* Use Windows LDAP implementation */
+/* #undef USE_WIN32_LDAP */
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_SMALL_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+#define VERSION "-"
+
+/* Define to 1 to provide own prototypes. */
+/* #undef WANT_IDN_PROTOTYPES */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
+
diff --git a/libcurl/src/lib/config-ios-sim.h b/libcurl/src/lib/config-ios-sim.h
new file mode 100644
index 0000000..c94f53e
--- /dev/null
+++ b/libcurl/src/lib/config-ios-sim.h
@@ -0,0 +1,1019 @@
+/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+#define CURL_DISABLE_COOKIES 1
+
+/* to disable cryptographic authentication */
+#define CURL_DISABLE_CRYPTO_AUTH 1
+
+/* to disable DICT */
+#define CURL_DISABLE_DICT 1
+
+/* to disable FILE */
+#define CURL_DISABLE_FILE 1
+
+/* to disable FTP */
+#define CURL_DISABLE_FTP 1
+
+/* to disable Gopher */
+#define CURL_DISABLE_GOPHER 1
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable IMAP */
+#define CURL_DISABLE_IMAP 1
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable --libcurl C code generation option */
+#define CURL_DISABLE_LIBCURL_OPTION 1
+
+/* to disable POP3 */
+#define CURL_DISABLE_POP3 1
+
+/* to disable proxies */
+#define CURL_DISABLE_PROXY 1
+
+/* to disable RTSP */
+#define CURL_DISABLE_RTSP 1
+
+/* to disable SMB/CIFS */
+#define CURL_DISABLE_SMB 1
+
+/* to disable SMTP */
+#define CURL_DISABLE_SMTP 1
+
+/* to disable TELNET */
+#define CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+#define CURL_DISABLE_TFTP 1
+
+/* to disable TLS-SRP authentication */
+#define CURL_DISABLE_TLS_SRP 1
+
+/* to disable verbose strings */
+#define CURL_DISABLE_VERBOSE_STRINGS 1
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6 1
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 size_t
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 socklen_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+/* #undef GETSERVBYPORT_R_ARGS */
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+/* #undef GETSERVBYPORT_R_BUFSIZE */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+#define HAVE_ARPA_TFTP_H 1
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+/* #undef HAVE_CYASSL_ERROR_SSL_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the fsetxattr function. */
+#define HAVE_FSETXATTR 1
+
+/* fsetxattr() takes 5 args */
+/* #undef HAVE_FSETXATTR_5 */
+
+/* fsetxattr() takes 6 args */
+#define HAVE_FSETXATTR_6 1
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the gai_strerror function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#define HAVE_GETADDRINFO_THREADSAFE 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+/* #undef HAVE_GETHOSTBYADDR_R */
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+/* #undef HAVE_GETHOSTBYADDR_R_8 */
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#define HAVE_GETPWUID_R 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the function gnutls_srp_verifier */
+/* #undef HAVE_GNUTLS_SRP */
+
+/* if you have GSS-API libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have GNU GSS */
+/* #undef HAVE_GSSGNU */
+
+/* if you have Heimdal */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have MIT Kerberos */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#define HAVE_IF_NAMETOINDEX 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+/* #undef HAVE_LDAP_INIT_FD */
+
+/* Use LDAPS implementation */
+/* #undef HAVE_LDAP_SSL */
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+/* #undef HAVE_LIBRTMP_RTMP_H */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the memrchr function or macro. */
+/* #undef HAVE_MEMRCHR */
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+/* #undef HAVE_MSG_NOSIGNAL */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#define HAVE_POLL 1
+
+/* If you have a fine poll */
+#define HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* if you have <pthread.h> */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+#define HAVE_SETMODE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#define HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* if you have the function SRP_Calc_client_key */
+/* #undef HAVE_SSLEAY_SRP */
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+/* #undef HAVE_SSLV2_CLIENT_METHOD */
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/* #undef HAVE_SSL_GET_SHUTDOWN */
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#define HAVE_SYS_XATTR_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#define HAVE_WRITABLE_ARGV 1
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_ENABLED */
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_FILE */
+
+/* cpu-machine-OS */
+#define OS "x86_64-apple-darwin13.4.0"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV ssize_t
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV ssize_t
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `long long', as computed by sizeof. */
+/* #undef SIZEOF_LONG_LONG */
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 8
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#define STRERROR_R_TYPE_ARG3 size_t
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to enable c-ares support */
+/* #undef USE_ARES */
+
+/* if axTLS is enabled */
+/* #undef USE_AXTLS */
+
+/* if CyaSSL is enabled */
+/* #undef USE_CYASSL */
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+/* #undef USE_DARWINSSL */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if GnuTLS uses nettle as crypto backend */
+/* #undef USE_GNUTLS_NETTLE */
+
+/* if librtmp is in use */
+/* #undef USE_LIBRTMP */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+/* #undef USE_MANUAL */
+
+/* Define to enable metalink support */
+/* #undef USE_METALINK */
+
+/* if nghttp2 is in use */
+/* #undef USE_NGHTTP2 */
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* Use OpenLDAP-specific code */
+/* #undef USE_OPENLDAP */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if PolarSSL is enabled */
+/* #undef USE_POLARSSL */
+
+/* to enable Windows native SSL/TLS support */
+/* #undef USE_SCHANNEL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* if you want POSIX threaded DNS lookup */
+#define USE_THREADS_POSIX 1
+
+/* Use TLS-SRP authentication */
+/* #undef USE_TLS_SRP */
+
+/* Use Unix domain sockets */
+/* #undef USE_UNIX_SOCKETS */
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+/* #undef USE_WIN32_IDN */
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_SMALL_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+#define VERSION "-"
+
+/* Define to 1 to provide own prototypes. */
+/* #undef WANT_IDN_PROTOTYPES */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
diff --git a/libcurl/src/lib/config-ios.h b/libcurl/src/lib/config-ios.h
new file mode 100644
index 0000000..c94f53e
--- /dev/null
+++ b/libcurl/src/lib/config-ios.h
@@ -0,0 +1,1019 @@
+/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+#define CURL_DISABLE_COOKIES 1
+
+/* to disable cryptographic authentication */
+#define CURL_DISABLE_CRYPTO_AUTH 1
+
+/* to disable DICT */
+#define CURL_DISABLE_DICT 1
+
+/* to disable FILE */
+#define CURL_DISABLE_FILE 1
+
+/* to disable FTP */
+#define CURL_DISABLE_FTP 1
+
+/* to disable Gopher */
+#define CURL_DISABLE_GOPHER 1
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable IMAP */
+#define CURL_DISABLE_IMAP 1
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable --libcurl C code generation option */
+#define CURL_DISABLE_LIBCURL_OPTION 1
+
+/* to disable POP3 */
+#define CURL_DISABLE_POP3 1
+
+/* to disable proxies */
+#define CURL_DISABLE_PROXY 1
+
+/* to disable RTSP */
+#define CURL_DISABLE_RTSP 1
+
+/* to disable SMB/CIFS */
+#define CURL_DISABLE_SMB 1
+
+/* to disable SMTP */
+#define CURL_DISABLE_SMTP 1
+
+/* to disable TELNET */
+#define CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+#define CURL_DISABLE_TFTP 1
+
+/* to disable TLS-SRP authentication */
+#define CURL_DISABLE_TLS_SRP 1
+
+/* to disable verbose strings */
+#define CURL_DISABLE_VERBOSE_STRINGS 1
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6 1
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 size_t
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 socklen_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+/* #undef GETSERVBYPORT_R_ARGS */
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+/* #undef GETSERVBYPORT_R_BUFSIZE */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+#define HAVE_ARPA_TFTP_H 1
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+/* #undef HAVE_CYASSL_ERROR_SSL_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the fsetxattr function. */
+#define HAVE_FSETXATTR 1
+
+/* fsetxattr() takes 5 args */
+/* #undef HAVE_FSETXATTR_5 */
+
+/* fsetxattr() takes 6 args */
+#define HAVE_FSETXATTR_6 1
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the gai_strerror function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#define HAVE_GETADDRINFO_THREADSAFE 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+/* #undef HAVE_GETHOSTBYADDR_R */
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+/* #undef HAVE_GETHOSTBYADDR_R_8 */
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#define HAVE_GETPWUID_R 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the function gnutls_srp_verifier */
+/* #undef HAVE_GNUTLS_SRP */
+
+/* if you have GSS-API libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have GNU GSS */
+/* #undef HAVE_GSSGNU */
+
+/* if you have Heimdal */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have MIT Kerberos */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#define HAVE_IF_NAMETOINDEX 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+/* #undef HAVE_LDAP_INIT_FD */
+
+/* Use LDAPS implementation */
+/* #undef HAVE_LDAP_SSL */
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+/* #undef HAVE_LIBRTMP_RTMP_H */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the memrchr function or macro. */
+/* #undef HAVE_MEMRCHR */
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+/* #undef HAVE_MSG_NOSIGNAL */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#define HAVE_POLL 1
+
+/* If you have a fine poll */
+#define HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* if you have <pthread.h> */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+#define HAVE_SETMODE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#define HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* if you have the function SRP_Calc_client_key */
+/* #undef HAVE_SSLEAY_SRP */
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+/* #undef HAVE_SSLV2_CLIENT_METHOD */
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/* #undef HAVE_SSL_GET_SHUTDOWN */
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#define HAVE_SYS_XATTR_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#define HAVE_WRITABLE_ARGV 1
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_ENABLED */
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_FILE */
+
+/* cpu-machine-OS */
+#define OS "x86_64-apple-darwin13.4.0"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV ssize_t
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV ssize_t
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `long long', as computed by sizeof. */
+/* #undef SIZEOF_LONG_LONG */
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 8
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#define STRERROR_R_TYPE_ARG3 size_t
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to enable c-ares support */
+/* #undef USE_ARES */
+
+/* if axTLS is enabled */
+/* #undef USE_AXTLS */
+
+/* if CyaSSL is enabled */
+/* #undef USE_CYASSL */
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+/* #undef USE_DARWINSSL */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if GnuTLS uses nettle as crypto backend */
+/* #undef USE_GNUTLS_NETTLE */
+
+/* if librtmp is in use */
+/* #undef USE_LIBRTMP */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+/* #undef USE_MANUAL */
+
+/* Define to enable metalink support */
+/* #undef USE_METALINK */
+
+/* if nghttp2 is in use */
+/* #undef USE_NGHTTP2 */
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* Use OpenLDAP-specific code */
+/* #undef USE_OPENLDAP */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if PolarSSL is enabled */
+/* #undef USE_POLARSSL */
+
+/* to enable Windows native SSL/TLS support */
+/* #undef USE_SCHANNEL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* if you want POSIX threaded DNS lookup */
+#define USE_THREADS_POSIX 1
+
+/* Use TLS-SRP authentication */
+/* #undef USE_TLS_SRP */
+
+/* Use Unix domain sockets */
+/* #undef USE_UNIX_SOCKETS */
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+/* #undef USE_WIN32_IDN */
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_SMALL_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+#define VERSION "-"
+
+/* Define to 1 to provide own prototypes. */
+/* #undef WANT_IDN_PROTOTYPES */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
diff --git a/libcurl/src/lib/config-mac.h b/libcurl/src/lib/config-mac.h
new file mode 100644
index 0000000..ee7a659
--- /dev/null
+++ b/libcurl/src/lib/config-mac.h
@@ -0,0 +1,125 @@
+#ifndef HEADER_CURL_CONFIG_MAC_H
+#define HEADER_CURL_CONFIG_MAC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* =================================================================== */
+/* Hand crafted config file for Mac OS 9 */
+/* =================================================================== */
+/* On Mac OS X you must run configure to generate curl_config.h file */
+/* =================================================================== */
+
+#define OS "mac"
+
+/* Define if you want the built-in manual */
+#define USE_MANUAL 1
+
+#define HAVE_ERRNO_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_SELECT_H 1
+#define HAVE_NETDB_H 1
+#define HAVE_ARPA_INET_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_NET_IF_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_GETTIMEOFDAY 1
+#define HAVE_FCNTL_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_ALLOCA_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UTIME_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_UTIME_H 1
+
+#define TIME_WITH_SYS_TIME 1
+
+#define HAVE_ALARM 1
+#define HAVE_FTRUNCATE 1
+#define HAVE_UTIME 1
+#define HAVE_SETVBUF 1
+#define HAVE_STRFTIME 1
+#define HAVE_INET_ADDR 1
+#define HAVE_MEMCPY 1
+#define HAVE_SELECT 1
+#define HAVE_SOCKET 1
+#define HAVE_STRUCT_TIMEVAL 1
+
+#define HAVE_SIGACTION 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_SIG_ATOMIC_T 1
+
+#ifdef MACOS_SSL_SUPPORT
+# define USE_OPENSSL 1
+#endif
+
+#define CURL_DISABLE_LDAP 1
+
+#define HAVE_RAND_STATUS 1
+#define HAVE_RAND_EGD 1
+
+#define HAVE_IOCTL 1
+#define HAVE_IOCTL_FIONBIO 1
+
+#define RETSIGTYPE void
+
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_SIZE_T 4
+
+#define HAVE_GETNAMEINFO 1
+#define GETNAMEINFO_QUAL_ARG1 const
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+#define GETNAMEINFO_TYPE_ARG46 size_t
+#define GETNAMEINFO_TYPE_ARG7 int
+
+#define HAVE_RECV 1
+#define RECV_TYPE_ARG1 int
+#define RECV_TYPE_ARG2 void *
+#define RECV_TYPE_ARG3 size_t
+#define RECV_TYPE_ARG4 int
+#define RECV_TYPE_RETV ssize_t
+
+#define HAVE_RECVFROM 1
+#define RECVFROM_TYPE_ARG1 int
+#define RECVFROM_TYPE_ARG2 void
+#define RECVFROM_TYPE_ARG3 size_t
+#define RECVFROM_TYPE_ARG4 int
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 int
+#define RECVFROM_TYPE_RETV ssize_t
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+#define HAVE_SEND 1
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 void *
+#define SEND_TYPE_ARG3 size_T
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV ssize_t
+
+#define HAVE_EXTRA_STRICMP_H 1
+#define HAVE_EXTRA_STRDUP_H 1
+
+#endif /* HEADER_CURL_CONFIG_MAC_H */
diff --git a/libcurl/src/lib/config-os400.h b/libcurl/src/lib/config-os400.h
new file mode 100644
index 0000000..1e62228
--- /dev/null
+++ b/libcurl/src/lib/config-os400.h
@@ -0,0 +1,563 @@
+#ifndef HEADER_CURL_CONFIG_OS400_H
+#define HEADER_CURL_CONFIG_OS400_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for OS/400 */
+/* ================================================================ */
+
+#pragma enum(int)
+
+#undef PACKAGE
+
+/* Version number of this archive. */
+#undef VERSION
+
+/* Define if you have the getpass function. */
+#undef HAVE_GETPASS
+
+/* Define cpu-machine-OS */
+#define OS "OS/400"
+
+/* Define if you have the gethostbyaddr_r() function with 5 arguments */
+#define HAVE_GETHOSTBYADDR_R_5
+
+/* Define if you have the gethostbyaddr_r() function with 7 arguments */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* Define if you have the gethostbyaddr_r() function with 8 arguments */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its
+ * prototype is incompatible with the "standard" one (1st argument is not
+ * const). However, getaddrinfo() is supported (ASCII version defined as
+ * a local wrapper in setup-os400.h) in a threadsafe way: we can then
+ * configure getaddrinfo() as such and get rid of gethostbyname_r() without
+ * loss of threadsafeness. */
+#undef HAVE_GETHOSTBYNAME_R
+#undef HAVE_GETHOSTBYNAME_R_3
+#undef HAVE_GETHOSTBYNAME_R_5
+#undef HAVE_GETHOSTBYNAME_R_6
+#define HAVE_GETADDRINFO
+#define HAVE_GETADDRINFO_THREADSAFE
+
+/* Define if you need the _REENTRANT define for some functions */
+#undef NEED_REENTRANT
+
+/* Define if you have the Kerberos4 libraries (including -ldes) */
+#undef HAVE_KRB4
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define this to 'int' if ssize_t is not an available typedefed type */
+#undef ssize_t
+
+/* Define this as a suitable file to read random data from */
+#undef RANDOM_FILE
+
+/* Define this to your Entropy Gathering Daemon socket pathname */
+#undef EGD_SOCKET
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define if you have the <alloca.h> header file. */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H
+
+/* Define if you have the `closesocket' function. */
+#undef HAVE_CLOSESOCKET
+
+/* Define if you have the <crypto.h> header file. */
+#undef HAVE_CRYPTO_H
+
+/* Define if you have the <des.h> header file. */
+#undef HAVE_DES_H
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
+/* Define if you have the <err.h> header file. */
+#undef HAVE_ERR_H
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H
+
+/* Define if you have the `geteuid' function. */
+#define HAVE_GETEUID
+
+/* Define if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR
+
+/* Define if you have the `gethostbyaddr_r' function. */
+#define HAVE_GETHOSTBYADDR_R
+
+/* Define if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME
+
+/* Define if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define if you have the `getpass_r' function. */
+#undef HAVE_GETPASS_R
+
+/* Define if you have the `getpwuid' function. */
+#define HAVE_GETPWUID
+
+/* Define if you have the `getservbyname' function. */
+#define HAVE_GETSERVBYNAME
+
+/* Define if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY
+
+/* Define if you have the `timeval' struct. */
+#define HAVE_STRUCT_TIMEVAL
+
+/* Define if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H
+
+/* Define if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define if you have the `krb_get_our_ip_for_realm' function. */
+#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
+
+/* Define if you have the <krb.h> header file. */
+#undef HAVE_KRB_H
+
+/* Define if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define if you have the `resolve' library (-lresolve). */
+#undef HAVE_LIBRESOLVE
+
+/* Define if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
+/* Define if you have GSS API. */
+#define HAVE_GSSAPI
+
+/* Define if you have the GNU gssapi libraries */
+#undef HAVE_GSSGNU
+
+/* Define if you have the Heimdal gssapi libraries */
+#define HAVE_GSSHEIMDAL
+
+/* Define if you have the MIT gssapi libraries */
+#undef HAVE_GSSMIT
+
+/* Define if you have the `ucb' library (-lucb). */
+#undef HAVE_LIBUCB
+
+/* Define if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R
+
+/* Define if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H
+
+/* Define if you need the malloc.h header file even with stdlib.h */
+/* #define NEED_MALLOC_H 1 */
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H
+
+/* Define if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H
+
+/* Define if you have the <openssl/crypto.h> header file. */
+#undef HAVE_OPENSSL_CRYPTO_H
+
+/* Define if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define if you have the <openssl/pem.h> header file. */
+#undef HAVE_OPENSSL_PEM_H
+
+/* Define if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
+/* Define if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define if you have the <openssl/x509.h> header file. */
+#undef HAVE_OPENSSL_X509_H
+
+/* Define if you have the <pem.h> header file. */
+#undef HAVE_PEM_H
+
+/* Define if you have the `perror' function. */
+#define HAVE_PERROR
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H
+
+/* Define if you have the `RAND_egd' function. */
+#undef HAVE_RAND_EGD
+
+/* Define if you have the `RAND_screen' function. */
+#undef HAVE_RAND_SCREEN
+
+/* Define if you have the `RAND_status' function. */
+#undef HAVE_RAND_STATUS
+
+/* Define if you have the <rsa.h> header file. */
+#undef HAVE_RSA_H
+
+/* Define if you have the `select' function. */
+#define HAVE_SELECT
+
+/* Define if you have the `setvbuf' function. */
+#define HAVE_SETVBUF
+
+/* Define if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define if you have the `sigaction' function. */
+#define HAVE_SIGACTION
+
+/* Define if you have the `signal' function. */
+#undef HAVE_SIGNAL
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T
+
+/* Define if sig_atomic_t is already defined as volatile. */
+#undef HAVE_SIG_ATOMIC_T_VOLATILE
+
+/* Define if you have the `socket' function. */
+#define HAVE_SOCKET
+
+/* Define if you have the <ssl.h> header file. */
+#undef HAVE_SSL_H
+
+/* Define if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+
+/* The following define is needed on OS400 to enable strcmpi(), stricmp() and
+ strdup(). */
+#define __cplusplus__strings__
+
+/* Define if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the `strcmpi' function. */
+#define HAVE_STRCMPI
+
+/* Define if you have the `stricmp' function. */
+#define HAVE_STRICMP
+
+/* Define if you have the `strdup' function. */
+#define HAVE_STRDUP
+
+
+/* Define if you have the `strftime' function. */
+#define HAVE_STRFTIME
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define if you have the <stropts.h> header file. */
+#undef HAVE_STROPTS_H
+
+/* Define if you have the `strstr' function. */
+#define HAVE_STRSTR
+
+/* Define if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R
+
+/* Define if you have the `strtoll' function. */
+#undef HAVE_STRTOLL /* Allows ASCII compile on V5R1. */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H
+
+/* Define if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H
+
+/* Define if you have the `tcgetattr' function. */
+#undef HAVE_TCGETATTR
+
+/* Define if you have the `tcsetattr' function. */
+#undef HAVE_TCSETATTR
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H
+
+/* Define if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H
+
+/* Define if you have the <winsock.h> header file. */
+#undef HAVE_WINSOCK_H
+
+/* Define if you have the <x509.h> header file. */
+#undef HAVE_X509_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 8
+
+/* Define if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG
+
+/* The size of a `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* Whether long long constants must be suffixed by LL. */
+
+#define HAVE_LL
+
+/* Define this if you have struct sockaddr_storage */
+#define HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#define _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* type to use in place of in_addr_t if not defined */
+#define in_addr_t unsigned long
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define if you have the ioctl function. */
+#define HAVE_IOCTL
+
+/* Define if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO
+
+/* Define if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR
+
+/* To disable LDAP */
+#undef CURL_DISABLE_LDAP
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL
+
+/* Define if you have the ldap_url_parse procedure. */
+/* #define HAVE_LDAP_URL_PARSE */ /* Disabled because of an IBM bug. */
+
+/* Define if you have the getnameinfo function. */
+/* OS400 has no ASCII version of this procedure: wrapped in setup-os400.h. */
+#define HAVE_GETNAMEINFO
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 socklen_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define if you have the recvfrom function. */
+#define HAVE_RECVFROM
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define if you have the send function. */
+#define HAVE_SEND
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* Define to use the GSKit package. */
+#define USE_GSKIT
+
+/* Define to use the OS/400 crypto library. */
+#define USE_OS400CRYPTO
+
+/* Define to use Unix sockets. */
+#define USE_UNIX_SOCKETS
+
+/* Use the system keyring as the default CA bundle. */
+#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"
+
+/* ---------------------------------------------------------------- */
+/* ADDITIONAL DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* The following must be defined BEFORE system header files inclusion. */
+
+#define __ptr128 /* No teraspace. */
+#define qadrt_use_fputc_inline /* Generate fputc() wrapper inline. */
+#define qadrt_use_fread_inline /* Generate fread() wrapper inline. */
+#define qadrt_use_fwrite_inline /* Generate fwrite() wrapper inline. */
+
+#endif /* HEADER_CURL_CONFIG_OS400_H */
diff --git a/libcurl/src/lib/config-osx.h b/libcurl/src/lib/config-osx.h
new file mode 100644
index 0000000..c94f53e
--- /dev/null
+++ b/libcurl/src/lib/config-osx.h
@@ -0,0 +1,1019 @@
+/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+#define CURL_DISABLE_COOKIES 1
+
+/* to disable cryptographic authentication */
+#define CURL_DISABLE_CRYPTO_AUTH 1
+
+/* to disable DICT */
+#define CURL_DISABLE_DICT 1
+
+/* to disable FILE */
+#define CURL_DISABLE_FILE 1
+
+/* to disable FTP */
+#define CURL_DISABLE_FTP 1
+
+/* to disable Gopher */
+#define CURL_DISABLE_GOPHER 1
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable IMAP */
+#define CURL_DISABLE_IMAP 1
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable --libcurl C code generation option */
+#define CURL_DISABLE_LIBCURL_OPTION 1
+
+/* to disable POP3 */
+#define CURL_DISABLE_POP3 1
+
+/* to disable proxies */
+#define CURL_DISABLE_PROXY 1
+
+/* to disable RTSP */
+#define CURL_DISABLE_RTSP 1
+
+/* to disable SMB/CIFS */
+#define CURL_DISABLE_SMB 1
+
+/* to disable SMTP */
+#define CURL_DISABLE_SMTP 1
+
+/* to disable TELNET */
+#define CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+#define CURL_DISABLE_TFTP 1
+
+/* to disable TLS-SRP authentication */
+#define CURL_DISABLE_TLS_SRP 1
+
+/* to disable verbose strings */
+#define CURL_DISABLE_VERBOSE_STRINGS 1
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6 1
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 size_t
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 socklen_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+/* #undef GETSERVBYPORT_R_ARGS */
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+/* #undef GETSERVBYPORT_R_BUFSIZE */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+#define HAVE_ARPA_TFTP_H 1
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+/* #undef HAVE_CYASSL_ERROR_SSL_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the fsetxattr function. */
+#define HAVE_FSETXATTR 1
+
+/* fsetxattr() takes 5 args */
+/* #undef HAVE_FSETXATTR_5 */
+
+/* fsetxattr() takes 6 args */
+#define HAVE_FSETXATTR_6 1
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the gai_strerror function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#define HAVE_GETADDRINFO_THREADSAFE 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+/* #undef HAVE_GETHOSTBYADDR_R */
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+/* #undef HAVE_GETHOSTBYADDR_R_8 */
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#define HAVE_GETPWUID_R 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the function gnutls_srp_verifier */
+/* #undef HAVE_GNUTLS_SRP */
+
+/* if you have GSS-API libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have GNU GSS */
+/* #undef HAVE_GSSGNU */
+
+/* if you have Heimdal */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have MIT Kerberos */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#define HAVE_IF_NAMETOINDEX 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+/* #undef HAVE_LDAP_INIT_FD */
+
+/* Use LDAPS implementation */
+/* #undef HAVE_LDAP_SSL */
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+/* #undef HAVE_LIBRTMP_RTMP_H */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the memrchr function or macro. */
+/* #undef HAVE_MEMRCHR */
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+/* #undef HAVE_MSG_NOSIGNAL */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#define HAVE_POLL 1
+
+/* If you have a fine poll */
+#define HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* if you have <pthread.h> */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+#define HAVE_SETMODE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#define HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* if you have the function SRP_Calc_client_key */
+/* #undef HAVE_SSLEAY_SRP */
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+/* #undef HAVE_SSLV2_CLIENT_METHOD */
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/* #undef HAVE_SSL_GET_SHUTDOWN */
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#define HAVE_SYS_XATTR_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#define HAVE_WRITABLE_ARGV 1
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_ENABLED */
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_FILE */
+
+/* cpu-machine-OS */
+#define OS "x86_64-apple-darwin13.4.0"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV ssize_t
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV ssize_t
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `long long', as computed by sizeof. */
+/* #undef SIZEOF_LONG_LONG */
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 8
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#define STRERROR_R_TYPE_ARG3 size_t
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to enable c-ares support */
+/* #undef USE_ARES */
+
+/* if axTLS is enabled */
+/* #undef USE_AXTLS */
+
+/* if CyaSSL is enabled */
+/* #undef USE_CYASSL */
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+/* #undef USE_DARWINSSL */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if GnuTLS uses nettle as crypto backend */
+/* #undef USE_GNUTLS_NETTLE */
+
+/* if librtmp is in use */
+/* #undef USE_LIBRTMP */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+/* #undef USE_MANUAL */
+
+/* Define to enable metalink support */
+/* #undef USE_METALINK */
+
+/* if nghttp2 is in use */
+/* #undef USE_NGHTTP2 */
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* Use OpenLDAP-specific code */
+/* #undef USE_OPENLDAP */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if PolarSSL is enabled */
+/* #undef USE_POLARSSL */
+
+/* to enable Windows native SSL/TLS support */
+/* #undef USE_SCHANNEL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* if you want POSIX threaded DNS lookup */
+#define USE_THREADS_POSIX 1
+
+/* Use TLS-SRP authentication */
+/* #undef USE_TLS_SRP */
+
+/* Use Unix domain sockets */
+/* #undef USE_UNIX_SOCKETS */
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+/* #undef USE_WIN32_IDN */
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_SMALL_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+#define VERSION "-"
+
+/* Define to 1 to provide own prototypes. */
+/* #undef WANT_IDN_PROTOTYPES */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
diff --git a/libcurl/src/lib/config-riscos.h b/libcurl/src/lib/config-riscos.h
new file mode 100644
index 0000000..e400577
--- /dev/null
+++ b/libcurl/src/lib/config-riscos.h
@@ -0,0 +1,513 @@
+#ifndef HEADER_CURL_CONFIG_RISCOS_H
+#define HEADER_CURL_CONFIG_RISCOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for RISC OS */
+/* ================================================================ */
+
+/* Name of this package! */
+#undef PACKAGE
+
+/* Version number of this archive. */
+#undef VERSION
+
+/* Define if you have the getpass function. */
+#undef HAVE_GETPASS
+
+/* Define cpu-machine-OS */
+#define OS "ARM-RISC OS"
+
+/* Define if you want the built-in manual */
+#define USE_MANUAL
+
+/* Define if you have the gethostbyaddr_r() function with 5 arguments */
+#undef HAVE_GETHOSTBYADDR_R_5
+
+/* Define if you have the gethostbyaddr_r() function with 7 arguments */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* Define if you have the gethostbyaddr_r() function with 8 arguments */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* Define if you have the gethostbyname_r() function with 3 arguments */
+#undef HAVE_GETHOSTBYNAME_R_3
+
+/* Define if you have the gethostbyname_r() function with 5 arguments */
+#undef HAVE_GETHOSTBYNAME_R_5
+
+/* Define if you have the gethostbyname_r() function with 6 arguments */
+#undef HAVE_GETHOSTBYNAME_R_6
+
+/* Define if you need the _REENTRANT define for some functions */
+#undef NEED_REENTRANT
+
+/* Define if you have the Kerberos4 libraries (including -ldes) */
+#undef HAVE_KRB4
+
+/* Define if you want to enable IPv6 support */
+#undef ENABLE_IPV6
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define this to 'int' if ssize_t is not an available typedefed type */
+#undef ssize_t
+
+/* Define this as a suitable file to read random data from */
+#undef RANDOM_FILE
+
+/* Define this to your Entropy Gathering Daemon socket pathname */
+#undef EGD_SOCKET
+
+/* Define if you want to enable IPv6 support */
+#undef ENABLE_IPV6
+
+/* Define if you have the alarm function. */
+#define HAVE_ALARM
+
+/* Define if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H
+
+/* Define if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H
+
+/* Define if you have the `closesocket' function. */
+#undef HAVE_CLOSESOCKET
+
+/* Define if you have the <crypto.h> header file. */
+#undef HAVE_CRYPTO_H
+
+/* Define if you have the <des.h> header file. */
+#undef HAVE_DES_H
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
+/* Define if you have the <err.h> header file. */
+#undef HAVE_ERR_H
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H
+
+/* Define if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE
+
+/* Define if getaddrinfo exists and works */
+#define HAVE_GETADDRINFO
+
+/* Define if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR
+
+/* Define if you have the `gethostbyaddr_r' function. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* Define if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME
+
+/* Define if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H
+
+/* Define if you have the `getpass_r' function. */
+#undef HAVE_GETPASS_R
+
+/* Define if you have the `getpwuid' function. */
+#undef HAVE_GETPWUID
+
+/* Define if you have the `getservbyname' function. */
+#undef HAVE_GETSERVBYNAME
+
+/* Define if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY
+
+/* Define if you have the `timeval' struct. */
+#define HAVE_STRUCT_TIMEVAL
+
+/* Define if you have the `inet_addr' function. */
+#undef HAVE_INET_ADDR
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H
+
+/* Define if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define if you have the `krb_get_our_ip_for_realm' function. */
+#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
+
+/* Define if you have the <krb.h> header file. */
+#undef HAVE_KRB_H
+
+/* Define if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define if you have the `resolve' library (-lresolve). */
+#undef HAVE_LIBRESOLVE
+
+/* Define if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
+/* Define if you have the `ucb' library (-lucb). */
+#undef HAVE_LIBUCB
+
+/* Define if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H
+
+/* Define if you need the malloc.h header file even with stdlib.h */
+/* #define NEED_MALLOC_H 1 */
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H
+
+/* Define if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H
+
+/* Define if you have the <openssl/crypto.h> header file. */
+#undef HAVE_OPENSSL_CRYPTO_H
+
+/* Define if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define if you have the <openssl/pem.h> header file. */
+#undef HAVE_OPENSSL_PEM_H
+
+/* Define if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
+/* Define if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define if you have the <openssl/x509.h> header file. */
+#undef HAVE_OPENSSL_X509_H
+
+/* Define if you have the <pem.h> header file. */
+#undef HAVE_PEM_H
+
+/* Define if you have the `perror' function. */
+#undef HAVE_PERROR
+
+/* Define if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define if you have the `RAND_egd' function. */
+#undef HAVE_RAND_EGD
+
+/* Define if you have the `RAND_screen' function. */
+#undef HAVE_RAND_SCREEN
+
+/* Define if you have the `RAND_status' function. */
+#undef HAVE_RAND_STATUS
+
+/* Define if you have the <rsa.h> header file. */
+#undef HAVE_RSA_H
+
+/* Define if you have the `select' function. */
+#define HAVE_SELECT
+
+/* Define if you have the `setvbuf' function. */
+#undef HAVE_SETVBUF
+
+/* Define if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H
+
+/* Define if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
+/* Define if you have the `signal' function. */
+#define HAVE_SIGNAL
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T
+
+/* Define if sig_atomic_t is already defined as volatile. */
+#undef HAVE_SIG_ATOMIC_T_VOLATILE
+
+/* Define if you have the `socket' function. */
+#define HAVE_SOCKET
+
+/* Define if you have the <ssl.h> header file. */
+#undef HAVE_SSL_H
+
+/* Define if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+/* Define if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the `strcmpi' function. */
+#undef HAVE_STRCMPI
+
+/* Define if you have the `strdup' function. */
+#define HAVE_STRDUP
+
+/* Define if you have the `strftime' function. */
+#define HAVE_STRFTIME
+
+/* Define if you have the `stricmp' function. */
+#define HAVE_STRICMP
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define if you have the `strstr' function. */
+#define HAVE_STRSTR
+
+/* Define if you have the `strtok_r' function. */
+#undef HAVE_STRTOK_R
+
+/* Define if you have the `strtoll' function. */
+#undef HAVE_STRTOLL
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H
+
+/* Define if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H
+
+/* Define if you have the `tcgetattr' function. */
+#define HAVE_TCGETATTR
+
+/* Define if you have the `tcsetattr' function. */
+#define HAVE_TCSETATTR
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define if you have the `uname' function. */
+#define HAVE_UNAME
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H
+
+/* Define if you have the <winsock.h> header file. */
+#undef HAVE_WINSOCK_H
+
+/* Define if you have the <x509.h> header file. */
+#undef HAVE_X509_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long double', as computed by sizeof. */
+#undef SIZEOF_LONG_DOUBLE
+
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define if you have the ioctl function. */
+#define HAVE_IOCTL
+
+/* Define if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP
+
+/* Define if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV ssize_t
+
+/* Define 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 void
+
+/* Define if the type pointed by arg 2 for recvfrom is void. */
+#define RECVFROM_TYPE_ARG2_IS_VOID
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV ssize_t
+
+/* Define if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV ssize_t
+
+#endif /* HEADER_CURL_CONFIG_RISCOS_H */
diff --git a/libcurl/src/lib/config-symbian.h b/libcurl/src/lib/config-symbian.h
new file mode 100644
index 0000000..a40e3d8
--- /dev/null
+++ b/libcurl/src/lib/config-symbian.h
@@ -0,0 +1,811 @@
+#ifndef HEADER_CURL_CONFIG_SYMBIAN_H
+#define HEADER_CURL_CONFIG_SYMBIAN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for Symbian */
+/* ================================================================ */
+
+/* Location of default ca bundle */
+/* #define CURL_CA_BUNDLE "/etc/pki/tls/certs/ca-bundle.crt"*/
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+/* #undef CURL_DISABLE_FTP */
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable TELNET */
+/* #undef CURL_DISABLE_TELNET */
+
+/* to disable TFTP */
+/* #undef CURL_DISABLE_TFTP */
+
+/* to disable verbose strings */
+/* #define CURL_DISABLE_VERBOSE_STRINGS 1*/
+
+/* Definition to make a library symbol externally visible. */
+/* #undef CURL_EXTERN_SYMBOL */
+
+/* Use Windows LDAP implementation */
+/* #undef USE_WIN32_LDAP */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6 1
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define to 1 if you have the <alloca.h> header file. */
+/*#define HAVE_ALLOCA_H 1*/
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/*#define HAVE_ARPA_TFTP_H 1*/
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `basename' function. */
+/*#define HAVE_BASENAME 1*/
+
+/* Define to 1 if bool is an available type. */
+/*#define HAVE_BOOL_T 1*/
+
+/* Define to 1 if you have the `closesocket' function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/*#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1*/
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <des.h> header file. */
+/* #undef HAVE_DES_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/*#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1*/
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the `fork' function. */
+/*#define HAVE_FORK 1*/
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if getaddrinfo exists and works */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* If you have gethostbyname */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+/*#define HAVE_GETRLIMIT 1*/
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* we have a glibc-style strerror_r() */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the gssapi libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have the GNU gssapi libraries */
+/* #undef HAVE_GSSGNU */
+
+/* if you have the Heimdal gssapi libraries */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have the MIT gssapi libraries */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/*#define HAVE_IDNA_STRERROR 1*/
+
+/* Define to 1 if you have the `idn_free' function. */
+/*#define HAVE_IDN_FREE 1*/
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/*#define HAVE_IDN_FREE_H 1*/
+
+/* Define to 1 if you have the `inet_addr' function. */
+/*#define HAVE_INET_ADDR 1*/
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+/*#define HAVE_INET_NTOP 1*/
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+/*#define HAVE_INET_PTON 1*/
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO
+ function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* if you have the Kerberos4 libraries (including -ldes) */
+/* #undef HAVE_KRB4 */
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
+
+/* Define to 1 if you have the <krb.h> header file. */
+/* #undef HAVE_KRB_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/*#define HAVE_LBER_H 1*/
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/*#define HAVE_LDAP_H 1*/
+
+/* Use LDAPS implementation */
+/*#define HAVE_LDAP_SSL 1*/
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/*#define HAVE_LDAP_URL_PARSE 1*/
+
+/* Define to 1 if you have the <libgen.h> header file. */
+/*#define HAVE_LIBGEN_H 1*/
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/*#define HAVE_LIBIDN 1*/
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/*#define HAVE_LIBSSH2 1*/
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/*#define HAVE_LIBSSH2_H 1*/
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/*#define HAVE_LIBSSL 1*/
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+/*#define HAVE_MALLOC_H 1*/
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+/*#define HAVE_MSG_NOSIGNAL 1*/
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+/*#define HAVE_NETINET_TCP_H 1*/
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/*#define HAVE_NI_WITHSCOPEID 1*/
+
+/* we have no strerror_r() proto */
+/* #undef HAVE_NO_STRERROR_R_DECL */
+
+/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/*#define HAVE_OPENSSL_CRYPTO_H 1*/
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/*#define HAVE_OPENSSL_ENGINE_H 1*/
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/*#define HAVE_OPENSSL_ERR_H 1*/
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/*#define HAVE_OPENSSL_PEM_H 1*/
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/*#define HAVE_OPENSSL_PKCS12_H 1*/
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/*#define HAVE_OPENSSL_RSA_H 1*/
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/*#define HAVE_OPENSSL_SSL_H 1*/
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/*#define HAVE_OPENSSL_X509_H 1*/
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `poll' function. */
+/*#define HAVE_POLL 1*/
+
+/* If you have a fine poll */
+/*#define HAVE_POLL_FINE 1*/
+
+/* Define to 1 if you have the <poll.h> header file. */
+/*#define HAVE_POLL_H 1*/
+
+/* we have a POSIX-style strerror_r() */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+#define HAVE_RAND_EGD 1
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/*#define HAVE_RAND_STATUS 1*/
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+/* #undef HAVE_SETMODE */
+
+/* Define to 1 if you have the `setrlimit' function. */
+/*#define HAVE_SETRLIMIT 1*/
+
+/* Define to 1 if you have the setsockopt function. */
+/* #undef HAVE_SETSOCKOPT */
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+/*#define HAVE_SGTTY_H 1*/
+
+/* Define to 1 if you have the `sigaction' function. */
+/*#define HAVE_SIGACTION 1*/
+
+/* Define to 1 if you have the `siginterrupt' function. */
+/*#define HAVE_SIGINTERRUPT 1*/
+
+/* Define to 1 if you have the `signal' function. */
+/*#define HAVE_SIGNAL 1*/
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* If you have sigsetjmp */
+/*#define HAVE_SIGSETJMP 1*/
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+/*#define HAVE_SIG_ATOMIC_T 1*/
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/*#define HAVE_SSL_GET_SHUTDOWN 1*/
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+/*#define HAVE_SYS_POLL_H 1*/
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+/*#define HAVE_TERMIOS_H 1*/
+
+/* Define to 1 if you have the <termio.h> header file. */
+/*#define HAVE_TERMIO_H 1*/
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/*#define HAVE_TLD_H 1*/
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/*#define HAVE_TLD_STRERROR 1*/
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+/*#define HAVE_VARIADIC_MACROS_GCC 1*/
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+/*#define HAVE_WRITABLE_ARGV 1*/
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* cpu-machine-OS */
+#ifdef __WINS__
+#define OS "i386-pc-epoc32"
+#elif __MARM__
+#define OS "arm-unknown-epoc32"
+#else
+/* This won't happen on any current Symbian version */
+#define OS "unknown-unknown-epoc32"
+#endif
+
+/* Name of package */
+/*#define PACKAGE "curl"*/
+
+/* Define to the address where bug reports for this package should be sent. */
+/*#define PACKAGE_BUGREPORT \
+ "a suitable curl mailing list => http://curl.haxx.se/mail/"*/
+
+/* Define to the full name of this package. */
+/*#define PACKAGE_NAME "curl"*/
+
+/* Define to the full name and version of this package. */
+/*#define PACKAGE_STRING "curl -"*/
+
+/* Define to the one symbol short name of this package. */
+/*#define PACKAGE_TARNAME "curl"*/
+
+/* Define to the version of this package. */
+/*#define PACKAGE_VERSION "-"*/
+
+/* a suitable file to read random data from */
+/*#define RANDOM_FILE "/dev/urandom"*/
+
+#define RECV_TYPE_ARG1 int
+#define RECV_TYPE_ARG2 void*
+#define RECV_TYPE_ARG3 size_t
+#define RECV_TYPE_ARG4 int
+#define RECV_TYPE_RETV ssize_t
+
+#define RECVFROM_TYPE_ARG1 int
+#define RECVFROM_TYPE_ARG2 void
+#define RECVFROM_TYPE_ARG3 size_t
+#define RECVFROM_TYPE_ARG4 int
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 size_t
+#define RECVFROM_TYPE_RETV ssize_t
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 void*
+#define SEND_TYPE_ARG3 size_t
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV ssize_t
+
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+/*#define RETSIGTYPE void*/
+
+/* Define to the type of arg 1 for `select'. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#define SELECT_TYPE_ARG234 (fd_set *)
+
+/* Define to the type of arg 5 for `select'. */
+#define SELECT_TYPE_ARG5 (struct timeval *)
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if you want to enable c-ares support */
+/* #undef USE_ARES */
+
+/* Define to disable non-blocking sockets */
+/* #undef USE_BLOCKING_SOCKETS */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if libSSH2 is in use */
+/*#define USE_LIBSSH2 1*/
+
+/* If you want to build curl with the built-in manual */
+/*#define USE_MANUAL 1*/
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+/*#define VERSION "7.18.2-CVS"*/
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* type to use in place of in_addr_t if not defined */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
+
+/* Enabling curl debug mode when building in Symbian debug mode would work */
+/* except that debug mode introduces new exports that must be frozen. */
+#ifdef _DEBUG
+/* #define CURLDEBUG */
+#endif
+
+/* sys/cdefs.h fails to define this for WINSCW prior to Symbian OS ver. 9.4 */
+#ifndef __LONG_LONG_SUPPORTED
+#define __LONG_LONG_SUPPORTED
+#endif
+
+/* Enable appropriate header only when zlib support is enabled */
+#ifdef HAVE_LIBZ
+#define HAVE_ZLIB_H 1
+#endif
+
+#endif /* HEADER_CURL_CONFIG_SYMBIAN_H */
diff --git a/libcurl/src/lib/config-tpf.h b/libcurl/src/lib/config-tpf.h
new file mode 100644
index 0000000..d6b8cc2
--- /dev/null
+++ b/libcurl/src/lib/config-tpf.h
@@ -0,0 +1,772 @@
+#ifndef HEADER_CURL_CONFIG_TPF_H
+#define HEADER_CURL_CONFIG_TPF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for TPF */
+/* ================================================================ */
+
+/* ---------------------------------------------------------------- */
+/* FEATURES, FUNCTIONS, and DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* NOTE: Refer also to the .mak file for some of the flags below */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+/* #undef CURL_DISABLE_FTP */
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable LDAP */
+/* #undef CURL_DISABLE_LDAP */
+
+/* to disable TELNET */
+/* #undef CURL_DISABLE_TELNET */
+
+/* to disable TFTP */
+/* #undef CURL_DISABLE_TFTP */
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* lber dynamic library file */
+/* #undef DL_LBER_FILE */
+
+/* ldap dynamic library file */
+/* #undef DL_LDAP_FILE */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+/* #undef ENABLE_IPV6 */
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */
+
+/* Define to the type of arg 1 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG1 */
+
+/* Define to the type of arg 2 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG2 */
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG46 */
+
+/* Define to the type of arg 7 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG7 */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/* #undef HAVE_ARPA_TFTP_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `basename' function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if you have the `closesocket' function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+#define HAVE_CRYPTO_H 1
+
+/* Define to 1 if you have the <des.h> header file. */
+/* #undef HAVE_DES_H */
+#define HAVE_DES_H 1
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the `fork' function. */
+/* #undef HAVE_FORK */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if getaddrinfo exists and works */
+/* #undef HAVE_GETADDRINFO */
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* If you have gethostbyname */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 1 */
+
+/* Define to 1 if you have the getnameinfo function. */
+/* #undef HAVE_GETNAMEINFO */
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getprotobyname' function. */
+/* #undef HAVE_GETPROTOBYNAME */
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+/* #undef HAVE_GETRLIMIT */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* we have a glibc-style strerror_r() */
+/* #undef HAVE_GLIBC_STRERROR_R */
+#define HAVE_GLIBC_STRERROR_R 1
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the gssapi libraries */
+/* #undef HAVE_GSSAPI */
+
+/* if you have the GNU gssapi libraries */
+/* #undef HAVE_GSSGNU */
+
+/* if you have the Heimdal gssapi libraries */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have the MIT gssapi libraries */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `iconv' functions. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+/* #undef HAVE_INET_NTOP */
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+/* #undef HAVE_INET_PTON */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO
+ function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* if you have the Kerberos4 libraries (including -ldes) */
+/* #undef HAVE_KRB4 */
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
+
+/* Define to 1 if you have the <krb.h> header file. */
+/* #undef HAVE_KRB_H */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+/* #undef HAVE_LIBGEN_H 1 */
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+#define HAVE_LIBSSL 1
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+/* undef HAVE_NETINET_TCP_H */
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if NI_WITHSCOPEID exists and works */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* we have no strerror_r() proto */
+/* #undef HAVE_NO_STRERROR_R_DECL */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+#define HAVE_OPENSSL_CRYPTO_H 1
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+#define HAVE_OPENSSL_ENGINE_H 1
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+#define HAVE_OPENSSL_ERR_H 1
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+#define HAVE_OPENSSL_PEM_H 1
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+#define HAVE_OPENSSL_PKCS12_H 1
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+#define HAVE_OPENSSL_RSA_H 1
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+#define HAVE_OPENSSL_SSL_H 1
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+#define HAVE_OPENSSL_X509_H 1
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+#define HAVE_PEM_H 1
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `poll' function. */
+/* #undef HAVE_POLL */
+
+/* If you have a fine poll */
+/* #undef HAVE_POLL_FINE */
+
+/* we have a POSIX-style strerror_r() */
+/* #undef HAVE_POSIX_STRERROR_R */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+#define HAVE_RAND_EGD 1
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+#define HAVE_RAND_STATUS 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+#define HAVE_RSA_H 1
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+/* #undef HAVE_SETSOCKOPT */
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+/* #undef HAVE_SGTTY_H 1 */
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `siginterrupt' function. */
+/* #undef HAVE_SIGINTERRUPT */
+
+/* Define to 1 if you have the `signal' function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* If you have sigsetjmp */
+/* #undef HAVE_SIGSETJMP */
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+#define HAVE_SSL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+#define HAVE_STRICMP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+/* #undef HAVE_STRLCPY */
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+/* #undef HAVE_STRUCT_SOCKADDR_STORAGE */
+
+/* Define this if you have struct timeval */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+/* #undef HAVE_SYS_POLL_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+/* #undef HAVE_TERMIOS_H */
+
+/* Define to 1 if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if you have the <winsock2.h> header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the <winsock.h> header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+/* #undef HAVE_WRITABLE_ARGV */
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* cpu-machine-OS */
+#define OS "s390x-ibm-tpf"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT \
+ "a suitable curl mailing list => http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type of arg 1 for `select'. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#define SELECT_TYPE_ARG234 (fd_set *)
+
+/* Define to the type of arg 5 for `select'. */
+#define SELECT_TYPE_ARG5 (struct timeval *)
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if you want to enable ares support */
+/* #undef USE_ARES */
+
+/* Define to disable non-blocking sockets */
+/* #undef USE_BLOCKING_SOCKETS */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* If you want to build curl with the built-in manual */
+/* #undef USE_MANUAL */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if SSL is enabled */
+/* #undef USE_OPENSSL */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Version number of package */
+#define VERSION "not-used"
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* type to use in place of in_addr_t if not defined */
+/* #undef in_addr_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
+
+/* Define to 1 if you have the getnameinfo function. */
+/* #undef HAVE_GETNAMEINFO 1 */
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+/* #undef GETNAMEINFO_QUAL_ARG1 const */
+
+/* Define to the type of arg 1 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG1 struct sockaddr * */
+
+/* Define to the type of arg 2 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG2 socklen_t */
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG46 size_t */
+
+/* Define to the type of arg 7 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG7 int */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define to 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+#define CURL_DOES_CONVERSIONS
+#ifndef CURL_ICONV_CODESET_OF_HOST
+#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
+#endif
+
+
+#endif /* HEADER_CURL_CONFIG_TPF_H */
diff --git a/libcurl/src/lib/config-vxworks.h b/libcurl/src/lib/config-vxworks.h
new file mode 100644
index 0000000..d889efc
--- /dev/null
+++ b/libcurl/src/lib/config-vxworks.h
@@ -0,0 +1,928 @@
+#ifndef HEADER_CURL_CONFIG_VXWORKS_H
+#define HEADER_CURL_CONFIG_VXWORKS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* =============================================================== */
+/* Hand crafted config file for VxWorks */
+/* =============================================================== */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+#define CURL_DISABLE_FTP 1
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable NTLM authentication */
+#define CURL_DISABLE_NTLM 1
+
+/* to disable proxies */
+/* #undef CURL_DISABLE_PROXY */
+
+/* to disable TELNET */
+#define CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+#define CURL_DISABLE_TFTP 1
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* Definition to make a library symbol externally visible. */
+/* #undef CURL_EXTERN_SYMBOL */
+
+/* Use Windows LDAP implementation */
+/* #undef USE_WIN32_LDAP */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 unsigned int
+
+/* Specifies the number of arguments to getservbyport_r */
+#define GETSERVBYPORT_R_ARGS 6
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+#define GETSERVBYPORT_R_BUFSIZE 4096
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/* #undef HAVE_ARPA_TFTP_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `basename' function. */
+/* #undef HAVE_BASENAME */
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */
+
+/* Define to 1 if you have the `closesocket' function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <des.h> header file. */
+/* #undef HAVE_DES_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `geteuid' function. */
+/* #undef HAVE_GETEUID */
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+#define HAVE_GETHOSTBYADDR_R 1
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+#define HAVE_GETHOSTBYADDR_R_8 1
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+/* #undef HAVE_GETIFADDRS */
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+/* #undef HAVE_GETPWUID */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the gssapi libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have the GNU gssapi libraries */
+/* #undef HAVE_GSSGNU */
+
+/* if you have the Heimdal gssapi libraries */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have the MIT gssapi libraries */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+/* #undef HAVE_IFADDRS_H */
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+/* #undef HAVE_INET_NTOP */
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+/* #undef HAVE_INET_PTON */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* if you have the Kerberos4 libraries (including -ldes) */
+/* #undef HAVE_KRB4 */
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
+
+/* Define to 1 if you have the <krb.h> header file. */
+/* #undef HAVE_KRB_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Use LDAPS implementation */
+/* #undef HAVE_LDAP_SSL */
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+/* #undef HAVE_LIBGEN_H */
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `libssh2_version' function. */
+/* #undef HAVE_LIBSSH2_VERSION */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#define HAVE_LIBSSL 1
+
+/* if zlib is available */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+/* #undef HAVE_MSG_NOSIGNAL */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+#define HAVE_OPENSSL_CRYPTO_H 1
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+#define HAVE_OPENSSL_ENGINE_H 1
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+#define HAVE_OPENSSL_ERR_H 1
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+#define HAVE_OPENSSL_PEM_H 1
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+#define HAVE_OPENSSL_PKCS12_H 1
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#define HAVE_OPENSSL_RSA_H 1
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#define HAVE_OPENSSL_SSL_H 1
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+#define HAVE_OPENSSL_X509_H 1
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+/* #undef HAVE_POLL */
+
+/* If you have a fine poll */
+/* #undef HAVE_POLL_FINE */
+
+/* Define to 1 if you have the <poll.h> header file. */
+/* #undef HAVE_POLL_H */
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+/* #undef HAVE_POSIX_STRERROR_R */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+/* #undef HAVE_PWD_H */
+
+/* Define to 1 if you have the `RAND_egd' function. */
+#define HAVE_RAND_EGD 1
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+#define HAVE_RAND_STATUS 1
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+#define HAVE_SETMODE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+/* #undef HAVE_SGTTY_H */
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+/* #undef HAVE_SIGSETJMP */
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+#define HAVE_SSL_GET_SHUTDOWN 1
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+/* #undef HAVE_STRLCPY */
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+/* #undef HAVE_STRTOLL */
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+/* #undef HAVE_SYS_PARAM_H */
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+/* #undef HAVE_SYS_POLL_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#define HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have a working vxworks-style strerror_r function. */
+#define HAVE_VXWORKS_STRERROR_R 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#define HAVE_WRITABLE_ARGV 1
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+#define HAVE_ZLIB_H 1
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to 1 if the open function requires three arguments. */
+#define OPEN_NEEDS_ARG3 1
+
+/* cpu-machine-OS */
+#define OS "unknown-unknown-vxworks"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* a suitable file to read random data from */
+#define RANDOM_FILE "/dev/urandom"
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 void
+
+/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
+/* #undef RECVFROM_TYPE_ARG5_IS_VOID */
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 socklen_t
+
+/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
+/* #undef RECVFROM_TYPE_ARG6_IS_VOID */
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+/* #undef STRERROR_R_TYPE_ARG3 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #undef TIME_WITH_SYS_TIME */
+
+/* Define if you want to enable c-ares support */
+/* #undef USE_ARES */
+
+/* Define to disable non-blocking sockets. */
+/* #undef USE_BLOCKING_SOCKETS */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* if OpenSSL is in use */
+#define USE_OPENSSL 1
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
+
+#endif /* HEADER_CURL_CONFIG_VXWORKS_H */
diff --git a/libcurl/src/lib/config-win32.h b/libcurl/src/lib/config-win32.h
new file mode 100644
index 0000000..e9a3712
--- /dev/null
+++ b/libcurl/src/lib/config-win32.h
@@ -0,0 +1,734 @@
+#ifndef HEADER_CURL_CONFIG_WIN32_H
+#define HEADER_CURL_CONFIG_WIN32_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for Windows */
+/* ================================================================ */
+
+/* ---------------------------------------------------------------- */
+/* HEADER FILES */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the <arpa/inet.h> header file. */
+/* #define HAVE_ARPA_INET_H 1 */
+
+/* Define if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define if you have the <crypto.h> header file. */
+/* #define HAVE_CRYPTO_H 1 */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <err.h> header file. */
+/* #define HAVE_ERR_H 1 */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <getopt.h> header file. */
+#if defined(__MINGW32__) || defined(__POCC__)
+#define HAVE_GETOPT_H 1
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#define HAVE_INTTYPES_H 1
+#endif
+
+/* Define if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you need <malloc.h> header even with <stdlib.h> header file. */
+#if !defined(__SALFORDC__) && !defined(__POCC__)
+#define NEED_MALLOC_H 1
+#endif
+
+/* Define if you have the <netdb.h> header file. */
+/* #define HAVE_NETDB_H 1 */
+
+/* Define if you have the <netinet/in.h> header file. */
+/* #define HAVE_NETINET_IN_H 1 */
+
+/* Define if you have the <process.h> header file. */
+#ifndef __SALFORDC__
+#define HAVE_PROCESS_H 1
+#endif
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define if you have the <sgtty.h> header file. */
+/* #define HAVE_SGTTY_H 1 */
+
+/* Define if you have the <ssl.h> header file. */
+/* #define HAVE_SSL_H 1 */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#define HAVE_STDBOOL_H 1
+#endif
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+/* #define HAVE_SYS_PARAM_H 1 */
+
+/* Define if you have the <sys/select.h> header file. */
+/* #define HAVE_SYS_SELECT_H 1 */
+
+/* Define if you have the <sys/socket.h> header file. */
+/* #define HAVE_SYS_SOCKET_H 1 */
+
+/* Define if you have the <sys/sockio.h> header file. */
+/* #define HAVE_SYS_SOCKIO_H 1 */
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/utime.h> header file. */
+#ifndef __BORLANDC__
+#define HAVE_SYS_UTIME_H 1
+#endif
+
+/* Define if you have the <termio.h> header file. */
+/* #define HAVE_TERMIO_H 1 */
+
+/* Define if you have the <termios.h> header file. */
+/* #define HAVE_TERMIOS_H 1 */
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) || \
+ defined(__POCC__)
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define if you have the <windows.h> header file. */
+#define HAVE_WINDOWS_H 1
+
+/* Define if you have the <winsock.h> header file. */
+#define HAVE_WINSOCK_H 1
+
+/* Define if you have the <winsock2.h> header file. */
+#ifndef __SALFORDC__
+#define HAVE_WINSOCK2_H 1
+#endif
+
+/* Define if you have the <ws2tcpip.h> header file. */
+#ifndef __SALFORDC__
+#define HAVE_WS2TCPIP_H 1
+#endif
+
+/* ---------------------------------------------------------------- */
+/* OTHER HEADER INFO */
+/* ---------------------------------------------------------------- */
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* Define to 1 if bool is an available type. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#define HAVE_BOOL_T 1
+#endif
+
+/* ---------------------------------------------------------------- */
+/* FUNCTIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the closesocket function. */
+#define HAVE_CLOSESOCKET 1
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #define HAVE_DOPRNT 1 */
+
+/* Define if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the getpass function. */
+/* #define HAVE_GETPASS 1 */
+
+/* Define if you have the getservbyname function. */
+#define HAVE_GETSERVBYNAME 1
+
+/* Define if you have the getprotobyname function. */
+#define HAVE_GETPROTOBYNAME
+
+/* Define if you have the gettimeofday function. */
+/* #define HAVE_GETTIMEOFDAY 1 */
+
+/* Define if you have the inet_addr function. */
+#define HAVE_INET_ADDR 1
+
+/* Define if you have the ioctlsocket function. */
+#define HAVE_IOCTLSOCKET 1
+
+/* Define if you have a working ioctlsocket FIONBIO function. */
+#define HAVE_IOCTLSOCKET_FIONBIO 1
+
+/* Define if you have the perror function. */
+#define HAVE_PERROR 1
+
+/* Define if you have the RAND_screen function when using SSL. */
+#define HAVE_RAND_SCREEN 1
+
+/* Define if you have the `RAND_status' function when using SSL. */
+#define HAVE_RAND_STATUS 1
+
+/* Define if you have the `CRYPTO_cleanup_all_ex_data' function.
+ This is present in OpenSSL versions after 0.9.6b */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
+/* Define if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setmode function. */
+#define HAVE_SETMODE 1
+
+/* Define if you have the setvbuf function. */
+#define HAVE_SETVBUF 1
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strcasecmp function. */
+/* #define HAVE_STRCASECMP 1 */
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the stricmp function. */
+#define HAVE_STRICMP 1
+
+/* Define if you have the strncasecmp function. */
+/* #define HAVE_STRNCASECMP 1 */
+
+/* Define if you have the strnicmp function. */
+#define HAVE_STRNICMP 1
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtoll function. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__POCC__) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1800))
+#define HAVE_STRTOLL 1
+#endif
+
+/* Define if you have the tcgetattr function. */
+/* #define HAVE_TCGETATTR 1 */
+
+/* Define if you have the tcsetattr function. */
+/* #define HAVE_TCSETATTR 1 */
+
+/* Define if you have the utime function. */
+#ifndef __BORLANDC__
+#define HAVE_UTIME 1
+#endif
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 DWORD
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 SOCKET
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 SOCKET
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 SOCKET
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* ---------------------------------------------------------------- */
+/* TYPEDEF REPLACEMENTS */
+/* ---------------------------------------------------------------- */
+
+/* Define if in_addr_t is not an available 'typedefed' type. */
+#define in_addr_t unsigned long
+
+/* Define to the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define if ssize_t is not an available 'typedefed' type. */
+#ifndef _SSIZE_T_DEFINED
+# if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || \
+ defined(__POCC__) || \
+ defined(__MINGW32__)
+# elif defined(_WIN64)
+# define _SSIZE_T_DEFINED
+# define ssize_t __int64
+# else
+# define _SSIZE_T_DEFINED
+# define ssize_t int
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* TYPE SIZES */
+/* ---------------------------------------------------------------- */
+
+/* Define to the size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* Define to the size of `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 16
+
+/* Define to the size of `long long', as computed by sizeof. */
+/* #define SIZEOF_LONG_LONG 8 */
+
+/* Define to the size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* Define to the size of `size_t', as computed by sizeof. */
+#if defined(_WIN64)
+# define SIZEOF_SIZE_T 8
+#else
+# define SIZEOF_SIZE_T 4
+#endif
+
+/* ---------------------------------------------------------------- */
+/* BSD-style lwIP TCP/IP stack SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Define to use BSD-style lwIP TCP/IP stack. */
+/* #define USE_LWIPSOCK 1 */
+
+#ifdef USE_LWIPSOCK
+# undef USE_WINSOCK
+# undef HAVE_WINSOCK_H
+# undef HAVE_WINSOCK2_H
+# undef HAVE_WS2TCPIP_H
+# undef HAVE_ERRNO_H
+# undef HAVE_GETHOSTNAME
+# undef HAVE_GETNAMEINFO
+# undef LWIP_POSIX_SOCKETS_IO_NAMES
+# undef RECV_TYPE_ARG1
+# undef RECV_TYPE_ARG3
+# undef SEND_TYPE_ARG1
+# undef SEND_TYPE_ARG3
+# define HAVE_FREEADDRINFO
+# define HAVE_GETADDRINFO
+# define HAVE_GETHOSTBYNAME
+# define HAVE_GETHOSTBYNAME_R
+# define HAVE_GETHOSTBYNAME_R_6
+# define LWIP_POSIX_SOCKETS_IO_NAMES 0
+# define RECV_TYPE_ARG1 int
+# define RECV_TYPE_ARG3 size_t
+# define SEND_TYPE_ARG1 int
+# define SEND_TYPE_ARG3 size_t
+#endif
+
+/* ---------------------------------------------------------------- */
+/* Watt-32 tcp/ip SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+#ifdef USE_WATT32
+ #include <tcp.h>
+ #undef byte
+ #undef word
+ #undef USE_WINSOCK
+ #undef HAVE_WINSOCK_H
+ #undef HAVE_WINSOCK2_H
+ #undef HAVE_WS2TCPIP_H
+ #define HAVE_GETADDRINFO
+ #define HAVE_GETNAMEINFO
+ #define HAVE_SYS_IOCTL_H
+ #define HAVE_SYS_SOCKET_H
+ #define HAVE_NETINET_IN_H
+ #define HAVE_NETDB_H
+ #define HAVE_ARPA_INET_H
+ #define HAVE_FREEADDRINFO
+ #define SOCKET int
+#endif
+
+
+/* ---------------------------------------------------------------- */
+/* COMPILER SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Define to nothing if compiler does not support 'const' qualifier. */
+/* #define const */
+
+/* Define to nothing if compiler does not support 'volatile' qualifier. */
+/* #define volatile */
+
+/* Windows should not have HAVE_GMTIME_R defined */
+/* #undef HAVE_GMTIME_R */
+
+/* Define if the compiler supports C99 variadic macro style. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define HAVE_VARIADIC_MACROS_C99 1
+#endif
+
+/* Define if the compiler supports the 'long long' data type. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1310))
+#define HAVE_LONGLONG 1
+#endif
+
+/* Define to avoid VS2005 complaining about portable C functions. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+
+/* VS2005 and later dafault size for time_t is 64-bit, unless
+ _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+# ifndef _USE_32BIT_TIME_T
+# define SIZEOF_TIME_T 8
+# else
+# define SIZEOF_TIME_T 4
+# endif
+#endif
+
+/* Define some minimum and default build targets for Visual Studio */
+#if defined(_MSC_VER)
+ /* Officially, Microsoft's Windows SDK versions 6.X does not support Windows
+ 2000 as a supported build target. VS2008 default installations provides
+ an embedded Windows SDK v6.0A along with the claim that Windows 2000 is a
+ valid build target for VS2008. Popular belief is that binaries built with
+ VS2008 using Windows SDK versions v6.X and Windows 2000 as a build target
+ are functional. */
+# define VS2008_MIN_TARGET 0x0500
+
+ /* The minimum build target for VS2012 is Vista unless Update 1 is installed
+ and the v110_xp toolset is choosen. */
+# if defined(_USING_V110_SDK71_)
+# define VS2012_MIN_TARGET 0x0501
+# else
+# define VS2012_MIN_TARGET 0x0600
+# endif
+
+ /* VS2008 default build target is Windows Vista. We override default target
+ to be Windows XP. */
+# define VS2008_DEF_TARGET 0x0501
+
+ /* VS2012 default build target is Windows Vista unless Update 1 is installed
+ and the v110_xp toolset is choosen. */
+# if defined(_USING_V110_SDK71_)
+# define VS2012_DEF_TARGET 0x0501
+# else
+# define VS2012_DEF_TARGET 0x0600
+# endif
+#endif
+
+/* VS2008 default target settings and minimum build target check. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER <= 1600)
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT VS2008_DEF_TARGET
+# endif
+# ifndef WINVER
+# define WINVER VS2008_DEF_TARGET
+# endif
+# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET)
+# error VS2008 does not support Windows build targets prior to Windows 2000
+# endif
+#endif
+
+/* VS2012 default target settings and minimum build target check. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1700)
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT VS2012_DEF_TARGET
+# endif
+# ifndef WINVER
+# define WINVER VS2012_DEF_TARGET
+# endif
+# if (_WIN32_WINNT < VS2012_MIN_TARGET) || (WINVER < VS2012_MIN_TARGET)
+# if defined(_USING_V110_SDK71_)
+# error VS2012 does not support Windows build targets prior to Windows XP
+# else
+# error VS2012 does not support Windows build targets prior to Windows \
+Vista
+# endif
+# endif
+#endif
+
+/* When no build target is specified Pelles C 5.00 and later default build
+ target is Windows Vista. We override default target to be Windows 2000. */
+#if defined(__POCC__) && (__POCC__ >= 500)
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0500
+# endif
+# ifndef WINVER
+# define WINVER 0x0500
+# endif
+#endif
+
+/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is
+ quite convoluted, compiler dependent and even build target dependent. */
+#if defined(HAVE_WS2TCPIP_H)
+# if defined(__POCC__)
+# define HAVE_FREEADDRINFO 1
+# define HAVE_GETADDRINFO 1
+# define HAVE_GETADDRINFO_THREADSAFE 1
+# define HAVE_GETNAMEINFO 1
+# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
+# define HAVE_FREEADDRINFO 1
+# define HAVE_GETADDRINFO 1
+# define HAVE_GETADDRINFO_THREADSAFE 1
+# define HAVE_GETNAMEINFO 1
+# elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+# define HAVE_FREEADDRINFO 1
+# define HAVE_GETADDRINFO 1
+# define HAVE_GETADDRINFO_THREADSAFE 1
+# define HAVE_GETNAMEINFO 1
+# endif
+#endif
+
+#if defined(__POCC__)
+# ifndef _MSC_VER
+# error Microsoft extensions /Ze compiler option is required
+# endif
+# ifndef __POCC__OLDNAMES
+# error Compatibility names /Go compiler option is required
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* STRUCT RELATED */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have struct sockaddr_storage. */
+#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+#endif
+
+/* Define if you have struct timeval. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+#if HAVE_WINSOCK2_H && defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+#define HAVE_STRUCT_POLLFD 1
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LARGE FILE SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define USE_WIN32_LARGE_FILES
+# else
+# define USE_WIN32_SMALL_FILES
+# endif
+#endif
+
+#if defined(__MINGW32__) && !defined(USE_WIN32_LARGE_FILES)
+# define USE_WIN32_LARGE_FILES
+#endif
+
+#if defined(__WATCOMC__) && !defined(USE_WIN32_LARGE_FILES)
+# define USE_WIN32_LARGE_FILES
+#endif
+
+#if defined(__POCC__)
+# undef USE_WIN32_LARGE_FILES
+#endif
+
+#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
+# define USE_WIN32_SMALL_FILES
+#endif
+
+/* ---------------------------------------------------------------- */
+/* DNS RESOLVER SPECIALTY */
+/* ---------------------------------------------------------------- */
+
+/*
+ * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS.
+ */
+
+/* Define to enable c-ares asynchronous DNS lookups. */
+/* #define USE_ARES 1 */
+
+/* Default define to enable threaded asynchronous DNS lookups. */
+#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \
+ !defined(USE_THREADS_WIN32)
+# define USE_THREADS_WIN32 1
+#endif
+
+#if defined(USE_ARES) && defined(USE_THREADS_WIN32)
+# error "Only one DNS lookup specialty may be defined at most"
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LDAP SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK)
+#undef USE_WIN32_LDAP
+#define HAVE_LDAP_SSL_H 1
+#define HAVE_LDAP_URL_PARSE 1
+#elif defined(CURL_HAS_OPENLDAP_LDAPSDK)
+#undef USE_WIN32_LDAP
+#define HAVE_LDAP_URL_PARSE 1
+#else
+#undef HAVE_LDAP_URL_PARSE
+#define USE_WIN32_LDAP 1
+#endif
+
+#if defined(__WATCOMC__) && defined(USE_WIN32_LDAP)
+#if __WATCOMC__ < 1280
+#define WINBERAPI __declspec(cdecl)
+#define WINLDAPAPI __declspec(cdecl)
+#endif
+#endif
+
+#if defined(__POCC__) && defined(USE_WIN32_LDAP)
+# define CURL_DISABLE_LDAP 1
+#endif
+
+/* Define to use the Windows crypto library. */
+#if !defined(USE_OPENSSL) && !defined(USE_NSS)
+#define USE_WIN32_CRYPTO
+#endif
+
+/* ---------------------------------------------------------------- */
+/* ADDITIONAL DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define cpu-machine-OS */
+#undef OS
+#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */
+#define OS "i386-pc-win32"
+#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */
+#define OS "x86_64-pc-win32"
+#elif defined(_M_IA64) /* Itanium */
+#define OS "ia64-pc-win32"
+#else
+#define OS "unknown-pc-win32"
+#endif
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+#if defined(__POCC__) || (USE_IPV6)
+# define ENABLE_IPV6 1
+#endif
+
+#endif /* HEADER_CURL_CONFIG_WIN32_H */
diff --git a/libcurl/src/lib/config-win32ce.h b/libcurl/src/lib/config-win32ce.h
new file mode 100644
index 0000000..a723fd1
--- /dev/null
+++ b/libcurl/src/lib/config-win32ce.h
@@ -0,0 +1,448 @@
+#ifndef HEADER_CURL_CONFIG_WIN32CE_H
+#define HEADER_CURL_CONFIG_WIN32CE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* lib/config-win32ce.h - Hand crafted config file for windows ce */
+/* ================================================================ */
+
+/* ---------------------------------------------------------------- */
+/* HEADER FILES */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the <arpa/inet.h> header file. */
+/* #define HAVE_ARPA_INET_H 1 */
+
+/* Define if you have the <assert.h> header file. */
+/* #define HAVE_ASSERT_H 1 */
+
+/* Define if you have the <crypto.h> header file. */
+/* #define HAVE_CRYPTO_H 1 */
+
+/* Define if you have the <errno.h> header file. */
+/* #define HAVE_ERRNO_H 1 */
+
+/* Define if you have the <err.h> header file. */
+/* #define HAVE_ERR_H 1 */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <getopt.h> header file. */
+/* #define HAVE_GETOPT_H 1 */
+
+/* Define if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you need the malloc.h header header file even with stdlib.h */
+#define NEED_MALLOC_H 1
+
+/* Define if you have the <netdb.h> header file. */
+/* #define HAVE_NETDB_H 1 */
+
+/* Define if you have the <netinet/in.h> header file. */
+/* #define HAVE_NETINET_IN_H 1 */
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define if you have the <sgtty.h> header file. */
+/* #define HAVE_SGTTY_H 1 */
+
+/* Define if you have the <ssl.h> header file. */
+/* #define HAVE_SSL_H 1 */
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <process.h> header file. */
+/* #define HAVE_PROCESS_H 1 */
+
+/* Define if you have the <sys/param.h> header file. */
+/* #define HAVE_SYS_PARAM_H 1 */
+
+/* Define if you have the <sys/select.h> header file. */
+/* #define HAVE_SYS_SELECT_H 1 */
+
+/* Define if you have the <sys/socket.h> header file. */
+/* #define HAVE_SYS_SOCKET_H 1 */
+
+/* Define if you have the <sys/sockio.h> header file. */
+/* #define HAVE_SYS_SOCKIO_H 1 */
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <sys/types.h> header file. */
+/* #define HAVE_SYS_TYPES_H 1 */
+
+/* Define if you have the <sys/utime.h> header file */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define if you have the <termio.h> header file. */
+/* #define HAVE_TERMIO_H 1 */
+
+/* Define if you have the <termios.h> header file. */
+/* #define HAVE_TERMIOS_H 1 */
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__)
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define if you have the <windows.h> header file. */
+#define HAVE_WINDOWS_H 1
+
+/* Define if you have the <winsock.h> header file. */
+#define HAVE_WINSOCK_H 1
+
+/* Define if you have the <winsock2.h> header file. */
+/* #define HAVE_WINSOCK2_H 1 */
+
+/* Define if you have the <ws2tcpip.h> header file. */
+/* #define HAVE_WS2TCPIP_H 1 */
+
+/* ---------------------------------------------------------------- */
+/* OTHER HEADER INFO */
+/* ---------------------------------------------------------------- */
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* ---------------------------------------------------------------- */
+/* FUNCTIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the closesocket function. */
+#define HAVE_CLOSESOCKET 1
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #define HAVE_DOPRNT 1 */
+
+/* Define if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the getpass function. */
+/* #define HAVE_GETPASS 1 */
+
+/* Define if you have the getservbyname function. */
+#define HAVE_GETSERVBYNAME 1
+
+/* Define if you have the gettimeofday function. */
+/* #define HAVE_GETTIMEOFDAY 1 */
+
+/* Define if you have the inet_addr function. */
+#define HAVE_INET_ADDR 1
+
+/* Define if you have the ioctlsocket function. */
+#define HAVE_IOCTLSOCKET 1
+
+/* Define if you have a working ioctlsocket FIONBIO function. */
+#define HAVE_IOCTLSOCKET_FIONBIO 1
+
+/* Define if you have the perror function. */
+#define HAVE_PERROR 1
+
+/* Define if you have the RAND_screen function when using SSL */
+#define HAVE_RAND_SCREEN 1
+
+/* Define if you have the `RAND_status' function when using SSL. */
+#define HAVE_RAND_STATUS 1
+
+/* Define if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the setvbuf function. */
+#define HAVE_SETVBUF 1
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strcasecmp function. */
+/* #define HAVE_STRCASECMP 1 */
+
+/* Define if you have the strdup function. */
+/* #define HAVE_STRDUP 1 */
+
+/* Define if you have the strftime function. */
+/* #define HAVE_STRFTIME 1 */
+
+/* Define if you have the stricmp function. */
+/* #define HAVE_STRICMP 1 */
+
+/* Define if you have the strncasecmp function. */
+/* #define HAVE_STRNCASECMP 1 */
+
+/* Define if you have the strnicmp function. */
+/* #define HAVE_STRNICMP 1 */
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtoll function. */
+#if defined(__MINGW32__) || defined(__WATCOMC__)
+#define HAVE_STRTOLL 1
+#endif
+
+/* Define if you have the tcgetattr function. */
+/* #define HAVE_TCGETATTR 1 */
+
+/* Define if you have the tcsetattr function. */
+/* #define HAVE_TCSETATTR 1 */
+
+/* Define if you have the utime function */
+#define HAVE_UTIME 1
+
+/* Define if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 DWORD
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 SOCKET
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 SOCKET
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 SOCKET
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* ---------------------------------------------------------------- */
+/* TYPEDEF REPLACEMENTS */
+/* ---------------------------------------------------------------- */
+
+/* Define this if in_addr_t is not an available 'typedefed' type */
+#define in_addr_t unsigned long
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define ssize_t if it is not an available 'typedefed' type */
+#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__)
+#elif defined(_WIN64)
+#define ssize_t __int64
+#else
+#define ssize_t int
+#endif
+
+/* ---------------------------------------------------------------- */
+/* TYPE SIZES */
+/* ---------------------------------------------------------------- */
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 16
+
+/* The size of `long long', as computed by sizeof. */
+/* #define SIZEOF_LONG_LONG 8 */
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#if defined(_WIN64)
+# define SIZEOF_SIZE_T 8
+#else
+# define SIZEOF_SIZE_T 4
+#endif
+
+/* ---------------------------------------------------------------- */
+/* STRUCT RELATED */
+/* ---------------------------------------------------------------- */
+
+/* Define this if you have struct sockaddr_storage */
+/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */
+
+/* Define this if you have struct timeval */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define this if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* ---------------------------------------------------------------- */
+/* COMPILER SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Undef keyword 'const' if it does not work. */
+/* #undef const */
+
+/* Define to avoid VS2005 complaining about portable C functions */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+
+/* VS2005 and later dafault size for time_t is 64-bit, unless */
+/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+# ifndef _USE_32BIT_TIME_T
+# define SIZEOF_TIME_T 8
+# else
+# define SIZEOF_TIME_T 4
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LARGE FILE SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define USE_WIN32_LARGE_FILES
+# else
+# define USE_WIN32_SMALL_FILES
+# endif
+#endif
+
+#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
+# define USE_WIN32_SMALL_FILES
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LDAP SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#define USE_WIN32_LDAP 1
+#undef HAVE_LDAP_URL_PARSE
+
+/* ---------------------------------------------------------------- */
+/* ADDITIONAL DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define cpu-machine-OS */
+#undef OS
+#define OS "i386-pc-win32ce"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* ---------------------------------------------------------------- */
+/* WinCE */
+/* ---------------------------------------------------------------- */
+
+#ifndef UNICODE
+# define UNICODE
+#endif
+
+#ifndef _UNICODE
+# define _UNICODE
+#endif
+
+#define CURL_DISABLE_FILE 1
+#define CURL_DISABLE_TELNET 1
+#define CURL_DISABLE_LDAP 1
+
+#define ENOSPC 1
+#define ENOMEM 2
+#define EAGAIN 3
+
+extern int stat(const char *path, struct stat *buffer);
+
+#endif /* HEADER_CURL_CONFIG_WIN32CE_H */
diff --git a/libcurl/src/lib/config-winrt.h b/libcurl/src/lib/config-winrt.h
new file mode 100644
index 0000000..8694d3d
--- /dev/null
+++ b/libcurl/src/lib/config-winrt.h
@@ -0,0 +1,468 @@
+#ifndef HEADER_CURL_CONFIG_WIN32CE_H
+#define HEADER_CURL_CONFIG_WIN32CE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* lib/config-win32ce.h - Hand crafted config file for windows ce */
+/* ================================================================ */
+
+/* ---------------------------------------------------------------- */
+/* HEADER FILES */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the <arpa/inet.h> header file. */
+/* #define HAVE_ARPA_INET_H 1 */
+
+/* Define if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define if you have the <crypto.h> header file. */
+/* #define HAVE_CRYPTO_H 1 */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <err.h> header file. */
+/* #define HAVE_ERR_H 1 */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <getopt.h> header file. */
+/* #define HAVE_GETOPT_H 1 */
+
+/* Define if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you need the malloc.h header header file even with stdlib.h */
+#define NEED_MALLOC_H 1
+
+/* Define if you have the <netdb.h> header file. */
+/* #define HAVE_NETDB_H 1 */
+
+/* Define if you have the <netinet/in.h> header file. */
+/* #define HAVE_NETINET_IN_H 1 */
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define if you have the <sgtty.h> header file. */
+/* #define HAVE_SGTTY_H 1 */
+
+/* Define if you have the <ssl.h> header file. */
+/* #define HAVE_SSL_H 1 */
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <process.h> header file. */
+/* #define HAVE_PROCESS_H 1 */
+
+/* Define if you have the <sys/param.h> header file. */
+/* #define HAVE_SYS_PARAM_H 1 */
+
+/* Define if you have the <sys/select.h> header file. */
+/* #define HAVE_SYS_SELECT_H 1 */
+
+/* Define if you have the <sys/socket.h> header file. */
+/* #define HAVE_SYS_SOCKET_H 1 */
+
+/* Define if you have the <sys/sockio.h> header file. */
+/* #define HAVE_SYS_SOCKIO_H 1 */
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <sys/types.h> header file. */
+/* #define HAVE_SYS_TYPES_H 1 */
+
+/* Define if you have the <sys/utime.h> header file */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define if you have the <termio.h> header file. */
+/* #define HAVE_TERMIO_H 1 */
+
+/* Define if you have the <termios.h> header file. */
+/* #define HAVE_TERMIOS_H 1 */
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__)
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define if you have the <windows.h> header file. */
+#define HAVE_WINDOWS_H 1
+
+/* Define if you have the <winsock.h> header file. */
+/* #define HAVE_WINSOCK_H 1 */
+
+/* Define if you have the <winsock2.h> header file. */
+#define HAVE_WINSOCK2_H 1
+
+/* Define if you have the <ws2tcpip.h> header file. */
+#define HAVE_WS2TCPIP_H 1
+
+/* ---------------------------------------------------------------- */
+/* OTHER HEADER INFO */
+/* ---------------------------------------------------------------- */
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* ---------------------------------------------------------------- */
+/* FUNCTIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the closesocket function. */
+#define HAVE_CLOSESOCKET 1
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #define HAVE_DOPRNT 1 */
+
+/* Define if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the getpass function. */
+/* #define HAVE_GETPASS 1 */
+
+/* Define if you have the getservbyname function. */
+#define HAVE_GETSERVBYNAME 1
+
+/* Define if you have the gettimeofday function. */
+/* #define HAVE_GETTIMEOFDAY 1 */
+
+/* Define if you have the inet_addr function. */
+#define HAVE_INET_ADDR 1
+
+/* Define if you have the ioctlsocket function. */
+#define HAVE_IOCTLSOCKET 1
+
+/* Define if you have a working ioctlsocket FIONBIO function. */
+#define HAVE_IOCTLSOCKET_FIONBIO 1
+
+/* Define if you have the perror function. */
+#define HAVE_PERROR 1
+
+/* Define if you have the RAND_screen function when using SSL */
+#define HAVE_RAND_SCREEN 1
+
+/* Define if you have the `RAND_status' function when using SSL. */
+#define HAVE_RAND_STATUS 1
+
+/* Define if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the setvbuf function. */
+#define HAVE_SETVBUF 1
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strcasecmp function. */
+/* #define HAVE_STRCASECMP 1 */
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strftime function. */
+/* #define HAVE_STRFTIME 1 */
+
+/* Define if you have the stricmp function. */
+/* #define HAVE_STRICMP 1 */
+
+/* Define if you have the strncasecmp function. */
+/* #define HAVE_STRNCASECMP 1 */
+
+/* Define if you have the strnicmp function. */
+/* #define HAVE_STRNICMP 1 */
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtoll function. */
+#if defined(__MINGW32__) || defined(__WATCOMC__)
+#define HAVE_STRTOLL 1
+#endif
+
+/* Define if you have the tcgetattr function. */
+/* #define HAVE_TCGETATTR 1 */
+
+/* Define if you have the tcsetattr function. */
+/* #define HAVE_TCSETATTR 1 */
+
+/* Define if you have the utime function */
+#define HAVE_UTIME 1
+
+/* Define if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 DWORD
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 SOCKET
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 SOCKET
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 SOCKET
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* ---------------------------------------------------------------- */
+/* TYPEDEF REPLACEMENTS */
+/* ---------------------------------------------------------------- */
+
+/* Define this if in_addr_t is not an available 'typedefed' type */
+#define in_addr_t unsigned long
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define ssize_t if it is not an available 'typedefed' type */
+#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__)
+#elif defined(_WIN64)
+#define ssize_t __int64
+#else
+#define ssize_t int
+#endif
+
+/* ---------------------------------------------------------------- */
+/* TYPE SIZES */
+/* ---------------------------------------------------------------- */
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 16
+
+/* The size of `long long', as computed by sizeof. */
+/* #define SIZEOF_LONG_LONG 8 */
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#if defined(_WIN64)
+# define SIZEOF_SIZE_T 8
+#else
+# define SIZEOF_SIZE_T 4
+#endif
+
+/* ---------------------------------------------------------------- */
+/* STRUCT RELATED */
+/* ---------------------------------------------------------------- */
+
+/* Define this if you have struct sockaddr_storage */
+/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */
+
+/* Define this if you have struct timeval */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define this if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+#define HAVE_STRUCT_POLLFD 1
+
+/* ---------------------------------------------------------------- */
+/* COMPILER SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Undef keyword 'const' if it does not work. */
+/* #undef const */
+
+/* Define to avoid VS2005 complaining about portable C functions */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+
+/* VS2005 and later dafault size for time_t is 64-bit, unless */
+/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+# ifndef _USE_32BIT_TIME_T
+# define SIZEOF_TIME_T 8
+# else
+# define SIZEOF_TIME_T 4
+# endif
+#endif
+
+# define HAVE_FREEADDRINFO 1
+# define HAVE_GETADDRINFO 1
+# define HAVE_GETADDRINFO_THREADSAFE 1
+# define HAVE_GETNAMEINFO 1
+
+/* ---------------------------------------------------------------- */
+/* LARGE FILE SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define USE_WIN32_LARGE_FILES
+# else
+# define USE_WIN32_SMALL_FILES
+# endif
+#endif
+
+#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
+# define USE_WIN32_SMALL_FILES
+#endif
+
+/* ---------------------------------------------------------------- */
+/* DNS RESOLVER SPECIALTY */
+/* ---------------------------------------------------------------- */
+
+/*
+ * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS.
+ */
+
+/* Define to enable c-ares asynchronous DNS lookups. */
+/* #define USE_ARES 1 */
+
+/* Default define to enable threaded asynchronous DNS lookups. */
+#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \
+ !defined(USE_THREADS_WIN32)
+//# define USE_THREADS_WIN32 1
+#endif
+
+#if defined(USE_ARES) && defined(USE_THREADS_WIN32)
+# error "Only one DNS lookup specialty may be defined at most"
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LDAP SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#define CURL_LDAP_WIN 1
+#undef HAVE_LDAP_URL_PARSE
+
+/* ---------------------------------------------------------------- */
+/* ADDITIONAL DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define cpu-machine-OS */
+#undef OS
+#define OS "unknown-pc-winrt"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* ---------------------------------------------------------------- */
+/* WinRT */
+/* ---------------------------------------------------------------- */
+
+#ifndef UNICODE
+# define UNICODE
+#endif
+
+#ifndef _UNICODE
+# define _UNICODE
+#endif
+
+extern int stat(const char *path,struct stat *buffer );
+
+#endif /* HEADER_CURL_CONFIG_WIN32CE_H */
diff --git a/libcurl/src/lib/conncache.c b/libcurl/src/lib/conncache.c
new file mode 100644
index 0000000..e536782
--- /dev/null
+++ b/libcurl/src/lib/conncache.c
@@ -0,0 +1,289 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "multiif.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "bundles.h"
+#include "conncache.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void free_bundle_hash_entry(void *freethis)
+{
+ struct connectbundle *b = (struct connectbundle *) freethis;
+
+ Curl_bundle_destroy(b);
+}
+
+CURL_STATIC struct conncache *Curl_conncache_init(int size)
+{
+ struct conncache *connc;
+
+ connc = calloc(1, sizeof(struct conncache));
+ if(!connc)
+ return NULL;
+
+ connc->hash = Curl_hash_alloc(size, Curl_hash_str,
+ Curl_str_key_compare, free_bundle_hash_entry);
+
+ if(!connc->hash) {
+ free(connc);
+ return NULL;
+ }
+
+ return connc;
+}
+
+CURL_STATIC void Curl_conncache_destroy(struct conncache *connc)
+{
+ if(connc) {
+ Curl_hash_destroy(connc->hash);
+ connc->hash = NULL;
+ free(connc);
+ }
+}
+
+CURL_STATIC struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
+ struct conncache *connc)
+{
+ struct connectbundle *bundle = NULL;
+
+ char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name;
+
+ if(connc)
+ bundle = Curl_hash_pick(connc->hash, hostname, strlen(hostname)+1);
+
+ return bundle;
+}
+
+static bool conncache_add_bundle(struct conncache *connc,
+ char *hostname,
+ struct connectbundle *bundle)
+{
+ void *p;
+
+ p = Curl_hash_add(connc->hash, hostname, strlen(hostname)+1, bundle);
+
+ return p?TRUE:FALSE;
+}
+
+static void conncache_remove_bundle(struct conncache *connc,
+ struct connectbundle *bundle)
+{
+ struct curl_hash_iterator iter;
+ struct curl_hash_element *he;
+
+ if(!connc)
+ return;
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ if(he->ptr == bundle) {
+ /* The bundle is destroyed by the hash destructor function,
+ free_bundle_hash_entry() */
+ Curl_hash_delete(connc->hash, he->key, he->key_len);
+ return;
+ }
+
+ he = Curl_hash_next_element(&iter);
+ }
+}
+
+CURL_STATIC CURLcode Curl_conncache_add_conn(struct conncache *connc,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ struct connectbundle *bundle;
+ struct connectbundle *new_bundle = NULL;
+ struct SessionHandle *data = conn->data;
+
+ bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
+ if(!bundle) {
+ char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name;
+
+ result = Curl_bundle_create(data, &new_bundle);
+ if(result)
+ return result;
+
+ if(!conncache_add_bundle(data->state.conn_cache, hostname, new_bundle)) {
+ Curl_bundle_destroy(new_bundle);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ bundle = new_bundle;
+ }
+
+ result = Curl_bundle_add_conn(bundle, conn);
+ if(result) {
+ if(new_bundle)
+ conncache_remove_bundle(data->state.conn_cache, new_bundle);
+ return result;
+ }
+
+ conn->connection_id = connc->next_connection_id++;
+ connc->num_connections++;
+
+ DEBUGF(infof(conn->data, "Added connection %ld. "
+ "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n",
+ conn->connection_id, (curl_off_t) connc->num_connections));
+
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_conncache_remove_conn(struct conncache *connc,
+ struct connectdata *conn)
+{
+ struct connectbundle *bundle = conn->bundle;
+
+ /* The bundle pointer can be NULL, since this function can be called
+ due to a failed connection attempt, before being added to a bundle */
+ if(bundle) {
+ Curl_bundle_remove_conn(bundle, conn);
+ if(bundle->num_connections == 0) {
+ conncache_remove_bundle(connc, bundle);
+ }
+
+ if(connc) {
+ connc->num_connections--;
+
+ DEBUGF(infof(conn->data, "The cache now contains %"
+ CURL_FORMAT_CURL_OFF_TU " members\n",
+ (curl_off_t) connc->num_connections));
+ }
+ }
+}
+
+/* This function iterates the entire connection cache and calls the
+ function func() with the connection pointer as the first argument
+ and the supplied 'param' argument as the other,
+
+ Return 0 from func() to continue the loop, return 1 to abort it.
+ */
+CURL_STATIC void Curl_conncache_foreach(struct conncache *connc,
+ void *param,
+ int (*func)(struct connectdata *conn, void *param))
+{
+ struct curl_hash_iterator iter;
+ struct curl_llist_element *curr;
+ struct curl_hash_element *he;
+
+ if(!connc)
+ return;
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct connectbundle *bundle;
+
+ bundle = he->ptr;
+ he = Curl_hash_next_element(&iter);
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ /* Yes, we need to update curr before calling func(), because func()
+ might decide to remove the connection */
+ struct connectdata *conn = curr->ptr;
+ curr = curr->next;
+
+ if(1 == func(conn, param))
+ return;
+ }
+ }
+}
+
+/* Return the first connection found in the cache. Used when closing all
+ connections */
+CURL_STATIC struct connectdata *
+Curl_conncache_find_first_connection(struct conncache *connc)
+{
+ struct curl_hash_iterator iter;
+ struct curl_hash_element *he;
+ struct connectbundle *bundle;
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct curl_llist_element *curr;
+ bundle = he->ptr;
+
+ curr = bundle->conn_list->head;
+ if(curr) {
+ return curr->ptr;
+ }
+
+ he = Curl_hash_next_element(&iter);
+ }
+
+ return NULL;
+}
+
+
+#if 0
+/* Useful for debugging the connection cache */
+CURL_STATIC void Curl_conncache_print(struct conncache *connc)
+{
+ struct curl_hash_iterator iter;
+ struct curl_llist_element *curr;
+ struct curl_hash_element *he;
+
+ if(!connc)
+ return;
+
+ fprintf(stderr, "=Bundle cache=\n");
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct connectbundle *bundle;
+ struct connectdata *conn;
+
+ bundle = he->ptr;
+
+ fprintf(stderr, "%s -", he->key);
+ curr = bundle->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+
+ fprintf(stderr, " [%p %d]", (void *)conn, conn->inuse);
+ curr = curr->next;
+ }
+ fprintf(stderr, "\n");
+
+ he = Curl_hash_next_element(&iter);
+ }
+}
+#endif
diff --git a/libcurl/src/lib/conncache.h b/libcurl/src/lib/conncache.h
new file mode 100644
index 0000000..2ccdd00
--- /dev/null
+++ b/libcurl/src/lib/conncache.h
@@ -0,0 +1,57 @@
+#ifndef HEADER_CURL_CONNCACHE_H
+#define HEADER_CURL_CONNCACHE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct conncache {
+ struct curl_hash *hash;
+ size_t num_connections;
+ long next_connection_id;
+ struct timeval last_cleanup;
+};
+
+CURL_STATIC struct conncache *Curl_conncache_init(int size);
+
+CURL_STATIC void Curl_conncache_destroy(struct conncache *connc);
+
+/* return the correct bundle, to a host or a proxy */
+CURL_STATIC struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
+ struct conncache *connc);
+
+CURL_STATIC CURLcode Curl_conncache_add_conn(struct conncache *connc,
+ struct connectdata *conn);
+
+CURL_STATIC void Curl_conncache_remove_conn(struct conncache *connc,
+ struct connectdata *conn);
+
+CURL_STATIC void Curl_conncache_foreach(struct conncache *connc,
+ void *param,
+ int (*func)(struct connectdata *conn,
+ void *param));
+
+CURL_STATIC struct connectdata *
+Curl_conncache_find_first_connection(struct conncache *connc);
+
+CURL_STATIC void Curl_conncache_print(struct conncache *connc);
+
+#endif /* HEADER_CURL_CONNCACHE_H */
diff --git a/libcurl/src/lib/connect.c b/libcurl/src/lib/connect.c
new file mode 100644
index 0000000..eaaac4e
--- /dev/null
+++ b/libcurl/src/lib/connect.c
@@ -0,0 +1,1377 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h> /* <netinet/tcp.h> may need it */
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h> /* for sockaddr_un */
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h> /* for TCP_NODELAY */
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
+#include <sys/filio.h>
+#endif
+#ifdef NETWARE
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#include "curl_printf.h"
+#include "urldata.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "strerror.h"
+#include "connect.h"
+#include "select.h"
+#include "url.h" /* for Curl_safefree() */
+#include "multiif.h"
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "inet_ntop.h"
+#include "inet_pton.h"
+#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
+#include "progress.h"
+#include "warnless.h"
+#include "conncache.h"
+#include "multihandle.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef __SYMBIAN32__
+/* This isn't actually supported under Symbian OS */
+#undef SO_NOSIGPIPE
+#endif
+
+static bool verifyconnect(curl_socket_t sockfd, int *error);
+
+#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
+/* DragonFlyBSD and Windows use millisecond units */
+#define KEEPALIVE_FACTOR(x) (x *= 1000)
+#else
+#define KEEPALIVE_FACTOR(x)
+#endif
+
+#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
+#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
+
+struct tcp_keepalive {
+ u_long onoff;
+ u_long keepalivetime;
+ u_long keepaliveinterval;
+};
+#endif
+
+static void
+tcpkeepalive(struct SessionHandle *data,
+ curl_socket_t sockfd)
+{
+ int optval = data->set.tcp_keepalive?1:0;
+
+ /* only set IDLE and INTVL if setting KEEPALIVE is successful */
+ if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
+ }
+ else {
+#if defined(SIO_KEEPALIVE_VALS)
+ struct tcp_keepalive vals;
+ DWORD dummy;
+ vals.onoff = 1;
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ vals.keepalivetime = optval;
+ optval = curlx_sltosi(data->set.tcp_keepintvl);
+ KEEPALIVE_FACTOR(optval);
+ vals.keepaliveinterval = optval;
+ if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
+ NULL, 0, &dummy, NULL, NULL) != 0) {
+ infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
+ (int)sockfd, WSAGetLastError());
+ }
+#else
+#ifdef TCP_KEEPIDLE
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
+ }
+#endif
+#ifdef TCP_KEEPINTVL
+ optval = curlx_sltosi(data->set.tcp_keepintvl);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
+ }
+#endif
+#ifdef TCP_KEEPALIVE
+ /* Mac OS X style */
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
+ }
+#endif
+#endif
+ }
+}
+
+static CURLcode
+singleipconnect(struct connectdata *conn,
+ const Curl_addrinfo *ai, /* start connecting to this */
+ curl_socket_t *sock);
+
+/*
+ * Curl_timeleft() returns the amount of milliseconds left allowed for the
+ * transfer/connection. If the value is negative, the timeout time has already
+ * elapsed.
+ *
+ * The start time is stored in progress.t_startsingle - as set with
+ * Curl_pgrsTime(..., TIMER_STARTSINGLE);
+ *
+ * If 'nowp' is non-NULL, it points to the current time.
+ * 'duringconnect' is FALSE if not during a connect, as then of course the
+ * connect timeout is not taken into account!
+ *
+ * @unittest: 1303
+ */
+CURL_STATIC long Curl_timeleft(struct SessionHandle *data,
+ struct timeval *nowp,
+ bool duringconnect)
+{
+ int timeout_set = 0;
+ long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
+ struct timeval now;
+
+ /* if a timeout is set, use the most restrictive one */
+
+ if(data->set.timeout > 0)
+ timeout_set |= 1;
+ if(duringconnect && (data->set.connecttimeout > 0))
+ timeout_set |= 2;
+
+ switch (timeout_set) {
+ case 1:
+ timeout_ms = data->set.timeout;
+ break;
+ case 2:
+ timeout_ms = data->set.connecttimeout;
+ break;
+ case 3:
+ if(data->set.timeout < data->set.connecttimeout)
+ timeout_ms = data->set.timeout;
+ else
+ timeout_ms = data->set.connecttimeout;
+ break;
+ default:
+ /* use the default */
+ if(!duringconnect)
+ /* if we're not during connect, there's no default timeout so if we're
+ at zero we better just return zero and not make it a negative number
+ by the math below */
+ return 0;
+ break;
+ }
+
+ if(!nowp) {
+ now = Curl_tvnow();
+ nowp = &now;
+ }
+
+ /* subtract elapsed time */
+ if(duringconnect)
+ /* since this most recent connect started */
+ timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
+ else
+ /* since the entire operation started */
+ timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
+ if(!timeout_ms)
+ /* avoid returning 0 as that means no timeout! */
+ return -1;
+
+ return timeout_ms;
+}
+
+static CURLcode bindlocal(struct connectdata *conn,
+ curl_socket_t sockfd, int af, unsigned int scope)
+{
+ struct SessionHandle *data = conn->data;
+
+ struct Curl_sockaddr_storage sa;
+ struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
+ curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
+ struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
+#endif
+
+ struct Curl_dns_entry *h=NULL;
+ unsigned short port = data->set.localport; /* use this port number, 0 for
+ "random" */
+ /* how many port numbers to try to bind to, increasing one at a time */
+ int portnum = data->set.localportrange;
+ const char *dev = data->set.str[STRING_DEVICE];
+ int error;
+
+ /*************************************************************
+ * Select device to bind socket to
+ *************************************************************/
+ if(!dev && !port)
+ /* no local kind of binding was requested */
+ return CURLE_OK;
+
+ memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
+
+ if(dev && (strlen(dev)<255) ) {
+ char myhost[256] = "";
+ int done = 0; /* -1 for error, 1 for address found */
+ bool is_interface = FALSE;
+ bool is_host = FALSE;
+ static const char *if_prefix = "if!";
+ static const char *host_prefix = "host!";
+
+ if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
+ dev += strlen(if_prefix);
+ is_interface = TRUE;
+ }
+ else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
+ dev += strlen(host_prefix);
+ is_host = TRUE;
+ }
+
+ /* interface */
+ if(!is_host) {
+ switch(Curl_if2ip(af, scope, conn->scope_id, dev,
+ myhost, sizeof(myhost))) {
+ case IF2IP_NOT_FOUND:
+ if(is_interface) {
+ /* Do not fall back to treating it as a host name */
+ failf(data, "Couldn't bind to interface '%s'", dev);
+ return CURLE_INTERFACE_FAILED;
+ }
+ break;
+ case IF2IP_AF_NOT_SUPPORTED:
+ /* Signal the caller to try another address family if available */
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ case IF2IP_FOUND:
+ is_interface = TRUE;
+ /*
+ * We now have the numerical IP address in the 'myhost' buffer
+ */
+ infof(data, "Local Interface %s is ip %s using address family %i\n",
+ dev, myhost, af);
+ done = 1;
+
+#ifdef SO_BINDTODEVICE
+ /* I am not sure any other OSs than Linux that provide this feature,
+ * and at the least I cannot test. --Ben
+ *
+ * This feature allows one to tightly bind the local socket to a
+ * particular interface. This will force even requests to other
+ * local interfaces to go out the external interface.
+ *
+ *
+ * Only bind to the interface when specified as interface, not just
+ * as a hostname or ip address.
+ */
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+ dev, (curl_socklen_t)strlen(dev)+1) != 0) {
+ error = SOCKERRNO;
+ infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
+ " will do regular bind\n",
+ dev, error, Curl_strerror(conn, error));
+ /* This is typically "errno 1, error: Operation not permitted" if
+ you're not running as root or another suitable privileged
+ user */
+ }
+#endif
+ break;
+ }
+ }
+ if(!is_interface) {
+ /*
+ * This was not an interface, resolve the name as a host name
+ * or IP number
+ *
+ * Temporarily force name resolution to use only the address type
+ * of the connection. The resolve functions should really be changed
+ * to take a type parameter instead.
+ */
+ long ipver = conn->ip_version;
+ int rc;
+
+ if(af == AF_INET)
+ conn->ip_version = CURL_IPRESOLVE_V4;
+#ifdef ENABLE_IPV6
+ else if(af == AF_INET6)
+ conn->ip_version = CURL_IPRESOLVE_V6;
+#endif
+
+ rc = Curl_resolv(conn, dev, 0, &h);
+ if(rc == CURLRESOLV_PENDING)
+ (void)Curl_resolver_wait_resolv(conn, &h);
+ conn->ip_version = ipver;
+
+ if(h) {
+ /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
+ Curl_printable_address(h->addr, myhost, sizeof(myhost));
+ infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
+ dev, af, myhost, h->addr->ai_family);
+ Curl_resolv_unlock(data, h);
+ done = 1;
+ }
+ else {
+ /*
+ * provided dev was no interface (or interfaces are not supported
+ * e.g. solaris) no ip address and no domain we fail here
+ */
+ done = -1;
+ }
+ }
+
+ if(done > 0) {
+#ifdef ENABLE_IPV6
+ /* IPv6 address */
+ if(af == AF_INET6) {
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ char *scope_ptr = strchr(myhost, '%');
+ if(scope_ptr)
+ *(scope_ptr++) = 0;
+#endif
+ if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
+ si6->sin6_family = AF_INET6;
+ si6->sin6_port = htons(port);
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ if(scope_ptr)
+ /* The "myhost" string either comes from Curl_if2ip or from
+ Curl_printable_address. The latter returns only numeric scope
+ IDs and the former returns none at all. So the scope ID, if
+ present, is known to be numeric */
+ si6->sin6_scope_id = atoi(scope_ptr);
+#endif
+ }
+ sizeof_sa = sizeof(struct sockaddr_in6);
+ }
+ else
+#endif
+ /* IPv4 address */
+ if((af == AF_INET) &&
+ (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
+ si4->sin_family = AF_INET;
+ si4->sin_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in);
+ }
+ }
+
+ if(done < 1) {
+ failf(data, "Couldn't bind to '%s'", dev);
+ return CURLE_INTERFACE_FAILED;
+ }
+ }
+ else {
+ /* no device was given, prepare sa to match af's needs */
+#ifdef ENABLE_IPV6
+ if(af == AF_INET6) {
+ si6->sin6_family = AF_INET6;
+ si6->sin6_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in6);
+ }
+ else
+#endif
+ if(af == AF_INET) {
+ si4->sin_family = AF_INET;
+ si4->sin_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in);
+ }
+ }
+
+ for(;;) {
+ if(bind(sockfd, sock, sizeof_sa) >= 0) {
+ /* we succeeded to bind */
+ struct Curl_sockaddr_storage add;
+ curl_socklen_t size = sizeof(add);
+ memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
+ if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
+ data->state.os_errno = error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return CURLE_INTERFACE_FAILED;
+ }
+ infof(data, "Local port: %hu\n", port);
+ conn->bits.bound = TRUE;
+ return CURLE_OK;
+ }
+
+ if(--portnum > 0) {
+ infof(data, "Bind to local port %hu failed, trying next\n", port);
+ port++; /* try next port */
+ /* We re-use/clobber the port variable here below */
+ if(sock->sa_family == AF_INET)
+ si4->sin_port = ntohs(port);
+#ifdef ENABLE_IPV6
+ else
+ si6->sin6_port = ntohs(port);
+#endif
+ }
+ else
+ break;
+ }
+
+ data->state.os_errno = error = SOCKERRNO;
+ failf(data, "bind failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+
+ return CURLE_INTERFACE_FAILED;
+}
+
+/*
+ * verifyconnect() returns TRUE if the connect really has happened.
+ */
+static bool verifyconnect(curl_socket_t sockfd, int *error)
+{
+ bool rc = TRUE;
+#ifdef SO_ERROR
+ int err = 0;
+ curl_socklen_t errSize = sizeof(err);
+
+#ifdef WIN32
+ /*
+ * In October 2003 we effectively nullified this function on Windows due to
+ * problems with it using all CPU in multi-threaded cases.
+ *
+ * In May 2004, we bring it back to offer more info back on connect failures.
+ * Gisle Vanem could reproduce the former problems with this function, but
+ * could avoid them by adding this SleepEx() call below:
+ *
+ * "I don't have Rational Quantify, but the hint from his post was
+ * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
+ * just Sleep(0) would be enough?) would release whatever
+ * mutex/critical-section the ntdll call is waiting on.
+ *
+ * Someone got to verify this on Win-NT 4.0, 2000."
+ */
+
+#ifdef _WIN32_WCE
+ Sleep(0);
+#elif !defined(CURL_WINRT)
+ SleepEx(0, FALSE);
+#endif
+
+#endif
+
+ if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
+ err = SOCKERRNO;
+#ifdef _WIN32_WCE
+ /* Old WinCE versions don't support SO_ERROR */
+ if(WSAENOPROTOOPT == err) {
+ SET_SOCKERRNO(0);
+ err = 0;
+ }
+#endif
+#ifdef __minix
+ /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
+ if(EBADIOCTL == err) {
+ SET_SOCKERRNO(0);
+ err = 0;
+ }
+#endif
+ if((0 == err) || (EISCONN == err))
+ /* we are connected, awesome! */
+ rc = TRUE;
+ else
+ /* This wasn't a successful connect */
+ rc = FALSE;
+ if(error)
+ *error = err;
+#else
+ (void)sockfd;
+ if(error)
+ *error = SOCKERRNO;
+#endif
+ return rc;
+}
+
+/* Used within the multi interface. Try next IP address, return TRUE if no
+ more address exists or error */
+static CURLcode trynextip(struct connectdata *conn,
+ int sockindex,
+ int tempindex)
+{
+ const int other = tempindex ^ 1;
+ CURLcode result = CURLE_COULDNT_CONNECT;
+
+ /* First clean up after the failed socket.
+ Don't close it yet to ensure that the next IP's socket gets a different
+ file descriptor, which can prevent bugs when the curl_multi_socket_action
+ interface is used with certain select() replacements such as kqueue. */
+ curl_socket_t fd_to_close = conn->tempsock[tempindex];
+ conn->tempsock[tempindex] = CURL_SOCKET_BAD;
+
+ if(sockindex == FIRSTSOCKET) {
+ Curl_addrinfo *ai = NULL;
+ int family = AF_UNSPEC;
+
+ if(conn->tempaddr[tempindex]) {
+ /* find next address in the same protocol family */
+ family = conn->tempaddr[tempindex]->ai_family;
+ ai = conn->tempaddr[tempindex]->ai_next;
+ }
+#ifdef ENABLE_IPV6
+ else if(conn->tempaddr[0]) {
+ /* happy eyeballs - try the other protocol family */
+ int firstfamily = conn->tempaddr[0]->ai_family;
+ family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
+ ai = conn->tempaddr[0]->ai_next;
+ }
+#endif
+
+ while(ai) {
+ if(conn->tempaddr[other]) {
+ /* we can safely skip addresses of the other protocol family */
+ while(ai && ai->ai_family != family)
+ ai = ai->ai_next;
+ }
+
+ if(ai) {
+ result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
+ if(result == CURLE_COULDNT_CONNECT) {
+ ai = ai->ai_next;
+ continue;
+ }
+
+ conn->tempaddr[tempindex] = ai;
+ }
+ break;
+ }
+ }
+
+ if(fd_to_close != CURL_SOCKET_BAD)
+ Curl_closesocket(conn, fd_to_close);
+
+ return result;
+}
+
+/* Copies connection info into the session handle to make it available
+ when the session handle is no longer associated with a connection. */
+CURL_STATIC void Curl_persistconninfo(struct connectdata *conn)
+{
+ memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
+ memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
+ conn->data->info.conn_primary_port = conn->primary_port;
+ conn->data->info.conn_local_port = conn->local_port;
+}
+
+/* retrieves ip address and port from a sockaddr structure */
+static bool getaddressinfo(struct sockaddr* sa, char* addr,
+ long* port)
+{
+ unsigned short us_port;
+ struct sockaddr_in* si = NULL;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6* si6 = NULL;
+#endif
+#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
+ struct sockaddr_un* su = NULL;
+#endif
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ si = (struct sockaddr_in*) sa;
+ if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
+ addr, MAX_IPADR_LEN)) {
+ us_port = ntohs(si->sin_port);
+ *port = us_port;
+ return TRUE;
+ }
+ break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ si6 = (struct sockaddr_in6*)sa;
+ if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
+ addr, MAX_IPADR_LEN)) {
+ us_port = ntohs(si6->sin6_port);
+ *port = us_port;
+ return TRUE;
+ }
+ break;
+#endif
+#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
+ case AF_UNIX:
+ su = (struct sockaddr_un*)sa;
+ snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
+ *port = 0;
+ return TRUE;
+#endif
+ default:
+ break;
+ }
+
+ addr[0] = '\0';
+ *port = 0;
+
+ return FALSE;
+}
+
+/* retrieves the start/end point information of a socket of an established
+ connection */
+CURL_STATIC void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
+{
+ curl_socklen_t len;
+ struct Curl_sockaddr_storage ssrem;
+ struct Curl_sockaddr_storage ssloc;
+ struct SessionHandle *data = conn->data;
+
+ if(conn->socktype == SOCK_DGRAM)
+ /* there's no connection! */
+ return;
+
+ if(!conn->bits.reuse) {
+ int error;
+
+ len = sizeof(struct Curl_sockaddr_storage);
+ if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
+ error = SOCKERRNO;
+ failf(data, "getpeername() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+
+ len = sizeof(struct Curl_sockaddr_storage);
+ memset(&ssloc, 0, sizeof(ssloc));
+ if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
+ error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+
+ if(!getaddressinfo((struct sockaddr*)&ssrem,
+ conn->primary_ip, &conn->primary_port)) {
+ error = ERRNO;
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+ memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
+
+ if(!getaddressinfo((struct sockaddr*)&ssloc,
+ conn->local_ip, &conn->local_port)) {
+ error = ERRNO;
+ failf(data, "ssloc inet_ntop() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+
+ }
+
+ /* persist connection info in session handle */
+ Curl_persistconninfo(conn);
+}
+
+/*
+ * Curl_is_connected() checks if the socket has connected.
+ */
+
+CURL_STATIC CURLcode Curl_is_connected(struct connectdata *conn,
+ int sockindex,
+ bool *connected)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode result = CURLE_OK;
+ long allow;
+ int error = 0;
+ struct timeval now;
+ int rc;
+ int i;
+
+ DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
+
+ *connected = FALSE; /* a very negative world view is best */
+
+ if(conn->bits.tcpconnect[sockindex]) {
+ /* we are connected already! */
+ *connected = TRUE;
+ return CURLE_OK;
+ }
+
+ now = Curl_tvnow();
+
+ /* figure out how long time we have left to connect */
+ allow = Curl_timeleft(data, &now, TRUE);
+
+ if(allow < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ for(i=0; i<2; i++) {
+ const int other = i ^ 1;
+ if(conn->tempsock[i] == CURL_SOCKET_BAD)
+ continue;
+
+#ifdef mpeix
+ /* Call this function once now, and ignore the results. We do this to
+ "clear" the error state on the socket so that we can later read it
+ reliably. This is reported necessary on the MPE/iX operating system. */
+ (void)verifyconnect(conn->tempsock[i], NULL);
+#endif
+
+ /* check socket for connect */
+ rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
+
+ if(rc == 0) { /* no connection yet */
+ if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
+ infof(data, "After %ldms connect time, move on!\n",
+ conn->timeoutms_per_addr);
+ error = ETIMEDOUT;
+ }
+
+ /* should we try another protocol family? */
+ if(i == 0 && conn->tempaddr[1] == NULL &&
+ curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
+ trynextip(conn, sockindex, 1);
+ }
+ }
+ else if(rc == CURL_CSELECT_OUT) {
+ if(verifyconnect(conn->tempsock[i], &error)) {
+ /* we are connected with TCP, awesome! */
+
+ /* use this socket from now on */
+ conn->sock[sockindex] = conn->tempsock[i];
+ conn->ip_addr = conn->tempaddr[i];
+ conn->tempsock[i] = CURL_SOCKET_BAD;
+
+ /* close the other socket, if open */
+ if(conn->tempsock[other] != CURL_SOCKET_BAD) {
+ Curl_closesocket(conn, conn->tempsock[other]);
+ conn->tempsock[other] = CURL_SOCKET_BAD;
+ }
+
+ /* see if we need to do any proxy magic first once we connected */
+ result = Curl_connected_proxy(conn, sockindex);
+ if(result)
+ return result;
+
+ conn->bits.tcpconnect[sockindex] = TRUE;
+
+ *connected = TRUE;
+ if(sockindex == FIRSTSOCKET)
+ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
+ Curl_updateconninfo(conn, conn->sock[sockindex]);
+ Curl_verboseconnect(conn);
+
+ return CURLE_OK;
+ }
+ else
+ infof(data, "Connection failed\n");
+ }
+ else if(rc & CURL_CSELECT_ERR)
+ (void)verifyconnect(conn->tempsock[i], &error);
+
+ /*
+ * The connection failed here, we should attempt to connect to the "next
+ * address" for the given host. But first remember the latest error.
+ */
+ if(error) {
+ data->state.os_errno = error;
+ SET_SOCKERRNO(error);
+ if(conn->tempaddr[i]) {
+ CURLcode status;
+ char ipaddress[MAX_IPADR_LEN];
+ Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
+ infof(data, "connect to %s port %ld failed: %s\n",
+ ipaddress, conn->port, Curl_strerror(conn, error));
+
+ conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
+ allow : allow / 2;
+
+ status = trynextip(conn, sockindex, i);
+ if(status != CURLE_COULDNT_CONNECT
+ || conn->tempsock[other] == CURL_SOCKET_BAD)
+ /* the last attempt failed and no other sockets remain open */
+ result = status;
+ }
+ }
+ }
+
+ if(result) {
+ /* no more addresses to try */
+
+ /* if the first address family runs out of addresses to try before
+ the happy eyeball timeout, go ahead and try the next family now */
+ if(conn->tempaddr[1] == NULL) {
+ result = trynextip(conn, sockindex, 1);
+ if(!result)
+ return result;
+ }
+
+ failf(data, "Failed to connect to %s port %ld: %s",
+ conn->bits.proxy?conn->proxy.name:conn->host.name,
+ conn->port, Curl_strerror(conn, error));
+ }
+
+ return result;
+}
+
+static void tcpnodelay(struct connectdata *conn,
+ curl_socket_t sockfd)
+{
+#ifdef TCP_NODELAY
+ struct SessionHandle *data= conn->data;
+ curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
+ int level = IPPROTO_TCP;
+
+#if 0
+ /* The use of getprotobyname() is disabled since it isn't thread-safe on
+ numerous systems. On these getprotobyname_r() should be used instead, but
+ that exists in at least one 4 arg version and one 5 arg version, and
+ since the proto number rarely changes anyway we now just use the hard
+ coded number. The "proper" fix would need a configure check for the
+ correct function much in the same style the gethostbyname_r versions are
+ detected. */
+ struct protoent *pe = getprotobyname("tcp");
+ if(pe)
+ level = pe->p_proto;
+#endif
+
+ if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
+ sizeof(onoff)) < 0)
+ infof(data, "Could not set TCP_NODELAY: %s\n",
+ Curl_strerror(conn, SOCKERRNO));
+ else
+ infof(data, "TCP_NODELAY set\n");
+#else
+ (void)conn;
+ (void)sockfd;
+#endif
+}
+
+#ifdef SO_NOSIGPIPE
+/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
+ sending data to a dead peer (instead of relying on the 4th argument to send
+ being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
+ systems? */
+static void nosigpipe(struct connectdata *conn,
+ curl_socket_t sockfd)
+{
+ struct SessionHandle *data= conn->data;
+ int onoff = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
+ sizeof(onoff)) < 0)
+ infof(data, "Could not set SO_NOSIGPIPE: %s\n",
+ Curl_strerror(conn, SOCKERRNO));
+}
+#else
+#define nosigpipe(x,y) Curl_nop_stmt
+#endif
+
+#ifdef USE_WINSOCK
+/* When you run a program that uses the Windows Sockets API, you may
+ experience slow performance when you copy data to a TCP server.
+
+ http://support.microsoft.com/kb/823764
+
+ Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
+ Buffer Size
+
+ The problem described in this knowledge-base is applied only to pre-Vista
+ Windows. Following function trying to detect OS version and skips
+ SO_SNDBUF adjustment for Windows Vista and above.
+*/
+#define DETECT_OS_NONE 0
+#define DETECT_OS_PREVISTA 1
+#define DETECT_OS_VISTA_OR_LATER 2
+
+CURL_STATIC void Curl_sndbufset(curl_socket_t sockfd)
+{
+ int val = CURL_MAX_WRITE_SIZE + 32;
+ int curval = 0;
+ int curlen = sizeof(curval);
+ DWORD majorVersion = 6;
+
+ static int detectOsState = DETECT_OS_NONE;
+
+ if(detectOsState == DETECT_OS_NONE) {
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
+ (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
+ OSVERSIONINFO osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+
+ detectOsState = DETECT_OS_PREVISTA;
+ if(GetVersionEx(&osver)) {
+ if(osver.dwMajorVersion >= majorVersion)
+ detectOsState = DETECT_OS_VISTA_OR_LATER;
+ }
+#elif defined(CURL_WINRT)
+ detectOsState = DETECT_OS_VISTA_OR_LATER;
+#else
+ ULONGLONG majorVersionMask;
+ OSVERSIONINFOEX osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ osver.dwMajorVersion = majorVersion;
+ majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION,
+ VER_GREATER_EQUAL);
+
+ if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask))
+ detectOsState = DETECT_OS_VISTA_OR_LATER;
+ else
+ detectOsState = DETECT_OS_PREVISTA;
+#endif
+ }
+
+ if(detectOsState == DETECT_OS_VISTA_OR_LATER)
+ return;
+
+ if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
+ if(curval > val)
+ return;
+
+ setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
+}
+#endif
+
+/*
+ * singleipconnect()
+ *
+ * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
+ * CURL_SOCKET_BAD. Other errors will however return proper errors.
+ *
+ * singleipconnect() connects to the given IP only, and it may return without
+ * having connected.
+ */
+static CURLcode singleipconnect(struct connectdata *conn,
+ const Curl_addrinfo *ai,
+ curl_socket_t *sockp)
+{
+ struct Curl_sockaddr_ex addr;
+ int rc;
+ int error = 0;
+ bool isconnected = FALSE;
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd;
+ CURLcode result;
+ char ipaddress[MAX_IPADR_LEN];
+ long port;
+ bool is_tcp;
+
+ *sockp = CURL_SOCKET_BAD;
+
+ result = Curl_socket(conn, ai, &addr, &sockfd);
+ if(result)
+ /* Failed to create the socket, but still return OK since we signal the
+ lack of socket as well. This allows the parent function to keep looping
+ over alternative addresses/socket families etc. */
+ return CURLE_OK;
+
+ /* store remote address and port used in this connection attempt */
+ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
+ ipaddress, &port)) {
+ /* malformed address or bug in inet_ntop, try next address */
+ error = ERRNO;
+ failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ Curl_closesocket(conn, sockfd);
+ return CURLE_OK;
+ }
+ infof(data, " Trying %s...\n", ipaddress);
+
+#ifdef ENABLE_IPV6
+ is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
+ addr.socktype == SOCK_STREAM;
+#else
+ is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
+#endif
+ if(is_tcp && data->set.tcp_nodelay)
+ tcpnodelay(conn, sockfd);
+
+ nosigpipe(conn, sockfd);
+
+ Curl_sndbufset(sockfd);
+
+ if(is_tcp && data->set.tcp_keepalive)
+ tcpkeepalive(data, sockfd);
+
+ if(data->set.fsockopt) {
+ /* activate callback for setting socket options */
+ error = data->set.fsockopt(data->set.sockopt_client,
+ sockfd,
+ CURLSOCKTYPE_IPCXN);
+
+ if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
+ isconnected = TRUE;
+ else if(error) {
+ Curl_closesocket(conn, sockfd); /* close the socket and bail out */
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ }
+
+ /* possibly bind the local end to an IP, interface or port */
+ if(addr.family == AF_INET
+#ifdef ENABLE_IPV6
+ || addr.family == AF_INET6
+#endif
+ ) {
+ result = bindlocal(conn, sockfd, addr.family,
+ Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
+ if(result) {
+ Curl_closesocket(conn, sockfd); /* close socket and bail out */
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ /* The address family is not supported on this interface.
+ We can continue trying addresses */
+ return CURLE_COULDNT_CONNECT;
+ }
+ return result;
+ }
+ }
+
+ /* set socket non-blocking */
+ (void)curlx_nonblock(sockfd, TRUE);
+
+ conn->connecttime = Curl_tvnow();
+ if(conn->num_addr > 1)
+ Curl_expire_latest(data, conn->timeoutms_per_addr);
+
+ /* Connect TCP sockets, bind UDP */
+ if(!isconnected && (conn->socktype == SOCK_STREAM)) {
+ rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+ if(-1 == rc)
+ error = SOCKERRNO;
+ }
+ else {
+ *sockp = sockfd;
+ return CURLE_OK;
+ }
+
+#ifdef ENABLE_IPV6
+ conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
+#endif
+
+ if(-1 == rc) {
+ switch(error) {
+ case EINPROGRESS:
+ case EWOULDBLOCK:
+#if defined(EAGAIN)
+#if (EAGAIN) != (EWOULDBLOCK)
+ /* On some platforms EAGAIN and EWOULDBLOCK are the
+ * same value, and on others they are different, hence
+ * the odd #if
+ */
+ case EAGAIN:
+#endif
+#endif
+ result = CURLE_OK;
+ break;
+
+ default:
+ /* unknown error, fallthrough and try another address! */
+ infof(data, "Immediate connect fail for %s: %s\n",
+ ipaddress, Curl_strerror(conn, error));
+ data->state.os_errno = error;
+
+ /* connect failed */
+ Curl_closesocket(conn, sockfd);
+ result = CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ if(!result)
+ *sockp = sockfd;
+
+ return result;
+}
+
+/*
+ * TCP connect to the given host with timeout, proxy or remote doesn't matter.
+ * There might be more than one IP address to try out. Fill in the passed
+ * pointer with the connected socket.
+ */
+
+CURL_STATIC CURLcode Curl_connecthost(struct connectdata *conn, /* context */
+ const struct Curl_dns_entry *remotehost)
+{
+ struct SessionHandle *data = conn->data;
+ struct timeval before = Curl_tvnow();
+ CURLcode result = CURLE_COULDNT_CONNECT;
+
+ long timeout_ms = Curl_timeleft(data, &before, TRUE);
+
+ if(timeout_ms < 0) {
+ /* a precaution, no need to continue if time already is up */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ conn->num_addr = Curl_num_addresses(remotehost->addr);
+ conn->tempaddr[0] = remotehost->addr;
+ conn->tempaddr[1] = NULL;
+ conn->tempsock[0] = CURL_SOCKET_BAD;
+ conn->tempsock[1] = CURL_SOCKET_BAD;
+ Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
+
+ /* Max time for the next connection attempt */
+ conn->timeoutms_per_addr =
+ conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
+
+ /* start connecting to first IP */
+ while(conn->tempaddr[0]) {
+ result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
+ if(!result)
+ break;
+ conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
+ }
+
+ if(conn->tempsock[0] == CURL_SOCKET_BAD)
+ return result;
+
+ data->info.numconnects++; /* to track the number of connections made */
+
+ return CURLE_OK;
+}
+
+struct connfind {
+ struct connectdata *tofind;
+ bool found;
+};
+
+static int conn_is_conn(struct connectdata *conn, void *param)
+{
+ struct connfind *f = (struct connfind *)param;
+ if(conn == f->tofind) {
+ f->found = TRUE;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Used to extract socket and connectdata struct for the most recent
+ * transfer on the given SessionHandle.
+ *
+ * The returned socket will be CURL_SOCKET_BAD in case of failure!
+ */
+CURL_STATIC curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
+ struct connectdata **connp)
+{
+ curl_socket_t sockfd;
+
+ DEBUGASSERT(data);
+
+ /* this works for an easy handle:
+ * - that has been used for curl_easy_perform()
+ * - that is associated with a multi handle, and whose connection
+ * was detached with CURLOPT_CONNECT_ONLY
+ */
+ if(data->state.lastconnect && (data->multi_easy || data->multi)) {
+ struct connectdata *c = data->state.lastconnect;
+ struct connfind find;
+ find.tofind = data->state.lastconnect;
+ find.found = FALSE;
+
+ Curl_conncache_foreach(data->multi_easy?
+ data->multi_easy->conn_cache:
+ data->multi->conn_cache, &find, conn_is_conn);
+
+ if(!find.found) {
+ data->state.lastconnect = NULL;
+ return CURL_SOCKET_BAD;
+ }
+
+ if(connp)
+ /* only store this if the caller cares for it */
+ *connp = c;
+ sockfd = c->sock[FIRSTSOCKET];
+ /* we have a socket connected, let's determine if the server shut down */
+ /* determine if ssl */
+ if(c->ssl[FIRSTSOCKET].use) {
+ /* use the SSL context */
+ if(!Curl_ssl_check_cxn(c))
+ return CURL_SOCKET_BAD; /* FIN received */
+ }
+/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
+#ifdef MSG_PEEK
+ else {
+ /* use the socket */
+ char buf;
+ if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
+ (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
+ return CURL_SOCKET_BAD; /* FIN received */
+ }
+ }
+#endif
+ }
+ else
+ return CURL_SOCKET_BAD;
+
+ return sockfd;
+}
+
+/*
+ * Close a socket.
+ *
+ * 'conn' can be NULL, beware!
+ */
+CURL_STATIC int Curl_closesocket(struct connectdata *conn,
+ curl_socket_t sock)
+{
+ if(conn && conn->fclosesocket) {
+ if((sock == conn->sock[SECONDARYSOCKET]) &&
+ conn->sock_accepted[SECONDARYSOCKET])
+ /* if this socket matches the second socket, and that was created with
+ accept, then we MUST NOT call the callback but clear the accepted
+ status */
+ conn->sock_accepted[SECONDARYSOCKET] = FALSE;
+ else {
+ Curl_multi_closed(conn, sock);
+ return conn->fclosesocket(conn->closesocket_client, sock);
+ }
+ }
+
+ if(conn)
+ /* tell the multi-socket code about this */
+ Curl_multi_closed(conn, sock);
+
+ sclose(sock);
+
+ return 0;
+}
+
+/*
+ * Create a socket based on info from 'conn' and 'ai'.
+ *
+ * 'addr' should be a pointer to the correct struct to get data back, or NULL.
+ * 'sockfd' must be a pointer to a socket descriptor.
+ *
+ * If the open socket callback is set, used that!
+ *
+ */
+CURL_STATIC CURLcode Curl_socket(struct connectdata *conn,
+ const Curl_addrinfo *ai,
+ struct Curl_sockaddr_ex *addr,
+ curl_socket_t *sockfd)
+{
+ struct SessionHandle *data = conn->data;
+ struct Curl_sockaddr_ex dummy;
+
+ if(!addr)
+ /* if the caller doesn't want info back, use a local temp copy */
+ addr = &dummy;
+
+ /*
+ * The Curl_sockaddr_ex structure is basically libcurl's external API
+ * curl_sockaddr structure with enough space available to directly hold
+ * any protocol-specific address structures. The variable declared here
+ * will be used to pass / receive data to/from the fopensocket callback
+ * if this has been set, before that, it is initialized from parameters.
+ */
+
+ addr->family = ai->ai_family;
+ addr->socktype = conn->socktype;
+ addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
+ addr->addrlen = ai->ai_addrlen;
+
+ if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
+ addr->addrlen = sizeof(struct Curl_sockaddr_storage);
+ memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
+
+ if(data->set.fopensocket)
+ /*
+ * If the opensocket callback is set, all the destination address
+ * information is passed to the callback. Depending on this information the
+ * callback may opt to abort the connection, this is indicated returning
+ * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
+ * the callback returns a valid socket the destination address information
+ * might have been changed and this 'new' address will actually be used
+ * here to connect.
+ */
+ *sockfd = data->set.fopensocket(data->set.opensocket_client,
+ CURLSOCKTYPE_IPCXN,
+ (struct curl_sockaddr *)addr);
+ else
+ /* opensocket callback not set, so simply create the socket now */
+ *sockfd = socket(addr->family, addr->socktype, addr->protocol);
+
+ if(*sockfd == CURL_SOCKET_BAD)
+ /* no socket, no connection */
+ return CURLE_COULDNT_CONNECT;
+
+#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
+ if(conn->scope_id && (addr->family == AF_INET6)) {
+ struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
+ sa6->sin6_scope_id = conn->scope_id;
+ }
+#endif
+
+ return CURLE_OK;
+
+}
+
+#ifdef CURLDEBUG
+/*
+ * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
+ * MUST be called with the connclose() or connkeep() macros with a stated
+ * reason. The reason is only shown in debug builds but helps to figure out
+ * decision paths when connections are or aren't re-used as expected.
+ */
+CURL_STATIC void Curl_conncontrol(struct connectdata *conn, bool closeit,
+ const char *reason)
+{
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) reason;
+#endif
+ if(closeit != conn->bits.close) {
+ infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
+ reason);
+
+ conn->bits.close = closeit; /* the only place in the source code that
+ should assign this bit */
+ }
+}
+#endif
diff --git a/libcurl/src/lib/connect.h b/libcurl/src/lib/connect.h
new file mode 100644
index 0000000..f18ed55
--- /dev/null
+++ b/libcurl/src/lib/connect.h
@@ -0,0 +1,122 @@
+#ifndef HEADER_CURL_CONNECT_H
+#define HEADER_CURL_CONNECT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
+#include "sockaddr.h"
+
+CURL_STATIC CURLcode Curl_is_connected(struct connectdata *conn,
+ int sockindex,
+ bool *connected);
+
+CURL_STATIC CURLcode Curl_connecthost(struct connectdata *conn,
+ const struct Curl_dns_entry *host);
+
+/* generic function that returns how much time there's left to run, according
+ to the timeouts set */
+CURL_STATIC long Curl_timeleft(struct SessionHandle *data,
+ struct timeval *nowp,
+ bool duringconnect);
+
+#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
+#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
+ IPv4/IPv6 connection attempts */
+
+/*
+ * Used to extract socket and connectdata struct for the most recent
+ * transfer on the given SessionHandle.
+ *
+ * The returned socket will be CURL_SOCKET_BAD in case of failure!
+ */
+CURL_STATIC curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
+ struct connectdata **connp);
+
+#ifdef USE_WINSOCK
+/* When you run a program that uses the Windows Sockets API, you may
+ experience slow performance when you copy data to a TCP server.
+
+ http://support.microsoft.com/kb/823764
+
+ Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
+ Buffer Size
+
+*/
+CURL_STATIC void Curl_sndbufset(curl_socket_t sockfd);
+#else
+#define Curl_sndbufset(y) Curl_nop_stmt
+#endif
+
+CURL_STATIC void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
+CURL_STATIC void Curl_persistconninfo(struct connectdata *conn);
+CURL_STATIC int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
+
+/*
+ * The Curl_sockaddr_ex structure is basically libcurl's external API
+ * curl_sockaddr structure with enough space available to directly hold any
+ * protocol-specific address structures. The variable declared here will be
+ * used to pass / receive data to/from the fopensocket callback if this has
+ * been set, before that, it is initialized from parameters.
+ */
+struct Curl_sockaddr_ex {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen;
+ union {
+ struct sockaddr addr;
+ struct Curl_sockaddr_storage buff;
+ } _sa_ex_u;
+};
+#define sa_addr _sa_ex_u.addr
+
+/*
+ * Create a socket based on info from 'conn' and 'ai'.
+ *
+ * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
+ * socket callback is set, used that!
+ *
+ */
+CURL_STATIC CURLcode Curl_socket(struct connectdata *conn,
+ const Curl_addrinfo *ai,
+ struct Curl_sockaddr_ex *addr,
+ curl_socket_t *sockfd);
+
+#ifdef CURLDEBUG
+/*
+ * Curl_connclose() sets the bit.close bit to TRUE with an explanation.
+ * Nothing else.
+ */
+CURL_STATIC void Curl_conncontrol(struct connectdata *conn,
+ bool closeit,
+ const char *reason);
+#define connclose(x,y) Curl_conncontrol(x,TRUE, y)
+#define connkeep(x,y) Curl_conncontrol(x, FALSE, y)
+#else /* if !CURLDEBUG */
+
+#define connclose(x,y) (x)->bits.close = TRUE
+#define connkeep(x,y) (x)->bits.close = FALSE
+
+#endif
+
+#endif /* HEADER_CURL_CONNECT_H */
diff --git a/libcurl/src/lib/content_encoding.c b/libcurl/src/lib/content_encoding.c
new file mode 100644
index 0000000..0da02c8
--- /dev/null
+++ b/libcurl/src/lib/content_encoding.c
@@ -0,0 +1,435 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIBZ
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "sendf.h"
+#include "content_encoding.h"
+#include "curl_memory.h"
+
+#include "memdebug.h"
+
+/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
+ (doing so will reduce code size slightly). */
+#define OLD_ZLIB_SUPPORT 1
+
+#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
+
+#define GZIP_MAGIC_0 0x1f
+#define GZIP_MAGIC_1 0x8b
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+static voidpf
+zalloc_cb(voidpf opaque, unsigned int items, unsigned int size)
+{
+ (void) opaque;
+ /* not a typo, keep it calloc() */
+ return (voidpf) calloc(items, size);
+}
+
+static void
+zfree_cb(voidpf opaque, voidpf ptr)
+{
+ (void) opaque;
+ free(ptr);
+}
+
+static CURLcode
+process_zlib_error(struct connectdata *conn, z_stream *z)
+{
+ struct SessionHandle *data = conn->data;
+ if(z->msg)
+ failf (data, "Error while processing content unencoding: %s",
+ z->msg);
+ else
+ failf (data, "Error while processing content unencoding: "
+ "Unknown failure within decompression software.");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+}
+
+static CURLcode
+exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result)
+{
+ inflateEnd(z);
+ *zlib_init = ZLIB_UNINIT;
+ return result;
+}
+
+static CURLcode
+inflate_stream(struct connectdata *conn,
+ struct SingleRequest *k)
+{
+ int allow_restart = 1;
+ z_stream *z = &k->z; /* zlib state structure */
+ uInt nread = z->avail_in;
+ Bytef *orig_in = z->next_in;
+ int status; /* zlib status */
+ CURLcode result = CURLE_OK; /* Curl_client_write status */
+ char *decomp; /* Put the decompressed data here. */
+
+ /* Dynamically allocate a buffer for decompression because it's uncommonly
+ large to hold on the stack */
+ decomp = malloc(DSIZ);
+ if(decomp == NULL) {
+ return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+ }
+
+ /* because the buffer size is fixed, iteratively decompress and transfer to
+ the client via client_write. */
+ for(;;) {
+ /* (re)set buffer for decompressed output for every iteration */
+ z->next_out = (Bytef *)decomp;
+ z->avail_out = DSIZ;
+
+ status = inflate(z, Z_SYNC_FLUSH);
+ if(status == Z_OK || status == Z_STREAM_END) {
+ allow_restart = 0;
+ if((DSIZ - z->avail_out) && (!k->ignorebody)) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp,
+ DSIZ - z->avail_out);
+ /* if !CURLE_OK, clean up, return */
+ if(result) {
+ free(decomp);
+ return exit_zlib(z, &k->zlib_init, result);
+ }
+ }
+
+ /* Done? clean up, return */
+ if(status == Z_STREAM_END) {
+ free(decomp);
+ if(inflateEnd(z) == Z_OK)
+ return exit_zlib(z, &k->zlib_init, result);
+ else
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+
+ /* Done with these bytes, exit */
+
+ /* status is always Z_OK at this point! */
+ if(z->avail_in == 0) {
+ free(decomp);
+ return result;
+ }
+ }
+ else if(allow_restart && status == Z_DATA_ERROR) {
+ /* some servers seem to not generate zlib headers, so this is an attempt
+ to fix and continue anyway */
+
+ (void) inflateEnd(z); /* don't care about the return code */
+ if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
+ free(decomp);
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+ z->next_in = orig_in;
+ z->avail_in = nread;
+ allow_restart = 0;
+ continue;
+ }
+ else { /* Error; exit loop, handle below */
+ free(decomp);
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+ }
+ /* Will never get here */
+}
+
+CURL_STATIC CURLcode
+Curl_unencode_deflate_write(struct connectdata *conn,
+ struct SingleRequest *k,
+ ssize_t nread)
+{
+ z_stream *z = &k->z; /* zlib state structure */
+
+ /* Initialize zlib? */
+ if(k->zlib_init == ZLIB_UNINIT) {
+ memset(z, 0, sizeof(z_stream));
+ z->zalloc = (alloc_func)zalloc_cb;
+ z->zfree = (free_func)zfree_cb;
+
+ if(inflateInit(z) != Z_OK)
+ return process_zlib_error(conn, z);
+ k->zlib_init = ZLIB_INIT;
+ }
+
+ /* Set the compressed input when this function is called */
+ z->next_in = (Bytef *)k->str;
+ z->avail_in = (uInt)nread;
+
+ /* Now uncompress the data */
+ return inflate_stream(conn, k);
+}
+
+#ifdef OLD_ZLIB_SUPPORT
+/* Skip over the gzip header */
+static enum {
+ GZIP_OK,
+ GZIP_BAD,
+ GZIP_UNDERFLOW
+} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
+{
+ int method, flags;
+ const ssize_t totallen = len;
+
+ /* The shortest header is 10 bytes */
+ if(len < 10)
+ return GZIP_UNDERFLOW;
+
+ if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
+ return GZIP_BAD;
+
+ method = data[2];
+ flags = data[3];
+
+ if(method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ /* Can't handle this compression method or unknown flag */
+ return GZIP_BAD;
+ }
+
+ /* Skip over time, xflags, OS code and all previous bytes */
+ len -= 10;
+ data += 10;
+
+ if(flags & EXTRA_FIELD) {
+ ssize_t extra_len;
+
+ if(len < 2)
+ return GZIP_UNDERFLOW;
+
+ extra_len = (data[1] << 8) | data[0];
+
+ if(len < (extra_len+2))
+ return GZIP_UNDERFLOW;
+
+ len -= (extra_len + 2);
+ data += (extra_len + 2);
+ }
+
+ if(flags & ORIG_NAME) {
+ /* Skip over NUL-terminated file name */
+ while(len && *data) {
+ --len;
+ ++data;
+ }
+ if(!len || *data)
+ return GZIP_UNDERFLOW;
+
+ /* Skip over the NUL */
+ --len;
+ ++data;
+ }
+
+ if(flags & COMMENT) {
+ /* Skip over NUL-terminated comment */
+ while(len && *data) {
+ --len;
+ ++data;
+ }
+ if(!len || *data)
+ return GZIP_UNDERFLOW;
+
+ /* Skip over the NUL */
+ --len;
+ }
+
+ if(flags & HEAD_CRC) {
+ if(len < 2)
+ return GZIP_UNDERFLOW;
+
+ len -= 2;
+ }
+
+ *headerlen = totallen - len;
+ return GZIP_OK;
+}
+#endif
+
+CURL_STATIC CURLcode
+Curl_unencode_gzip_write(struct connectdata *conn,
+ struct SingleRequest *k,
+ ssize_t nread)
+{
+ z_stream *z = &k->z; /* zlib state structure */
+
+ /* Initialize zlib? */
+ if(k->zlib_init == ZLIB_UNINIT) {
+ memset(z, 0, sizeof(z_stream));
+ z->zalloc = (alloc_func)zalloc_cb;
+ z->zfree = (free_func)zfree_cb;
+
+ if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
+ /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
+ if(inflateInit2(z, MAX_WBITS+32) != Z_OK) {
+ return process_zlib_error(conn, z);
+ }
+ k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
+ }
+ else {
+ /* we must parse the gzip header ourselves */
+ if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
+ return process_zlib_error(conn, z);
+ }
+ k->zlib_init = ZLIB_INIT; /* Initial call state */
+ }
+ }
+
+ if(k->zlib_init == ZLIB_INIT_GZIP) {
+ /* Let zlib handle the gzip decompression entirely */
+ z->next_in = (Bytef *)k->str;
+ z->avail_in = (uInt)nread;
+ /* Now uncompress the data */
+ return inflate_stream(conn, k);
+ }
+
+#ifndef OLD_ZLIB_SUPPORT
+ /* Support for old zlib versions is compiled away and we are running with
+ an old version, so return an error. */
+ return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND);
+
+#else
+ /* This next mess is to get around the potential case where there isn't
+ * enough data passed in to skip over the gzip header. If that happens, we
+ * malloc a block and copy what we have then wait for the next call. If
+ * there still isn't enough (this is definitely a worst-case scenario), we
+ * make the block bigger, copy the next part in and keep waiting.
+ *
+ * This is only required with zlib versions < 1.2.0.4 as newer versions
+ * can handle the gzip header themselves.
+ */
+
+ switch (k->zlib_init) {
+ /* Skip over gzip header? */
+ case ZLIB_INIT:
+ {
+ /* Initial call state */
+ ssize_t hlen;
+
+ switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
+ case GZIP_OK:
+ z->next_in = (Bytef *)k->str + hlen;
+ z->avail_in = (uInt)(nread - hlen);
+ k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
+ break;
+
+ case GZIP_UNDERFLOW:
+ /* We need more data so we can find the end of the gzip header. It's
+ * possible that the memory block we malloc here will never be freed if
+ * the transfer abruptly aborts after this point. Since it's unlikely
+ * that circumstances will be right for this code path to be followed in
+ * the first place, and it's even more unlikely for a transfer to fail
+ * immediately afterwards, it should seldom be a problem.
+ */
+ z->avail_in = (uInt)nread;
+ z->next_in = malloc(z->avail_in);
+ if(z->next_in == NULL) {
+ return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+ }
+ memcpy(z->next_in, k->str, z->avail_in);
+ k->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
+ /* We don't have any data to inflate yet */
+ return CURLE_OK;
+
+ case GZIP_BAD:
+ default:
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+
+ }
+ break;
+
+ case ZLIB_GZIP_HEADER:
+ {
+ /* Need more gzip header data state */
+ ssize_t hlen;
+ unsigned char *oldblock = z->next_in;
+
+ z->avail_in += (uInt)nread;
+ z->next_in = realloc(z->next_in, z->avail_in);
+ if(z->next_in == NULL) {
+ free(oldblock);
+ return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+ }
+ /* Append the new block of data to the previous one */
+ memcpy(z->next_in + z->avail_in - nread, k->str, nread);
+
+ switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
+ case GZIP_OK:
+ /* This is the zlib stream data */
+ free(z->next_in);
+ /* Don't point into the malloced block since we just freed it */
+ z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in;
+ z->avail_in = (uInt)(z->avail_in - hlen);
+ k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
+ break;
+
+ case GZIP_UNDERFLOW:
+ /* We still don't have any data to inflate! */
+ return CURLE_OK;
+
+ case GZIP_BAD:
+ default:
+ free(z->next_in);
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+
+ }
+ break;
+
+ case ZLIB_GZIP_INFLATING:
+ default:
+ /* Inflating stream state */
+ z->next_in = (Bytef *)k->str;
+ z->avail_in = (uInt)nread;
+ break;
+ }
+
+ if(z->avail_in == 0) {
+ /* We don't have any data to inflate; wait until next time */
+ return CURLE_OK;
+ }
+
+ /* We've parsed the header, now uncompress the data */
+ return inflate_stream(conn, k);
+#endif
+}
+
+CURL_STATIC void Curl_unencode_cleanup(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+ z_stream *z = &k->z;
+ if(k->zlib_init != ZLIB_UNINIT)
+ (void) exit_zlib(z, &k->zlib_init, CURLE_OK);
+}
+
+#endif /* HAVE_LIBZ */
diff --git a/libcurl/src/lib/content_encoding.h b/libcurl/src/lib/content_encoding.h
new file mode 100644
index 0000000..433e8d7
--- /dev/null
+++ b/libcurl/src/lib/content_encoding.h
@@ -0,0 +1,48 @@
+#ifndef HEADER_CURL_CONTENT_ENCODING_H
+#define HEADER_CURL_CONTENT_ENCODING_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * Comma-separated list all supported Content-Encodings ('identity' is implied)
+ */
+#ifdef HAVE_LIBZ
+#define ALL_CONTENT_ENCODINGS "deflate, gzip"
+/* force a cleanup */
+CURL_STATIC void Curl_unencode_cleanup(struct connectdata *conn);
+#else
+#define ALL_CONTENT_ENCODINGS "identity"
+#define Curl_unencode_cleanup(x) Curl_nop_stmt
+#endif
+
+CURL_STATIC CURLcode Curl_unencode_deflate_write(struct connectdata *conn,
+ struct SingleRequest *req,
+ ssize_t nread);
+
+CURL_STATIC CURLcode
+Curl_unencode_gzip_write(struct connectdata *conn,
+ struct SingleRequest *k,
+ ssize_t nread);
+
+
+#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/libcurl/src/lib/cookie.c b/libcurl/src/lib/cookie.c
new file mode 100644
index 0000000..61fc759
--- /dev/null
+++ b/libcurl/src/lib/cookie.c
@@ -0,0 +1,1365 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/***
+
+
+RECEIVING COOKIE INFORMATION
+============================
+
+struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
+ const char *file, struct CookieInfo *inc, bool newsession);
+
+ Inits a cookie struct to store data in a local file. This is always
+ called before any cookies are set.
+
+struct Cookie *Curl_cookie_add(struct SessionHandle *data,
+ struct CookieInfo *c, bool httpheader, char *lineptr,
+ const char *domain, const char *path);
+
+ The 'lineptr' parameter is a full "Set-cookie:" line as
+ received from a server.
+
+ The function need to replace previously stored lines that this new
+ line superceeds.
+
+ It may remove lines that are expired.
+
+ It should return an indication of success/error.
+
+
+SENDING COOKIE INFORMATION
+==========================
+
+struct Cookies *Curl_cookie_getlist(struct CookieInfo *cookie,
+ char *host, char *path, bool secure);
+
+ For a given host and path, return a linked list of cookies that
+ the client should send to the server if used now. The secure
+ boolean informs the cookie if a secure connection is achieved or
+ not.
+
+ It shall only return cookies that haven't expired.
+
+
+Example set of cookies:
+
+ Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
+ Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/ftgw; secure
+ Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie:
+ Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday,
+ 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
+****/
+
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+
+#include "curl_printf.h"
+#include "urldata.h"
+#include "cookie.h"
+#include "strequal.h"
+#include "strtok.h"
+#include "sendf.h"
+#include "slist.h"
+#include "share.h"
+#include "strtoofft.h"
+#include "rawstr.h"
+#include "curl_memrchr.h"
+#include "inet_pton.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+static void freecookie(struct Cookie *co)
+{
+ free(co->expirestr);
+ free(co->domain);
+ free(co->path);
+ free(co->spath);
+ free(co->name);
+ free(co->value);
+ free(co->maxage);
+ free(co->version);
+ free(co);
+}
+
+static bool tailmatch(const char *cooke_domain, const char *hostname)
+{
+ size_t cookie_domain_len = strlen(cooke_domain);
+ size_t hostname_len = strlen(hostname);
+
+ if(hostname_len < cookie_domain_len)
+ return FALSE;
+
+ if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len))
+ return FALSE;
+
+ /* A lead char of cookie_domain is not '.'.
+ RFC6265 4.1.2.3. The Domain Attribute says:
+ For example, if the value of the Domain attribute is
+ "example.com", the user agent will include the cookie in the Cookie
+ header when making HTTP requests to example.com, www.example.com, and
+ www.corp.example.com.
+ */
+ if(hostname_len == cookie_domain_len)
+ return TRUE;
+ if('.' == *(hostname + hostname_len - cookie_domain_len - 1))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * matching cookie path and url path
+ * RFC6265 5.1.4 Paths and Path-Match
+ */
+static bool pathmatch(const char* cookie_path, const char* request_uri)
+{
+ size_t cookie_path_len;
+ size_t uri_path_len;
+ char* uri_path = NULL;
+ char* pos;
+ bool ret = FALSE;
+
+ /* cookie_path must not have last '/' separator. ex: /sample */
+ cookie_path_len = strlen(cookie_path);
+ if(1 == cookie_path_len) {
+ /* cookie_path must be '/' */
+ return TRUE;
+ }
+
+ uri_path = strdup(request_uri);
+ if(!uri_path)
+ return FALSE;
+ pos = strchr(uri_path, '?');
+ if(pos)
+ *pos = 0x0;
+
+ /* #-fragments are already cut off! */
+ if(0 == strlen(uri_path) || uri_path[0] != '/') {
+ free(uri_path);
+ uri_path = strdup("/");
+ if(!uri_path)
+ return FALSE;
+ }
+
+ /* here, RFC6265 5.1.4 says
+ 4. Output the characters of the uri-path from the first character up
+ to, but not including, the right-most %x2F ("/").
+ but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
+ without redirect.
+ Ignore this algorithm because /hoge is uri path for this case
+ (uri path is not /).
+ */
+
+ uri_path_len = strlen(uri_path);
+
+ if(uri_path_len < cookie_path_len) {
+ ret = FALSE;
+ goto pathmatched;
+ }
+
+ /* not using checkprefix() because matching should be case-sensitive */
+ if(strncmp(cookie_path, uri_path, cookie_path_len)) {
+ ret = FALSE;
+ goto pathmatched;
+ }
+
+ /* The cookie-path and the uri-path are identical. */
+ if(cookie_path_len == uri_path_len) {
+ ret = TRUE;
+ goto pathmatched;
+ }
+
+ /* here, cookie_path_len < url_path_len */
+ if(uri_path[cookie_path_len] == '/') {
+ ret = TRUE;
+ goto pathmatched;
+ }
+
+ ret = FALSE;
+
+pathmatched:
+ free(uri_path);
+ return ret;
+}
+
+/*
+ * cookie path sanitize
+ */
+static char *sanitize_cookie_path(const char *cookie_path)
+{
+ size_t len;
+ char *new_path = strdup(cookie_path);
+ if(!new_path)
+ return NULL;
+
+ /* some stupid site sends path attribute with '"'. */
+ len = strlen(new_path);
+ if(new_path[0] == '\"') {
+ memmove((void *)new_path, (const void *)(new_path + 1), len);
+ len--;
+ }
+ if(len && (new_path[len - 1] == '\"')) {
+ new_path[len - 1] = 0x0;
+ len--;
+ }
+
+ /* RFC6265 5.2.4 The Path Attribute */
+ if(new_path[0] != '/') {
+ /* Let cookie-path be the default-path. */
+ free(new_path);
+ new_path = strdup("/");
+ return new_path;
+ }
+
+ /* convert /hoge/ to /hoge */
+ if(len && new_path[len - 1] == '/') {
+ new_path[len - 1] = 0x0;
+ }
+
+ return new_path;
+}
+
+/*
+ * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
+ *
+ * NOTE: OOM or cookie parsing failures are ignored.
+ */
+CURL_STATIC void Curl_cookie_loadfiles(struct SessionHandle *data)
+{
+ struct curl_slist *list = data->change.cookielist;
+ if(list) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ while(list) {
+ struct CookieInfo *newcookies = Curl_cookie_init(data,
+ list->data,
+ data->cookies,
+ data->set.cookiesession);
+ if(!newcookies)
+ /* Failure may be due to OOM or a bad cookie; both are ignored
+ * but only the first should be
+ */
+ infof(data, "ignoring failed cookie_init for %s\n", list->data);
+ else
+ data->cookies = newcookies;
+ list = list->next;
+ }
+ curl_slist_free_all(data->change.cookielist); /* clean up list */
+ data->change.cookielist = NULL; /* don't do this again! */
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+}
+
+/*
+ * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL
+ * that will be freed before the allocated string is stored there.
+ *
+ * It is meant to easily replace strdup()
+ */
+static void strstore(char **str, const char *newstr)
+{
+ free(*str);
+ *str = strdup(newstr);
+}
+
+/*
+ * remove_expired() removes expired cookies.
+ */
+static void remove_expired(struct CookieInfo *cookies)
+{
+ struct Cookie *co, *nx, *pv;
+ curl_off_t now = (curl_off_t)time(NULL);
+
+ co = cookies->cookies;
+ pv = NULL;
+ while(co) {
+ nx = co->next;
+ if((co->expirestr || co->maxage) && co->expires < now) {
+ if(co == cookies->cookies) {
+ cookies->cookies = co->next;
+ }
+ else {
+ pv->next = co->next;
+ }
+ cookies->numcookies--;
+ freecookie(co);
+ }
+ else {
+ pv = co;
+ }
+ co = nx;
+ }
+}
+
+/*
+ * Return true if the given string is an IP(v4|v6) address.
+ */
+static bool isip(const char *domain)
+{
+ struct in_addr addr;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+
+ if(Curl_inet_pton(AF_INET, domain, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, domain, &addr6)
+#endif
+ ) {
+ /* domain name given as IP address */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/****************************************************************************
+ *
+ * Curl_cookie_add()
+ *
+ * Add a single cookie line to the cookie keeping object.
+ *
+ * Be aware that sometimes we get an IP-only host name, and that might also be
+ * a numerical IPv6 address.
+ *
+ * Returns NULL on out of memory or invalid cookie. This is suboptimal,
+ * as they should be treated separately.
+ ***************************************************************************/
+
+struct Cookie *
+Curl_cookie_add(struct SessionHandle *data,
+ /* The 'data' pointer here may be NULL at times, and thus
+ must only be used very carefully for things that can deal
+ with data being NULL. Such as infof() and similar */
+
+ struct CookieInfo *c,
+ bool httpheader, /* TRUE if HTTP header-style line */
+ char *lineptr, /* first character of the line */
+ const char *domain, /* default domain */
+ const char *path) /* full path used when this cookie is set,
+ used to get default path for the cookie
+ unless set */
+{
+ struct Cookie *clist;
+ char name[MAX_NAME];
+ struct Cookie *co;
+ struct Cookie *lastc=NULL;
+ time_t now = time(NULL);
+ bool replace_old = FALSE;
+ bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
+
+ /* First, alloc and init a new struct for it */
+ co = calloc(1, sizeof(struct Cookie));
+ if(!co)
+ return NULL; /* bail out if we're this low on memory */
+
+ if(httpheader) {
+ /* This line was read off a HTTP-header */
+ const char *ptr;
+ const char *semiptr;
+ char *what;
+
+ what = malloc(MAX_COOKIE_LINE);
+ if(!what) {
+ free(co);
+ return NULL;
+ }
+
+ semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
+
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
+
+ ptr = lineptr;
+ do {
+ /* we have a <what>=<this> pair or a stand-alone word here */
+ name[0]=what[0]=0; /* init the buffers */
+ if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =] =%"
+ MAX_COOKIE_LINE_TXT "[^;\r\n]",
+ name, what)) {
+ /* Use strstore() below to properly deal with received cookie
+ headers that have the same string property set more than once,
+ and then we use the last one. */
+ const char *whatptr;
+ bool done = FALSE;
+ bool sep;
+ size_t len=strlen(what);
+ const char *endofn = &ptr[ strlen(name) ];
+
+ /* skip trailing spaces in name */
+ while(*endofn && ISBLANK(*endofn))
+ endofn++;
+
+ /* name ends with a '=' ? */
+ sep = (*endofn == '=')?TRUE:FALSE;
+
+ /* Strip off trailing whitespace from the 'what' */
+ while(len && ISBLANK(what[len-1])) {
+ what[len-1]=0;
+ len--;
+ }
+
+ /* Skip leading whitespace from the 'what' */
+ whatptr=what;
+ while(*whatptr && ISBLANK(*whatptr))
+ whatptr++;
+
+ if(!len) {
+ /* this was a "<name>=" with no content, and we must allow
+ 'secure' and 'httponly' specified this weirdly */
+ done = TRUE;
+ if(Curl_raw_equal("secure", name))
+ co->secure = TRUE;
+ else if(Curl_raw_equal("httponly", name))
+ co->httponly = TRUE;
+ else if(sep)
+ /* there was a '=' so we're not done parsing this field */
+ done = FALSE;
+ }
+ if(done)
+ ;
+ else if(Curl_raw_equal("path", name)) {
+ strstore(&co->path, whatptr);
+ if(!co->path) {
+ badcookie = TRUE; /* out of memory bad */
+ break;
+ }
+ co->spath = sanitize_cookie_path(co->path);
+ if(!co->spath) {
+ badcookie = TRUE; /* out of memory bad */
+ break;
+ }
+ }
+ else if(Curl_raw_equal("domain", name)) {
+ bool is_ip;
+ const char *dotp;
+
+ /* Now, we make sure that our host is within the given domain,
+ or the given domain is not valid and thus cannot be set. */
+
+ if('.' == whatptr[0])
+ whatptr++; /* ignore preceding dot */
+
+ is_ip = isip(domain ? domain : whatptr);
+
+ /* check for more dots */
+ dotp = strchr(whatptr, '.');
+ if(!dotp)
+ domain=":";
+
+ if(!domain
+ || (is_ip && !strcmp(whatptr, domain))
+ || (!is_ip && tailmatch(whatptr, domain))) {
+ strstore(&co->domain, whatptr);
+ if(!co->domain) {
+ badcookie = TRUE;
+ break;
+ }
+ if(!is_ip)
+ co->tailmatch=TRUE; /* we always do that if the domain name was
+ given */
+ }
+ else {
+ /* we did not get a tailmatch and then the attempted set domain
+ is not a domain to which the current host belongs. Mark as
+ bad. */
+ badcookie=TRUE;
+ infof(data, "skipped cookie with bad tailmatch domain: %s\n",
+ whatptr);
+ }
+ }
+ else if(Curl_raw_equal("version", name)) {
+ strstore(&co->version, whatptr);
+ if(!co->version) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ else if(Curl_raw_equal("max-age", name)) {
+ /* Defined in RFC2109:
+
+ Optional. The Max-Age attribute defines the lifetime of the
+ cookie, in seconds. The delta-seconds value is a decimal non-
+ negative integer. After delta-seconds seconds elapse, the
+ client should discard the cookie. A value of zero means the
+ cookie should be discarded immediately.
+
+ */
+ strstore(&co->maxage, whatptr);
+ if(!co->maxage) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ else if(Curl_raw_equal("expires", name)) {
+ strstore(&co->expirestr, whatptr);
+ if(!co->expirestr) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ else if(!co->name) {
+ co->name = strdup(name);
+ co->value = strdup(whatptr);
+ if(!co->name || !co->value) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ /*
+ else this is the second (or more) name we don't know
+ about! */
+ }
+ else {
+ /* this is an "illegal" <what>=<this> pair */
+ }
+
+ if(!semiptr || !*semiptr) {
+ /* we already know there are no more cookies */
+ semiptr = NULL;
+ continue;
+ }
+
+ ptr=semiptr+1;
+ while(*ptr && ISBLANK(*ptr))
+ ptr++;
+ semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
+
+ if(!semiptr && *ptr)
+ /* There are no more semicolons, but there's a final name=value pair
+ coming up */
+ semiptr=strchr(ptr, '\0');
+ } while(semiptr);
+
+ if(co->maxage) {
+ co->expires =
+ curlx_strtoofft((*co->maxage=='\"')?
+ &co->maxage[1]:&co->maxage[0], NULL, 10);
+ if(CURL_OFF_T_MAX - now < co->expires)
+ /* avoid overflow */
+ co->expires = CURL_OFF_T_MAX;
+ else
+ co->expires += now;
+ }
+ else if(co->expirestr) {
+ /* Note that if the date couldn't get parsed for whatever reason,
+ the cookie will be treated as a session cookie */
+ co->expires = curl_getdate(co->expirestr, NULL);
+
+ /* Session cookies have expires set to 0 so if we get that back
+ from the date parser let's add a second to make it a
+ non-session cookie */
+ if(co->expires == 0)
+ co->expires = 1;
+ else if(co->expires < 0)
+ co->expires = 0;
+ }
+
+ if(!badcookie && !co->domain) {
+ if(domain) {
+ /* no domain was given in the header line, set the default */
+ co->domain=strdup(domain);
+ if(!co->domain)
+ badcookie = TRUE;
+ }
+ }
+
+ if(!badcookie && !co->path && path) {
+ /* No path was given in the header line, set the default.
+ Note that the passed-in path to this function MAY have a '?' and
+ following part that MUST not be stored as part of the path. */
+ char *queryp = strchr(path, '?');
+
+ /* queryp is where the interesting part of the path ends, so now we
+ want to the find the last */
+ char *endslash;
+ if(!queryp)
+ endslash = strrchr(path, '/');
+ else
+ endslash = memrchr(path, '/', (size_t)(queryp - path));
+ if(endslash) {
+ size_t pathlen = (size_t)(endslash-path+1); /* include ending slash */
+ co->path=malloc(pathlen+1); /* one extra for the zero byte */
+ if(co->path) {
+ memcpy(co->path, path, pathlen);
+ co->path[pathlen]=0; /* zero terminate */
+ co->spath = sanitize_cookie_path(co->path);
+ if(!co->spath)
+ badcookie = TRUE; /* out of memory bad */
+ }
+ else
+ badcookie = TRUE;
+ }
+ }
+
+ free(what);
+
+ if(badcookie || !co->name) {
+ /* we didn't get a cookie name or a bad one,
+ this is an illegal line, bail out */
+ freecookie(co);
+ return NULL;
+ }
+
+ }
+ else {
+ /* This line is NOT a HTTP header style line, we do offer support for
+ reading the odd netscape cookies-file format here */
+ char *ptr;
+ char *firstptr;
+ char *tok_buf=NULL;
+ int fields;
+
+ /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
+ marked with httpOnly after the domain name are not accessible
+ from javascripts, but since curl does not operate at javascript
+ level, we include them anyway. In Firefox's cookie files, these
+ lines are preceded with #HttpOnly_ and then everything is
+ as usual, so we skip 10 characters of the line..
+ */
+ if(strncmp(lineptr, "#HttpOnly_", 10) == 0) {
+ lineptr += 10;
+ co->httponly = TRUE;
+ }
+
+ if(lineptr[0]=='#') {
+ /* don't even try the comments */
+ free(co);
+ return NULL;
+ }
+ /* strip off the possible end-of-line characters */
+ ptr=strchr(lineptr, '\r');
+ if(ptr)
+ *ptr=0; /* clear it */
+ ptr=strchr(lineptr, '\n');
+ if(ptr)
+ *ptr=0; /* clear it */
+
+ firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
+
+ /* Now loop through the fields and init the struct we already have
+ allocated */
+ for(ptr=firstptr, fields=0; ptr && !badcookie;
+ ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
+ switch(fields) {
+ case 0:
+ if(ptr[0]=='.') /* skip preceding dots */
+ ptr++;
+ co->domain = strdup(ptr);
+ if(!co->domain)
+ badcookie = TRUE;
+ break;
+ case 1:
+ /* This field got its explanation on the 23rd of May 2001 by
+ Andr�s Garc�a:
+
+ flag: A TRUE/FALSE value indicating if all machines within a given
+ domain can access the variable. This value is set automatically by
+ the browser, depending on the value you set for the domain.
+
+ As far as I can see, it is set to true when the cookie says
+ .domain.com and to false when the domain is complete www.domain.com
+ */
+ co->tailmatch = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
+ break;
+ case 2:
+ /* It turns out, that sometimes the file format allows the path
+ field to remain not filled in, we try to detect this and work
+ around it! Andr�s Garc�a made us aware of this... */
+ if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
+ /* only if the path doesn't look like a boolean option! */
+ co->path = strdup(ptr);
+ if(!co->path)
+ badcookie = TRUE;
+ else {
+ co->spath = sanitize_cookie_path(co->path);
+ if(!co->spath) {
+ badcookie = TRUE; /* out of memory bad */
+ }
+ }
+ break;
+ }
+ /* this doesn't look like a path, make one up! */
+ co->path = strdup("/");
+ if(!co->path)
+ badcookie = TRUE;
+ co->spath = strdup("/");
+ if(!co->spath)
+ badcookie = TRUE;
+ fields++; /* add a field and fall down to secure */
+ /* FALLTHROUGH */
+ case 3:
+ co->secure = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
+ break;
+ case 4:
+ co->expires = curlx_strtoofft(ptr, NULL, 10);
+ break;
+ case 5:
+ co->name = strdup(ptr);
+ if(!co->name)
+ badcookie = TRUE;
+ break;
+ case 6:
+ co->value = strdup(ptr);
+ if(!co->value)
+ badcookie = TRUE;
+ break;
+ }
+ }
+ if(6 == fields) {
+ /* we got a cookie with blank contents, fix it */
+ co->value = strdup("");
+ if(!co->value)
+ badcookie = TRUE;
+ else
+ fields++;
+ }
+
+ if(!badcookie && (7 != fields))
+ /* we did not find the sufficient number of fields */
+ badcookie = TRUE;
+
+ if(badcookie) {
+ freecookie(co);
+ return NULL;
+ }
+
+ }
+
+ if(!c->running && /* read from a file */
+ c->newsession && /* clean session cookies */
+ !co->expires) { /* this is a session cookie since it doesn't expire! */
+ freecookie(co);
+ return NULL;
+ }
+
+ co->livecookie = c->running;
+
+ /* now, we have parsed the incoming line, we must now check if this
+ superceeds an already existing cookie, which it may if the previous have
+ the same domain and path as this */
+
+ /* at first, remove expired cookies */
+ remove_expired(c);
+
+ clist = c->cookies;
+ replace_old = FALSE;
+ while(clist) {
+ if(Curl_raw_equal(clist->name, co->name)) {
+ /* the names are identical */
+
+ if(clist->domain && co->domain) {
+ if(Curl_raw_equal(clist->domain, co->domain))
+ /* The domains are identical */
+ replace_old=TRUE;
+ }
+ else if(!clist->domain && !co->domain)
+ replace_old = TRUE;
+
+ if(replace_old) {
+ /* the domains were identical */
+
+ if(clist->spath && co->spath) {
+ if(Curl_raw_equal(clist->spath, co->spath)) {
+ replace_old = TRUE;
+ }
+ else
+ replace_old = FALSE;
+ }
+ else if(!clist->spath && !co->spath)
+ replace_old = TRUE;
+ else
+ replace_old = FALSE;
+
+ }
+
+ if(replace_old && !co->livecookie && clist->livecookie) {
+ /* Both cookies matched fine, except that the already present
+ cookie is "live", which means it was set from a header, while
+ the new one isn't "live" and thus only read from a file. We let
+ live cookies stay alive */
+
+ /* Free the newcomer and get out of here! */
+ freecookie(co);
+ return NULL;
+ }
+
+ if(replace_old) {
+ co->next = clist->next; /* get the next-pointer first */
+
+ /* then free all the old pointers */
+ free(clist->name);
+ free(clist->value);
+ free(clist->domain);
+ free(clist->path);
+ free(clist->spath);
+ free(clist->expirestr);
+ free(clist->version);
+ free(clist->maxage);
+
+ *clist = *co; /* then store all the new data */
+
+ free(co); /* free the newly alloced memory */
+ co = clist; /* point to the previous struct instead */
+
+ /* We have replaced a cookie, now skip the rest of the list but
+ make sure the 'lastc' pointer is properly set */
+ do {
+ lastc = clist;
+ clist = clist->next;
+ } while(clist);
+ break;
+ }
+ }
+ lastc = clist;
+ clist = clist->next;
+ }
+
+ if(c->running)
+ /* Only show this when NOT reading the cookies from a file */
+ infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
+ "expire %" CURL_FORMAT_CURL_OFF_T "\n",
+ replace_old?"Replaced":"Added", co->name, co->value,
+ co->domain, co->path, co->expires);
+
+ if(!replace_old) {
+ /* then make the last item point on this new one */
+ if(lastc)
+ lastc->next = co;
+ else
+ c->cookies = co;
+ c->numcookies++; /* one more cookie in the jar */
+ }
+
+ return co;
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_init()
+ *
+ * Inits a cookie struct to read data from a local file. This is always
+ * called before any cookies are set. File may be NULL.
+ *
+ * If 'newsession' is TRUE, discard all "session cookies" on read from file.
+ *
+ * Returns NULL on out of memory. Invalid cookies are ignored.
+ ****************************************************************************/
+CURL_STATIC struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
+ const char *file,
+ struct CookieInfo *inc,
+ bool newsession)
+{
+ struct CookieInfo *c;
+ FILE *fp = NULL;
+ bool fromfile=TRUE;
+ char *line = NULL;
+
+ if(NULL == inc) {
+ /* we didn't get a struct, create one */
+ c = calloc(1, sizeof(struct CookieInfo));
+ if(!c)
+ return NULL; /* failed to get memory */
+ c->filename = strdup(file?file:"none"); /* copy the name just in case */
+ if(!c->filename)
+ goto fail; /* failed to get memory */
+ }
+ else {
+ /* we got an already existing one, use that */
+ c = inc;
+ }
+ c->running = FALSE; /* this is not running, this is init */
+
+ if(file && strequal(file, "-")) {
+ fp = stdin;
+ fromfile=FALSE;
+ }
+ else if(file && !*file) {
+ /* points to a "" string */
+ fp = NULL;
+ }
+ else
+ fp = file?fopen(file, "r"):NULL;
+
+ c->newsession = newsession; /* new session? */
+
+ if(fp) {
+ char *lineptr;
+ bool headerline;
+
+ line = malloc(MAX_COOKIE_LINE);
+ if(!line)
+ goto fail;
+ while(fgets(line, MAX_COOKIE_LINE, fp)) {
+ if(checkprefix("Set-Cookie:", line)) {
+ /* This is a cookie line, get it! */
+ lineptr=&line[11];
+ headerline=TRUE;
+ }
+ else {
+ lineptr=line;
+ headerline=FALSE;
+ }
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
+
+ Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
+ }
+ free(line); /* free the line buffer */
+
+ if(fromfile)
+ fclose(fp);
+ }
+
+ c->running = TRUE; /* now, we're running */
+
+ return c;
+
+fail:
+ free(line);
+ if(!inc)
+ /* Only clean up if we allocated it here, as the original could still be in
+ * use by a share handle */
+ Curl_cookie_cleanup(c);
+ if(fromfile && fp)
+ fclose(fp);
+ return NULL; /* out of memory */
+}
+
+/* sort this so that the longest path gets before the shorter path */
+static int cookie_sort(const void *p1, const void *p2)
+{
+ struct Cookie *c1 = *(struct Cookie **)p1;
+ struct Cookie *c2 = *(struct Cookie **)p2;
+ size_t l1, l2;
+
+ /* 1 - compare cookie path lengths */
+ l1 = c1->path ? strlen(c1->path) : 0;
+ l2 = c2->path ? strlen(c2->path) : 0;
+
+ if(l1 != l2)
+ return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
+
+ /* 2 - compare cookie domain lengths */
+ l1 = c1->domain ? strlen(c1->domain) : 0;
+ l2 = c2->domain ? strlen(c2->domain) : 0;
+
+ if(l1 != l2)
+ return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
+
+ /* 3 - compare cookie names */
+ if(c1->name && c2->name)
+ return strcmp(c1->name, c2->name);
+
+ /* sorry, can't be more deterministic */
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_getlist()
+ *
+ * For a given host and path, return a linked list of cookies that the
+ * client should send to the server if used now. The secure boolean informs
+ * the cookie if a secure connection is achieved or not.
+ *
+ * It shall only return cookies that haven't expired.
+ *
+ ****************************************************************************/
+
+CURL_STATIC struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
+ const char *host, const char *path,
+ bool secure)
+{
+ struct Cookie *newco;
+ struct Cookie *co;
+ time_t now = time(NULL);
+ struct Cookie *mainco=NULL;
+ size_t matches = 0;
+ bool is_ip;
+
+ if(!c || !c->cookies)
+ return NULL; /* no cookie struct or no cookies in the struct */
+
+ /* at first, remove expired cookies */
+ remove_expired(c);
+
+ /* check if host is an IP(v4|v6) address */
+ is_ip = isip(host);
+
+ co = c->cookies;
+
+ while(co) {
+ /* only process this cookie if it is not expired or had no expire
+ date AND that if the cookie requires we're secure we must only
+ continue if we are! */
+ if((!co->expires || (co->expires > now)) &&
+ (co->secure?secure:TRUE)) {
+
+ /* now check if the domain is correct */
+ if(!co->domain ||
+ (co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
+ ((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) {
+ /* the right part of the host matches the domain stuff in the
+ cookie data */
+
+ /* now check the left part of the path with the cookies path
+ requirement */
+ if(!co->spath || pathmatch(co->spath, path) ) {
+
+ /* and now, we know this is a match and we should create an
+ entry for the return-linked-list */
+
+ newco = malloc(sizeof(struct Cookie));
+ if(newco) {
+ /* first, copy the whole source cookie: */
+ memcpy(newco, co, sizeof(struct Cookie));
+
+ /* then modify our next */
+ newco->next = mainco;
+
+ /* point the main to us */
+ mainco = newco;
+
+ matches++;
+ }
+ else {
+ fail:
+ /* failure, clear up the allocated chain and return NULL */
+ while(mainco) {
+ co = mainco->next;
+ free(mainco);
+ mainco = co;
+ }
+
+ return NULL;
+ }
+ }
+ }
+ }
+ co = co->next;
+ }
+
+ if(matches) {
+ /* Now we need to make sure that if there is a name appearing more than
+ once, the longest specified path version comes first. To make this
+ the swiftest way, we just sort them all based on path length. */
+ struct Cookie **array;
+ size_t i;
+
+ /* alloc an array and store all cookie pointers */
+ array = malloc(sizeof(struct Cookie *) * matches);
+ if(!array)
+ goto fail;
+
+ co = mainco;
+
+ for(i=0; co; co = co->next)
+ array[i++] = co;
+
+ /* now sort the cookie pointers in path length order */
+ qsort(array, matches, sizeof(struct Cookie *), cookie_sort);
+
+ /* remake the linked list order according to the new order */
+
+ mainco = array[0]; /* start here */
+ for(i=0; i<matches-1; i++)
+ array[i]->next = array[i+1];
+ array[matches-1]->next = NULL; /* terminate the list */
+
+ free(array); /* remove the temporary data again */
+ }
+
+ return mainco; /* return the new list */
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_clearall()
+ *
+ * Clear all existing cookies and reset the counter.
+ *
+ ****************************************************************************/
+CURL_STATIC void Curl_cookie_clearall(struct CookieInfo *cookies)
+{
+ if(cookies) {
+ Curl_cookie_freelist(cookies->cookies, TRUE);
+ cookies->cookies = NULL;
+ cookies->numcookies = 0;
+ }
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_freelist()
+ *
+ * Free a list of cookies previously returned by Curl_cookie_getlist();
+ *
+ * The 'cookiestoo' argument tells this function whether to just free the
+ * list or actually also free all cookies within the list as well.
+ *
+ ****************************************************************************/
+
+CURL_STATIC void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo)
+{
+ struct Cookie *next;
+ while(co) {
+ next = co->next;
+ if(cookiestoo)
+ freecookie(co);
+ else
+ free(co); /* we only free the struct since the "members" are all just
+ pointed out in the main cookie list! */
+ co = next;
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * Curl_cookie_clearsess()
+ *
+ * Free all session cookies in the cookies list.
+ *
+ ****************************************************************************/
+CURL_STATIC void Curl_cookie_clearsess(struct CookieInfo *cookies)
+{
+ struct Cookie *first, *curr, *next, *prev = NULL;
+
+ if(!cookies || !cookies->cookies)
+ return;
+
+ first = curr = prev = cookies->cookies;
+
+ for(; curr; curr = next) {
+ next = curr->next;
+ if(!curr->expires) {
+ if(first == curr)
+ first = next;
+
+ if(prev == curr)
+ prev = next;
+ else
+ prev->next = next;
+
+ freecookie(curr);
+ cookies->numcookies--;
+ }
+ else
+ prev = curr;
+ }
+
+ cookies->cookies = first;
+}
+
+
+/*****************************************************************************
+ *
+ * Curl_cookie_cleanup()
+ *
+ * Free a "cookie object" previous created with Curl_cookie_init().
+ *
+ ****************************************************************************/
+CURL_STATIC void Curl_cookie_cleanup(struct CookieInfo *c)
+{
+ if(c) {
+ free(c->filename);
+ Curl_cookie_freelist(c->cookies, TRUE);
+ free(c); /* free the base struct as well */
+ }
+}
+
+/* get_netscape_format()
+ *
+ * Formats a string for Netscape output file, w/o a newline at the end.
+ *
+ * Function returns a char * to a formatted line. Has to be free()d
+*/
+static char *get_netscape_format(const struct Cookie *co)
+{
+ return aprintf(
+ "%s" /* httponly preamble */
+ "%s%s\t" /* domain */
+ "%s\t" /* tailmatch */
+ "%s\t" /* path */
+ "%s\t" /* secure */
+ "%" CURL_FORMAT_CURL_OFF_T "\t" /* expires */
+ "%s\t" /* name */
+ "%s", /* value */
+ co->httponly?"#HttpOnly_":"",
+ /* Make sure all domains are prefixed with a dot if they allow
+ tailmatching. This is Mozilla-style. */
+ (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
+ co->domain?co->domain:"unknown",
+ co->tailmatch?"TRUE":"FALSE",
+ co->path?co->path:"/",
+ co->secure?"TRUE":"FALSE",
+ co->expires,
+ co->name,
+ co->value?co->value:"");
+}
+
+/*
+ * cookie_output()
+ *
+ * Writes all internally known cookies to the specified file. Specify
+ * "-" as file name to write to stdout.
+ *
+ * The function returns non-zero on write failure.
+ */
+static int cookie_output(struct CookieInfo *c, const char *dumphere)
+{
+ struct Cookie *co;
+ FILE *out;
+ bool use_stdout=FALSE;
+
+ if((NULL == c) || (0 == c->numcookies))
+ /* If there are no known cookies, we don't write or even create any
+ destination file */
+ return 0;
+
+ /* at first, remove expired cookies */
+ remove_expired(c);
+
+ if(strequal("-", dumphere)) {
+ /* use stdout */
+ out = stdout;
+ use_stdout=TRUE;
+ }
+ else {
+ out = fopen(dumphere, "w");
+ if(!out)
+ return 1; /* failure */
+ }
+
+ if(c) {
+ char *format_ptr;
+
+ fputs("# Netscape HTTP Cookie File\n"
+ "# http://curl.haxx.se/docs/http-cookies.html\n"
+ "# This file was generated by libcurl! Edit at your own risk.\n\n",
+ out);
+ co = c->cookies;
+
+ while(co) {
+ format_ptr = get_netscape_format(co);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
+ co=co->next;
+ }
+ }
+
+ if(!use_stdout)
+ fclose(out);
+
+ return 0;
+}
+
+CURL_STATIC struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
+{
+ struct curl_slist *list = NULL;
+ struct curl_slist *beg;
+ struct Cookie *c;
+ char *line;
+
+ if((data->cookies == NULL) ||
+ (data->cookies->numcookies == 0))
+ return NULL;
+
+ c = data->cookies->cookies;
+
+ while(c) {
+ /* fill the list with _all_ the cookies we know */
+ line = get_netscape_format(c);
+ if(!line) {
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ beg = Curl_slist_append_nodup(list, line);
+ if(!beg) {
+ free(line);
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ list = beg;
+ c = c->next;
+ }
+
+ return list;
+}
+
+CURL_STATIC void Curl_flush_cookies(struct SessionHandle *data, int cleanup)
+{
+ if(data->set.str[STRING_COOKIEJAR]) {
+ if(data->change.cookielist) {
+ /* If there is a list of cookie files to read, do it first so that
+ we have all the told files read before we write the new jar.
+ Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
+ Curl_cookie_loadfiles(data);
+ }
+
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+
+ /* if we have a destination file for all the cookies to get dumped to */
+ if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
+ infof(data, "WARNING: failed to save cookies in %s\n",
+ data->set.str[STRING_COOKIEJAR]);
+ }
+ else {
+ if(cleanup && data->change.cookielist) {
+ /* since nothing is written, we can just free the list of cookie file
+ names */
+ curl_slist_free_all(data->change.cookielist); /* clean up list */
+ data->change.cookielist = NULL;
+ }
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ }
+
+ if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
+ Curl_cookie_cleanup(data->cookies);
+ }
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+}
+
+#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */
diff --git a/libcurl/src/lib/cookie.h b/libcurl/src/lib/cookie.h
new file mode 100644
index 0000000..bc60ba4
--- /dev/null
+++ b/libcurl/src/lib/cookie.h
@@ -0,0 +1,104 @@
+#ifndef HEADER_CURL_COOKIE_H
+#define HEADER_CURL_COOKIE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+struct Cookie {
+ struct Cookie *next; /* next in the chain */
+ char *name; /* <this> = value */
+ char *value; /* name = <this> */
+ char *path; /* path = <this> which is in Set-Cookie: */
+ char *spath; /* sanitized cookie path */
+ char *domain; /* domain = <this> */
+ curl_off_t expires; /* expires = <this> */
+ char *expirestr; /* the plain text version */
+ bool tailmatch; /* weather we do tail-matchning of the domain name */
+
+ /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
+ char *version; /* Version = <value> */
+ char *maxage; /* Max-Age = <value> */
+
+ bool secure; /* whether the 'secure' keyword was used */
+ bool livecookie; /* updated from a server, not a stored file */
+ bool httponly; /* true if the httponly directive is present */
+};
+
+struct CookieInfo {
+ /* linked list of cookies we know of */
+ struct Cookie *cookies;
+
+ char *filename; /* file we read from/write to */
+ bool running; /* state info, for cookie adding information */
+ long numcookies; /* number of cookies in the "jar" */
+ bool newsession; /* new session, discard session cookies on load */
+};
+
+/* This is the maximum line length we accept for a cookie line. RFC 2109
+ section 6.3 says:
+
+ "at least 4096 bytes per cookie (as measured by the size of the characters
+ that comprise the cookie non-terminal in the syntax description of the
+ Set-Cookie header)"
+
+*/
+#define MAX_COOKIE_LINE 5000
+#define MAX_COOKIE_LINE_TXT "4999"
+
+/* This is the maximum length of a cookie name we deal with: */
+#define MAX_NAME 1024
+#define MAX_NAME_TXT "1023"
+
+struct SessionHandle;
+/*
+ * Add a cookie to the internal list of cookies. The domain and path arguments
+ * are only used if the header boolean is TRUE.
+ */
+
+CURL_STATIC struct Cookie *Curl_cookie_add(struct SessionHandle *data,
+ struct CookieInfo *, bool header, char *lineptr,
+ const char *domain, const char *path);
+
+CURL_STATIC struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
+ const char *, bool);
+CURL_STATIC void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo);
+CURL_STATIC void Curl_cookie_clearall(struct CookieInfo *cookies);
+CURL_STATIC void Curl_cookie_clearsess(struct CookieInfo *cookies);
+
+#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES)
+#define Curl_cookie_list(x) NULL
+#define Curl_cookie_loadfiles(x) Curl_nop_stmt
+#define Curl_cookie_init(x,y,z,w) NULL
+#define Curl_cookie_cleanup(x) Curl_nop_stmt
+#define Curl_flush_cookies(x,y) Curl_nop_stmt
+#else
+CURL_STATIC void Curl_flush_cookies(struct SessionHandle *data, int cleanup);
+CURL_STATIC void Curl_cookie_cleanup(struct CookieInfo *);
+CURL_STATIC struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
+ const char *, struct CookieInfo *, bool);
+CURL_STATIC struct curl_slist *Curl_cookie_list(struct SessionHandle *data);
+CURL_STATIC void Curl_cookie_loadfiles(struct SessionHandle *data);
+#endif
+
+#endif /* HEADER_CURL_COOKIE_H */
diff --git a/libcurl/src/lib/curl_addrinfo.c b/libcurl/src/lib/curl_addrinfo.c
new file mode 100644
index 0000000..e572fdc
--- /dev/null
+++ b/libcurl/src/lib/curl_addrinfo.c
@@ -0,0 +1,558 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+
+#ifdef __VMS
+# include <in.h>
+# include <inet.h>
+#endif
+
+#if defined(NETWARE) && defined(__NOVELL_LIBC__)
+# undef in_addr_t
+# define in_addr_t unsigned long
+#endif
+
+#include "curl_addrinfo.h"
+#include "inet_pton.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Curl_freeaddrinfo()
+ *
+ * This is used to free a linked list of Curl_addrinfo structs along
+ * with all its associated allocated storage. This function should be
+ * called once for each successful call to Curl_getaddrinfo_ex() or to
+ * any function call which actually allocates a Curl_addrinfo struct.
+ */
+
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
+ defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
+ /* workaround icc 9.1 optimizer issue */
+# define vqualifier volatile
+#else
+# define vqualifier
+#endif
+
+CURL_STATIC void
+Curl_freeaddrinfo(Curl_addrinfo *cahead)
+{
+ Curl_addrinfo *vqualifier canext;
+ Curl_addrinfo *ca;
+
+ for(ca = cahead; ca != NULL; ca = canext) {
+ free(ca->ai_addr);
+ free(ca->ai_canonname);
+ canext = ca->ai_next;
+
+ free(ca);
+ }
+}
+
+
+#ifdef HAVE_GETADDRINFO
+/*
+ * Curl_getaddrinfo_ex()
+ *
+ * This is a wrapper function around system's getaddrinfo(), with
+ * the only difference that instead of returning a linked list of
+ * addrinfo structs this one returns a linked list of Curl_addrinfo
+ * ones. The memory allocated by this function *MUST* be free'd with
+ * Curl_freeaddrinfo(). For each successful call to this function
+ * there must be an associated call later to Curl_freeaddrinfo().
+ *
+ * There should be no single call to system's getaddrinfo() in the
+ * whole library, any such call should be 'routed' through this one.
+ */
+
+CURL_STATIC int
+Curl_getaddrinfo_ex(const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ Curl_addrinfo **result)
+{
+ const struct addrinfo *ai;
+ struct addrinfo *aihead;
+ Curl_addrinfo *cafirst = NULL;
+ Curl_addrinfo *calast = NULL;
+ Curl_addrinfo *ca;
+ size_t ss_size;
+ int error;
+
+ *result = NULL; /* assume failure */
+
+ error = getaddrinfo(nodename, servname, hints, &aihead);
+ if(error)
+ return error;
+
+ /* traverse the addrinfo list */
+
+ for(ai = aihead; ai != NULL; ai = ai->ai_next) {
+
+ /* ignore elements with unsupported address family, */
+ /* settle family-specific sockaddr structure size. */
+ if(ai->ai_family == AF_INET)
+ ss_size = sizeof(struct sockaddr_in);
+#ifdef ENABLE_IPV6
+ else if(ai->ai_family == AF_INET6)
+ ss_size = sizeof(struct sockaddr_in6);
+#endif
+ else
+ continue;
+
+ /* ignore elements without required address info */
+ if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0))
+ continue;
+
+ /* ignore elements with bogus address size */
+ if((size_t)ai->ai_addrlen < ss_size)
+ continue;
+
+ if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
+ error = EAI_MEMORY;
+ break;
+ }
+
+ /* copy each structure member individually, member ordering, */
+ /* size, or padding might be different for each platform. */
+
+ ca->ai_flags = ai->ai_flags;
+ ca->ai_family = ai->ai_family;
+ ca->ai_socktype = ai->ai_socktype;
+ ca->ai_protocol = ai->ai_protocol;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
+ ca->ai_addr = NULL;
+ ca->ai_canonname = NULL;
+ ca->ai_next = NULL;
+
+ if((ca->ai_addr = malloc(ss_size)) == NULL) {
+ error = EAI_MEMORY;
+ free(ca);
+ break;
+ }
+ memcpy(ca->ai_addr, ai->ai_addr, ss_size);
+
+ if(ai->ai_canonname != NULL) {
+ if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
+ error = EAI_MEMORY;
+ free(ca->ai_addr);
+ free(ca);
+ break;
+ }
+ }
+
+ /* if the return list is empty, this becomes the first element */
+ if(!cafirst)
+ cafirst = ca;
+
+ /* add this element last in the return list */
+ if(calast)
+ calast->ai_next = ca;
+ calast = ca;
+
+ }
+
+ /* destroy the addrinfo list */
+ if(aihead)
+ freeaddrinfo(aihead);
+
+ /* if we failed, also destroy the Curl_addrinfo list */
+ if(error) {
+ Curl_freeaddrinfo(cafirst);
+ cafirst = NULL;
+ }
+ else if(!cafirst) {
+#ifdef EAI_NONAME
+ /* rfc3493 conformant */
+ error = EAI_NONAME;
+#else
+ /* rfc3493 obsoleted */
+ error = EAI_NODATA;
+#endif
+#ifdef USE_WINSOCK
+ SET_SOCKERRNO(error);
+#endif
+ }
+
+ *result = cafirst;
+
+ /* This is not a CURLcode */
+ return error;
+}
+#endif /* HAVE_GETADDRINFO */
+
+
+/*
+ * Curl_he2ai()
+ *
+ * This function returns a pointer to the first element of a newly allocated
+ * Curl_addrinfo struct linked list filled with the data of a given hostent.
+ * Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6
+ * stack, but usable also for IPv4, all hosts and environments.
+ *
+ * The memory allocated by this function *MUST* be free'd later on calling
+ * Curl_freeaddrinfo(). For each successful call to this function there
+ * must be an associated call later to Curl_freeaddrinfo().
+ *
+ * Curl_addrinfo defined in "lib/curl_addrinfo.h"
+ *
+ * struct Curl_addrinfo {
+ * int ai_flags;
+ * int ai_family;
+ * int ai_socktype;
+ * int ai_protocol;
+ * curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
+ * char *ai_canonname;
+ * struct sockaddr *ai_addr;
+ * struct Curl_addrinfo *ai_next;
+ * };
+ * typedef struct Curl_addrinfo Curl_addrinfo;
+ *
+ * hostent defined in <netdb.h>
+ *
+ * struct hostent {
+ * char *h_name;
+ * char **h_aliases;
+ * int h_addrtype;
+ * int h_length;
+ * char **h_addr_list;
+ * };
+ *
+ * for backward compatibility:
+ *
+ * #define h_addr h_addr_list[0]
+ */
+
+CURL_STATIC Curl_addrinfo *
+Curl_he2ai(const struct hostent *he, int port)
+{
+ Curl_addrinfo *ai;
+ Curl_addrinfo *prevai = NULL;
+ Curl_addrinfo *firstai = NULL;
+ struct sockaddr_in *addr;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *addr6;
+#endif
+ CURLcode result = CURLE_OK;
+ int i;
+ char *curr;
+
+ if(!he)
+ /* no input == no output! */
+ return NULL;
+
+ DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
+
+ for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) {
+
+ size_t ss_size;
+#ifdef ENABLE_IPV6
+ if(he->h_addrtype == AF_INET6)
+ ss_size = sizeof (struct sockaddr_in6);
+ else
+#endif
+ ss_size = sizeof (struct sockaddr_in);
+
+ if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai);
+ break;
+ }
+ if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai->ai_canonname);
+ free(ai);
+ break;
+ }
+
+ if(!firstai)
+ /* store the pointer we want to return from this function */
+ firstai = ai;
+
+ if(prevai)
+ /* make the previous entry point to this */
+ prevai->ai_next = ai;
+
+ ai->ai_family = he->h_addrtype;
+
+ /* we return all names as STREAM, so when using this address for TFTP
+ the type must be ignored and conn->socktype be used instead! */
+ ai->ai_socktype = SOCK_STREAM;
+
+ ai->ai_addrlen = (curl_socklen_t)ss_size;
+
+ /* leave the rest of the struct filled with zero */
+
+ switch (ai->ai_family) {
+ case AF_INET:
+ addr = (void *)ai->ai_addr; /* storage area for this info */
+
+ memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
+ addr->sin_family = (unsigned short)(he->h_addrtype);
+ addr->sin_port = htons((unsigned short)port);
+ break;
+
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ addr6 = (void *)ai->ai_addr; /* storage area for this info */
+
+ memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
+ addr6->sin6_family = (unsigned short)(he->h_addrtype);
+ addr6->sin6_port = htons((unsigned short)port);
+ break;
+#endif
+ }
+
+ prevai = ai;
+ }
+
+ if(result) {
+ Curl_freeaddrinfo(firstai);
+ firstai = NULL;
+ }
+
+ return firstai;
+}
+
+
+struct namebuff {
+ struct hostent hostentry;
+ union {
+ struct in_addr ina4;
+#ifdef ENABLE_IPV6
+ struct in6_addr ina6;
+#endif
+ } addrentry;
+ char *h_addr_list[2];
+};
+
+
+/*
+ * Curl_ip2addr()
+ *
+ * This function takes an internet address, in binary form, as input parameter
+ * along with its address family and the string version of the address, and it
+ * returns a Curl_addrinfo chain filled in correctly with information for the
+ * given address/host
+ */
+
+CURL_STATIC Curl_addrinfo *
+Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
+{
+ Curl_addrinfo *ai;
+
+#if defined(__VMS) && \
+ defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
+#pragma pointer_size save
+#pragma pointer_size short
+#pragma message disable PTRMISMATCH
+#endif
+
+ struct hostent *h;
+ struct namebuff *buf;
+ char *addrentry;
+ char *hoststr;
+ size_t addrsize;
+
+ DEBUGASSERT(inaddr && hostname);
+
+ buf = malloc(sizeof(struct namebuff));
+ if(!buf)
+ return NULL;
+
+ hoststr = strdup(hostname);
+ if(!hoststr) {
+ free(buf);
+ return NULL;
+ }
+
+ switch(af) {
+ case AF_INET:
+ addrsize = sizeof(struct in_addr);
+ addrentry = (void *)&buf->addrentry.ina4;
+ memcpy(addrentry, inaddr, sizeof(struct in_addr));
+ break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ addrsize = sizeof(struct in6_addr);
+ addrentry = (void *)&buf->addrentry.ina6;
+ memcpy(addrentry, inaddr, sizeof(struct in6_addr));
+ break;
+#endif
+ default:
+ free(hoststr);
+ free(buf);
+ return NULL;
+ }
+
+ h = &buf->hostentry;
+ h->h_name = hoststr;
+ h->h_aliases = NULL;
+ h->h_addrtype = (short)af;
+ h->h_length = (short)addrsize;
+ h->h_addr_list = &buf->h_addr_list[0];
+ h->h_addr_list[0] = addrentry;
+ h->h_addr_list[1] = NULL; /* terminate list of entries */
+
+#if defined(__VMS) && \
+ defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
+#pragma pointer_size restore
+#pragma message enable PTRMISMATCH
+#endif
+
+ ai = Curl_he2ai(h, port);
+
+ free(hoststr);
+ free(buf);
+
+ return ai;
+}
+
+/*
+ * Given an IPv4 or IPv6 dotted string address, this converts it to a proper
+ * allocated Curl_addrinfo struct and returns it.
+ */
+CURL_STATIC Curl_addrinfo *Curl_str2addr(char *address, int port)
+{
+ struct in_addr in;
+ if(Curl_inet_pton(AF_INET, address, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, address, port);
+#ifdef ENABLE_IPV6
+ else {
+ struct in6_addr in6;
+ if(Curl_inet_pton(AF_INET6, address, &in6) > 0)
+ /* This is a dotted IPv6 address ::1-style */
+ return Curl_ip2addr(AF_INET6, &in6, address, port);
+ }
+#endif
+ return NULL; /* bad input format */
+}
+
+#ifdef USE_UNIX_SOCKETS
+/**
+ * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo
+ * struct initialized with this path.
+ */
+CURL_STATIC Curl_addrinfo *Curl_unix2addr(const char *path)
+{
+ Curl_addrinfo *ai;
+ struct sockaddr_un *sa_un;
+ size_t path_len;
+
+ ai = calloc(1, sizeof(Curl_addrinfo));
+ if(!ai)
+ return NULL;
+ if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) {
+ free(ai);
+ return NULL;
+ }
+ /* sun_path must be able to store the NUL-terminated path */
+ path_len = strlen(path);
+ if(path_len >= sizeof(sa_un->sun_path)) {
+ free(ai->ai_addr);
+ free(ai);
+ return NULL;
+ }
+
+ ai->ai_family = AF_UNIX;
+ ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */
+ ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un);
+ sa_un = (void *) ai->ai_addr;
+ sa_un->sun_family = AF_UNIX;
+ memcpy(sa_un->sun_path, path, path_len + 1); /* copy NUL byte */
+ return ai;
+}
+#endif
+
+#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
+/*
+ * curl_dofreeaddrinfo()
+ *
+ * This is strictly for memory tracing and are using the same style as the
+ * family otherwise present in memdebug.c. I put these ones here since they
+ * require a bunch of structs I didn't want to include in memdebug.c
+ */
+
+void
+curl_dofreeaddrinfo(struct addrinfo *freethis,
+ int line, const char *source)
+{
+ (freeaddrinfo)(freethis);
+ curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
+ source, line, (void *)freethis);
+}
+#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
+
+
+#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
+/*
+ * curl_dogetaddrinfo()
+ *
+ * This is strictly for memory tracing and are using the same style as the
+ * family otherwise present in memdebug.c. I put these ones here since they
+ * require a bunch of structs I didn't want to include in memdebug.c
+ */
+
+int
+curl_dogetaddrinfo(const char *hostname,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **result,
+ int line, const char *source)
+{
+ int res=(getaddrinfo)(hostname, service, hints, result);
+ if(0 == res)
+ /* success */
+ curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
+ source, line, (void *)*result);
+ else
+ curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
+ source, line);
+ return res;
+}
+#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */
+
diff --git a/libcurl/src/lib/curl_addrinfo.h b/libcurl/src/lib/curl_addrinfo.h
new file mode 100644
index 0000000..5f4f0f9
--- /dev/null
+++ b/libcurl/src/lib/curl_addrinfo.h
@@ -0,0 +1,101 @@
+#ifndef HEADER_CURL_ADDRINFO_H
+#define HEADER_CURL_ADDRINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#ifdef __VMS
+# include <in.h>
+# include <inet.h>
+# include <stdlib.h>
+#endif
+
+
+/*
+ * Curl_addrinfo is our internal struct definition that we use to allow
+ * consistent internal handling of this data. We use this even when the
+ * system provides an addrinfo structure definition. And we use this for
+ * all sorts of IPv4 and IPV6 builds.
+ */
+
+struct Curl_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct Curl_addrinfo *ai_next;
+};
+typedef struct Curl_addrinfo Curl_addrinfo;
+
+CURL_STATIC void
+Curl_freeaddrinfo(Curl_addrinfo *cahead);
+
+#ifdef HAVE_GETADDRINFO
+CURL_STATIC int
+Curl_getaddrinfo_ex(const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ Curl_addrinfo **result);
+#endif
+
+CURL_STATIC Curl_addrinfo *
+Curl_he2ai(const struct hostent *he, int port);
+
+CURL_STATIC Curl_addrinfo *
+Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
+
+CURL_STATIC Curl_addrinfo *Curl_str2addr(char *dotted, int port);
+
+#ifdef USE_UNIX_SOCKETS
+CURL_STATIC Curl_addrinfo *Curl_unix2addr(const char *path);
+#endif
+
+#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
+void
+curl_dofreeaddrinfo(struct addrinfo *freethis,
+ int line, const char *source);
+#endif
+
+#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
+int
+curl_dogetaddrinfo(const char *hostname,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **result,
+ int line, const char *source);
+#endif
+
+#endif /* HEADER_CURL_ADDRINFO_H */
diff --git a/libcurl/src/lib/curl_base64.h b/libcurl/src/lib/curl_base64.h
new file mode 100644
index 0000000..c40b245
--- /dev/null
+++ b/libcurl/src/lib/curl_base64.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_BASE64_H
+#define HEADER_CURL_BASE64_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+CURL_STATIC CURLcode Curl_base64_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen);
+CURL_STATIC CURLcode Curl_base64url_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen);
+
+CURL_STATIC CURLcode Curl_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen);
+
+#endif /* HEADER_CURL_BASE64_H */
diff --git a/libcurl/src/lib/curl_config.h.cmake b/libcurl/src/lib/curl_config.h.cmake
new file mode 100644
index 0000000..f60f79f
--- /dev/null
+++ b/libcurl/src/lib/curl_config.h.cmake
@@ -0,0 +1,952 @@
+/* lib/curl_config.h.in. Generated somehow by cmake. */
+
+/* when building libcurl itself */
+#cmakedefine BUILDING_LIBCURL 1
+
+/* Location of default ca bundle */
+#cmakedefine CURL_CA_BUNDLE ${CURL_CA_BUNDLE}
+
+/* Location of default ca path */
+#cmakedefine CURL_CA_PATH ${CURL_CA_PATH}
+
+/* to disable cookies support */
+#cmakedefine CURL_DISABLE_COOKIES 1
+
+/* to disable cryptographic authentication */
+#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1
+
+/* to disable DICT */
+#cmakedefine CURL_DISABLE_DICT 1
+
+/* to disable FILE */
+#cmakedefine CURL_DISABLE_FILE 1
+
+/* to disable FTP */
+#cmakedefine CURL_DISABLE_FTP 1
+
+/* to disable HTTP */
+#cmakedefine CURL_DISABLE_HTTP 1
+
+/* to disable LDAP */
+#cmakedefine CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#cmakedefine CURL_DISABLE_LDAPS 1
+
+/* to disable proxies */
+#cmakedefine CURL_DISABLE_PROXY 1
+
+/* to disable TELNET */
+#cmakedefine CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+#cmakedefine CURL_DISABLE_TFTP 1
+
+/* to disable verbose strings */
+#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
+
+/* to make a symbol visible */
+#cmakedefine CURL_EXTERN_SYMBOL 1
+/* Ensure using CURL_EXTERN_SYMBOL is possible */
+#ifndef CURL_EXTERN_SYMBOL
+#define CURL_EXTERN_SYMBOL
+#endif
+
+/* Use Windows LDAP implementation */
+#cmakedefine USE_WIN32_LDAP 1
+
+/* when not building a shared library */
+#cmakedefine CURL_STATICLIB 1
+
+/* Set to explicitly specify we don't want to use thread-safe functions */
+#cmakedefine DISABLED_THREADSAFE 1
+
+/* your Entropy Gathering Daemon socket pathname */
+#cmakedefine EGD_SOCKET ${EGD_SOCKET}
+
+/* Define if you want to enable IPv6 support */
+#cmakedefine ENABLE_IPV6 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1}
+
+/* Define to the type of arg 1 for getnameinfo. */
+#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1}
+
+/* Define to the type of arg 2 for getnameinfo. */
+#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2}
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46}
+
+/* Define to the type of arg 7 for getnameinfo. */
+#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7}
+
+/* Specifies the number of arguments to getservbyport_r */
+#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS}
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE}
+
+/* Define to 1 if you have the alarm function. */
+#cmakedefine HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#cmakedefine HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#cmakedefine HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+#cmakedefine HAVE_ARPA_TFTP_H 1
+
+/* Define to 1 if you have the <assert.h> header file. */
+#cmakedefine HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `basename' function. */
+#cmakedefine HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#cmakedefine HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1
+
+/* Define to 1 if you have the `closesocket' function. */
+#cmakedefine HAVE_CLOSESOCKET 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
+/* Define to 1 if you have the <crypto.h> header file. */
+#cmakedefine HAVE_CRYPTO_H 1
+
+/* Define to 1 if you have the <des.h> header file. */
+#cmakedefine HAVE_DES_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#cmakedefine HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#cmakedefine HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+#cmakedefine HAVE_ERR_H 1
+
+/* Define to 1 if you have the fcntl function. */
+#cmakedefine HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#cmakedefine HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#cmakedefine HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#cmakedefine HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#cmakedefine HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#cmakedefine HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+#cmakedefine HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the ftruncate function. */
+#cmakedefine HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#cmakedefine HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#cmakedefine HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#cmakedefine HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+#cmakedefine HAVE_GETHOSTBYADDR_R 1
+
+/* gethostbyaddr_r() takes 5 args */
+#cmakedefine HAVE_GETHOSTBYADDR_R_5 1
+
+/* gethostbyaddr_r() takes 7 args */
+#cmakedefine HAVE_GETHOSTBYADDR_R_7 1
+
+/* gethostbyaddr_r() takes 8 args */
+#cmakedefine HAVE_GETHOSTBYADDR_R_8 1
+
+/* Define to 1 if you have the gethostbyname function. */
+#cmakedefine HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+#cmakedefine HAVE_GETHOSTBYNAME_R 1
+
+/* gethostbyname_r() takes 3 args */
+#cmakedefine HAVE_GETHOSTBYNAME_R_3 1
+
+/* gethostbyname_r() takes 5 args */
+#cmakedefine HAVE_GETHOSTBYNAME_R_5 1
+
+/* gethostbyname_r() takes 6 args */
+#cmakedefine HAVE_GETHOSTBYNAME_R_6 1
+
+/* Define to 1 if you have the gethostname function. */
+#cmakedefine HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+#cmakedefine HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the getnameinfo function. */
+#cmakedefine HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+#cmakedefine HAVE_GETPASS_R 1
+
+/* Define to 1 if you have the `getppid' function. */
+#cmakedefine HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#cmakedefine HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#cmakedefine HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#cmakedefine HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+#cmakedefine HAVE_GETSERVBYPORT_R 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#cmakedefine HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+#cmakedefine HAVE_GLIBC_STRERROR_R 1
+
+/* Define to 1 if you have a working gmtime_r function. */
+#cmakedefine HAVE_GMTIME_R 1
+
+/* if you have the gssapi libraries */
+#cmakedefine HAVE_GSSAPI 1
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+#cmakedefine HAVE_GSSAPI_GSSAPI_GENERIC_H 1
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#cmakedefine HAVE_GSSAPI_GSSAPI_H 1
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H 1
+
+/* if you have the GNU gssapi libraries */
+#cmakedefine HAVE_GSSGNU 1
+
+/* if you have the Heimdal gssapi libraries */
+#cmakedefine HAVE_GSSHEIMDAL 1
+
+/* if you have the MIT gssapi libraries */
+#cmakedefine HAVE_GSSMIT 1
+
+/* Define to 1 if you have the `idna_strerror' function. */
+#cmakedefine HAVE_IDNA_STRERROR 1
+
+/* Define to 1 if you have the `idn_free' function. */
+#cmakedefine HAVE_IDN_FREE 1
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+#cmakedefine HAVE_IDN_FREE_H 1
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#cmakedefine HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#cmakedefine HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+#cmakedefine HAVE_INET_NTOA_R 1
+
+/* inet_ntoa_r() takes 2 args */
+#cmakedefine HAVE_INET_NTOA_R_2 1
+
+/* inet_ntoa_r() takes 3 args */
+#cmakedefine HAVE_INET_NTOA_R_3 1
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#cmakedefine HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#cmakedefine HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#cmakedefine HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+#cmakedefine HAVE_IOCTLSOCKET 1
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+#cmakedefine HAVE_IOCTLSOCKET_CAMEL 1
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+#cmakedefine HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+#cmakedefine HAVE_IOCTLSOCKET_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#cmakedefine HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#cmakedefine HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#cmakedefine HAVE_IO_H 1
+
+/* if you have the Kerberos4 libraries (including -ldes) */
+#cmakedefine HAVE_KRB4 1
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1
+
+/* Define to 1 if you have the <krb.h> header file. */
+#cmakedefine HAVE_KRB_H 1
+
+/* Define to 1 if you have the lber.h header file. */
+#cmakedefine HAVE_LBER_H 1
+
+/* Define to 1 if you have the ldapssl.h header file. */
+#cmakedefine HAVE_LDAPSSL_H 1
+
+/* Define to 1 if you have the ldap.h header file. */
+#cmakedefine HAVE_LDAP_H 1
+
+/* Use LDAPS implementation */
+#cmakedefine HAVE_LDAP_SSL 1
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+#cmakedefine HAVE_LDAP_SSL_H 1
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+#cmakedefine HAVE_LDAP_URL_PARSE 1
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#cmakedefine HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+#cmakedefine HAVE_LIBIDN 1
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#cmakedefine HAVE_LIBRESOLV 1
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+#cmakedefine HAVE_LIBRESOLVE 1
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#cmakedefine HAVE_LIBSOCKET 1
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+#cmakedefine HAVE_LIBSSH2 1
+
+/* Define to 1 if libssh2 provides `libssh2_version'. */
+#cmakedefine HAVE_LIBSSH2_VERSION 1
+
+/* Define to 1 if libssh2 provides `libssh2_init'. */
+#cmakedefine HAVE_LIBSSH2_INIT 1
+
+/* Define to 1 if libssh2 provides `libssh2_exit'. */
+#cmakedefine HAVE_LIBSSH2_EXIT 1
+
+/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */
+#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1
+
+/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */
+#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+#cmakedefine HAVE_LIBSSH2_H 1
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#cmakedefine HAVE_LIBSSL 1
+
+/* if zlib is available */
+#cmakedefine HAVE_LIBZ 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#cmakedefine HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#cmakedefine HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#cmakedefine HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#cmakedefine HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#cmakedefine HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+#cmakedefine HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#cmakedefine HAVE_MSG_NOSIGNAL 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#cmakedefine HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#cmakedefine HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#cmakedefine HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#cmakedefine HAVE_NET_IF_H 1
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+#cmakedefine HAVE_NI_WITHSCOPEID 1
+
+/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */
+#cmakedefine HAVE_OLD_GSSMIT 1
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+#cmakedefine HAVE_OPENSSL_CRYPTO_H 1
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+#cmakedefine HAVE_OPENSSL_ENGINE_H 1
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+#cmakedefine HAVE_OPENSSL_ERR_H 1
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+#cmakedefine HAVE_OPENSSL_PEM_H 1
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+#cmakedefine HAVE_OPENSSL_PKCS12_H 1
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#cmakedefine HAVE_OPENSSL_RSA_H 1
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#cmakedefine HAVE_OPENSSL_SSL_H 1
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+#cmakedefine HAVE_OPENSSL_X509_H 1
+
+/* Define to 1 if you have the <pem.h> header file. */
+#cmakedefine HAVE_PEM_H 1
+
+/* Define to 1 if you have the `perror' function. */
+#cmakedefine HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#cmakedefine HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#cmakedefine HAVE_POLL 1
+
+/* If you have a fine poll */
+#cmakedefine HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#cmakedefine HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#cmakedefine HAVE_POSIX_STRERROR_R 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#cmakedefine HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+#cmakedefine HAVE_RAND_EGD 1
+
+/* Define to 1 if you have the `RAND_screen' function. */
+#cmakedefine HAVE_RAND_SCREEN 1
+
+/* Define to 1 if you have the `RAND_status' function. */
+#cmakedefine HAVE_RAND_STATUS 1
+
+/* Define to 1 if you have the recv function. */
+#cmakedefine HAVE_RECV 1
+
+/* Define to 1 if you have the recvfrom function. */
+#cmakedefine HAVE_RECVFROM 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+#cmakedefine HAVE_RSA_H 1
+
+/* Define to 1 if you have the select function. */
+#cmakedefine HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#cmakedefine HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#cmakedefine HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#cmakedefine HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+#cmakedefine HAVE_SETMODE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#cmakedefine HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#cmakedefine HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#cmakedefine HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#cmakedefine HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#cmakedefine HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+#cmakedefine HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#cmakedefine HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#cmakedefine HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#cmakedefine HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the `socket' function. */
+#cmakedefine HAVE_SOCKET 1
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+#cmakedefine HAVE_SSL_GET_SHUTDOWN 1
+
+/* Define to 1 if you have the <ssl.h> header file. */
+#cmakedefine HAVE_SSL_H 1
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#cmakedefine HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#cmakedefine HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#cmakedefine HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcasestr function. */
+#cmakedefine HAVE_STRCASESTR 1
+
+/* Define to 1 if you have the strcmpi function. */
+#cmakedefine HAVE_STRCMPI 1
+
+/* Define to 1 if you have the strdup function. */
+#cmakedefine HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#cmakedefine HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+#cmakedefine HAVE_STRICMP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H 1
+
+/* Define to 1 if you have the strlcat function. */
+#cmakedefine HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#cmakedefine HAVE_STRLCPY 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#cmakedefine HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+#cmakedefine HAVE_STRNCMPI 1
+
+/* Define to 1 if you have the strnicmp function. */
+#cmakedefine HAVE_STRNICMP 1
+
+/* Define to 1 if you have the <stropts.h> header file. */
+#cmakedefine HAVE_STROPTS_H 1
+
+/* Define to 1 if you have the strstr function. */
+#cmakedefine HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#cmakedefine HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#cmakedefine HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#cmakedefine HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#cmakedefine HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#cmakedefine HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#cmakedefine HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#cmakedefine HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#cmakedefine HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#cmakedefine HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#cmakedefine HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#cmakedefine HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#cmakedefine HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#cmakedefine HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#cmakedefine HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#cmakedefine HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#cmakedefine HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#cmakedefine HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#cmakedefine HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+#cmakedefine HAVE_TLD_H 1
+
+/* Define to 1 if you have the `tld_strerror' function. */
+#cmakedefine HAVE_TLD_STRERROR 1
+
+/* Define to 1 if you have the `uname' function. */
+#cmakedefine HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#cmakedefine HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#cmakedefine HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#cmakedefine HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#cmakedefine HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+#cmakedefine HAVE_WINBER_H 1
+
+/* Define to 1 if you have the windows.h header file. */
+#cmakedefine HAVE_WINDOWS_H 1
+
+/* Define to 1 if you have the winldap.h header file. */
+#cmakedefine HAVE_WINLDAP_H 1
+
+/* Define to 1 if you have the winsock2.h header file. */
+#cmakedefine HAVE_WINSOCK2_H 1
+
+/* Define to 1 if you have the winsock.h header file. */
+#cmakedefine HAVE_WINSOCK_H 1
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#cmakedefine HAVE_WRITABLE_ARGV 1
+
+/* Define to 1 if you have the writev function. */
+#cmakedefine HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+#cmakedefine HAVE_WS2TCPIP_H 1
+
+/* Define to 1 if you have the <x509.h> header file. */
+#cmakedefine HAVE_X509_H 1
+
+/* Define if you have the <process.h> header file. */
+#cmakedefine HAVE_PROCESS_H 1
+
+/* if you have the zlib.h header file */
+#cmakedefine HAVE_ZLIB_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#cmakedefine LT_OBJDIR ${LT_OBJDIR}
+
+/* If you lack a fine basename() prototype */
+#cmakedefine NEED_BASENAME_PROTO 1
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+#cmakedefine NEED_LBER_H 1
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+#cmakedefine NEED_MALLOC_H 1
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+#cmakedefine NEED_REENTRANT 1
+
+/* cpu-machine-OS */
+#cmakedefine OS ${OS}
+
+/* Name of package */
+#cmakedefine PACKAGE ${PACKAGE}
+
+/* Define to the address where bug reports for this package should be sent. */
+#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT}
+
+/* Define to the full name of this package. */
+#cmakedefine PACKAGE_NAME ${PACKAGE_NAME}
+
+/* Define to the full name and version of this package. */
+#cmakedefine PACKAGE_STRING ${PACKAGE_STRING}
+
+/* Define to the one symbol short name of this package. */
+#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME}
+
+/* Define to the version of this package. */
+#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION}
+
+/* a suitable file to read random data from */
+#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
+
+/* Define to the type of arg 1 for recvfrom. */
+#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1}
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2}
+
+/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
+#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1
+
+/* Define to the type of arg 3 for recvfrom. */
+#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3}
+
+/* Define to the type of arg 4 for recvfrom. */
+#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4}
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5}
+
+/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
+#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6}
+
+/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
+#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1
+
+/* Define to the function return type for recvfrom. */
+#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV}
+
+/* Define to the type of arg 1 for recv. */
+#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}
+
+/* Define to the type of arg 2 for recv. */
+#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}
+
+/* Define to the type of arg 3 for recv. */
+#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}
+
+/* Define to the type of arg 4 for recv. */
+#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}
+
+/* Define to the function return type for recv. */
+#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#cmakedefine RETSIGTYPE ${RETSIGTYPE}
+
+/* Define to the type qualifier of arg 5 for select. */
+#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5}
+
+/* Define to the type of arg 1 for select. */
+#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1}
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234}
+
+/* Define to the type of arg 5 for select. */
+#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5}
+
+/* Define to the function return type for select. */
+#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV}
+
+/* Define to the type qualifier of arg 2 for send. */
+#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}
+
+/* Define to the type of arg 1 for send. */
+#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}
+
+/* Define to the type of arg 2 for send. */
+#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}
+
+/* Define to the type of arg 3 for send. */
+#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}
+
+/* Define to the type of arg 4 for send. */
+#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}
+
+/* Define to the function return type for send. */
+#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV}
+
+/* The size of `int', as computed by sizeof. */
+#cmakedefine SIZEOF_INT ${SIZEOF_INT}
+
+/* The size of `short', as computed by sizeof. */
+#cmakedefine SIZEOF_SHORT ${SIZEOF_SHORT}
+
+/* The size of `long', as computed by sizeof. */
+#cmakedefine SIZEOF_LONG ${SIZEOF_LONG}
+
+/* The size of `off_t', as computed by sizeof. */
+#cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T}
+
+/* The size of `size_t', as computed by sizeof. */
+#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}
+
+/* The size of `time_t', as computed by sizeof. */
+#cmakedefine SIZEOF_TIME_T ${SIZEOF_TIME_T}
+
+/* The size of `void*', as computed by sizeof. */
+#cmakedefine SIZEOF_VOIDP ${SIZEOF_VOIDP}
+
+/* Define to 1 if you have the ANSI C header files. */
+#cmakedefine STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3}
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#cmakedefine TIME_WITH_SYS_TIME 1
+
+/* Define if you want to enable c-ares support */
+#cmakedefine USE_ARES 1
+
+/* Define to disable non-blocking sockets. */
+#cmakedefine USE_BLOCKING_SOCKETS 1
+
+/* if GnuTLS is enabled */
+#cmakedefine USE_GNUTLS 1
+
+/* if PolarSSL is enabled */
+#cmakedefine USE_POLARSSL 1
+
+/* if libSSH2 is in use */
+#cmakedefine USE_LIBSSH2 1
+
+/* If you want to build curl with the built-in manual */
+#cmakedefine USE_MANUAL 1
+
+/* if NSS is enabled */
+#cmakedefine USE_NSS 1
+
+/* if you want to use OpenLDAP code instead of legacy ldap implementation */
+#cmakedefine USE_OPENLDAP 1
+
+/* if OpenSSL is in use */
+#cmakedefine USE_OPENSSL 1
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+#cmakedefine USE_WIN32_LARGE_FILES 1
+
+/* to enable SSPI support */
+#cmakedefine USE_WINDOWS_SSPI 1
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+#cmakedefine USE_YASSLEMUL 1
+
+/* Version number of package */
+#cmakedefine VERSION ${VERSION}
+
+/* Define to avoid automatic inclusion of winsock.h */
+#cmakedefine WIN32_LEAN_AND_MEAN 1
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES ${_LARGE_FILES}
+
+/* define this if you need it to compile thread-safe code */
+#cmakedefine _THREAD_SAFE ${_THREAD_SAFE}
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#cmakedefine const ${const}
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+#cmakedefine in_addr_t ${in_addr_t}
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#cmakedefine size_t ${size_t}
+
+/* the signed version of size_t */
+#cmakedefine ssize_t ${ssize_t}
diff --git a/libcurl/src/lib/curl_config.h.in b/libcurl/src/lib/curl_config.h.in
new file mode 100644
index 0000000..feb582e
--- /dev/null
+++ b/libcurl/src/lib/curl_config.h.in
@@ -0,0 +1,1024 @@
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+#undef CURL_CA_BUNDLE
+
+/* Location of default ca path */
+#undef CURL_CA_PATH
+
+/* to disable cookies support */
+#undef CURL_DISABLE_COOKIES
+
+/* to disable cryptographic authentication */
+#undef CURL_DISABLE_CRYPTO_AUTH
+
+/* to disable DICT */
+#undef CURL_DISABLE_DICT
+
+/* to disable FILE */
+#undef CURL_DISABLE_FILE
+
+/* to disable FTP */
+#undef CURL_DISABLE_FTP
+
+/* to disable Gopher */
+#undef CURL_DISABLE_GOPHER
+
+/* to disable HTTP */
+#undef CURL_DISABLE_HTTP
+
+/* to disable IMAP */
+#undef CURL_DISABLE_IMAP
+
+/* to disable LDAP */
+#undef CURL_DISABLE_LDAP
+
+/* to disable LDAPS */
+#undef CURL_DISABLE_LDAPS
+
+/* to disable --libcurl C code generation option */
+#undef CURL_DISABLE_LIBCURL_OPTION
+
+/* to disable POP3 */
+#undef CURL_DISABLE_POP3
+
+/* to disable proxies */
+#undef CURL_DISABLE_PROXY
+
+/* to disable RTSP */
+#undef CURL_DISABLE_RTSP
+
+/* to disable SMB/CIFS */
+#undef CURL_DISABLE_SMB
+
+/* to disable SMTP */
+#undef CURL_DISABLE_SMTP
+
+/* to disable TELNET */
+#undef CURL_DISABLE_TELNET
+
+/* to disable TFTP */
+#undef CURL_DISABLE_TFTP
+
+/* to disable TLS-SRP authentication */
+#undef CURL_DISABLE_TLS_SRP
+
+/* to disable verbose strings */
+#undef CURL_DISABLE_VERBOSE_STRINGS
+
+/* Definition to make a library symbol externally visible. */
+#undef CURL_EXTERN_SYMBOL
+
+/* your Entropy Gathering Daemon socket pathname */
+#undef EGD_SOCKET
+
+/* Define if you want to enable IPv6 support */
+#undef ENABLE_IPV6
+
+/* Define to the type of arg 2 for gethostname. */
+#undef GETHOSTNAME_TYPE_ARG2
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#undef GETNAMEINFO_QUAL_ARG1
+
+/* Define to the type of arg 1 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG1
+
+/* Define to the type of arg 2 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG2
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG46
+
+/* Define to the type of arg 7 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG7
+
+/* Specifies the number of arguments to getservbyport_r */
+#undef GETSERVBYPORT_R_ARGS
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+#undef GETSERVBYPORT_R_BUFSIZE
+
+/* Define to 1 if you have the alarm function. */
+#undef HAVE_ALARM
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+#undef HAVE_ARPA_TFTP_H
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the basename function. */
+#undef HAVE_BASENAME
+
+/* Define to 1 if bool is an available type. */
+#undef HAVE_BOOL_T
+
+/* Define to 1 if using BoringSSL. */
+#undef HAVE_BORINGSSL
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#undef HAVE_CLOCK_GETTIME_MONOTONIC
+
+/* Define to 1 if you have the closesocket function. */
+#undef HAVE_CLOSESOCKET
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+#undef HAVE_CLOSESOCKET_CAMEL
+
+/* Define to 1 if you have the connect function. */
+#undef HAVE_CONNECT
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
+
+/* Define to 1 if you have the <crypto.h> header file. */
+#undef HAVE_CRYPTO_H
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+#undef HAVE_CYASSL_ERROR_SSL_H
+
+/* Define to 1 if you have the <cyassl/options.h> header file. */
+#undef HAVE_CYASSL_OPTIONS_H
+
+/* Define to 1 if you have the `DES_set_odd_parity' function. */
+#undef HAVE_DES_SET_ODD_PARITY
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+#undef HAVE_ENGINE_CLEANUP
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+#undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <err.h> header file. */
+#undef HAVE_ERR_H
+
+/* Define to 1 if you have the fcntl function. */
+#undef HAVE_FCNTL
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#undef HAVE_FCNTL_O_NONBLOCK
+
+/* Define to 1 if you have the fdopen function. */
+#undef HAVE_FDOPEN
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#undef HAVE_FREEADDRINFO
+
+/* Define to 1 if you have the freeifaddrs function. */
+#undef HAVE_FREEIFADDRS
+
+/* Define to 1 if you have the fsetxattr function. */
+#undef HAVE_FSETXATTR
+
+/* fsetxattr() takes 5 args */
+#undef HAVE_FSETXATTR_5
+
+/* fsetxattr() takes 6 args */
+#undef HAVE_FSETXATTR_6
+
+/* Define to 1 if you have the ftruncate function. */
+#undef HAVE_FTRUNCATE
+
+/* Define to 1 if you have the gai_strerror function. */
+#undef HAVE_GAI_STRERROR
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#undef HAVE_GETADDRINFO_THREADSAFE
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#undef HAVE_GETHOSTBYADDR
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* gethostbyaddr_r() takes 5 args */
+#undef HAVE_GETHOSTBYADDR_R_5
+
+/* gethostbyaddr_r() takes 7 args */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* gethostbyaddr_r() takes 8 args */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* Define to 1 if you have the gethostbyname function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the gethostbyname_r function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* gethostbyname_r() takes 3 args */
+#undef HAVE_GETHOSTBYNAME_R_3
+
+/* gethostbyname_r() takes 5 args */
+#undef HAVE_GETHOSTBYNAME_R_5
+
+/* gethostbyname_r() takes 6 args */
+#undef HAVE_GETHOSTBYNAME_R_6
+
+/* Define to 1 if you have the gethostname function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have a working getifaddrs function. */
+#undef HAVE_GETIFADDRS
+
+/* Define to 1 if you have the getnameinfo function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if you have the `getpass_r' function. */
+#undef HAVE_GETPASS_R
+
+/* Define to 1 if you have the `getppid' function. */
+#undef HAVE_GETPPID
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#undef HAVE_GETPROTOBYNAME
+
+/* Define to 1 if you have the `getpwuid' function. */
+#undef HAVE_GETPWUID
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#undef HAVE_GETPWUID_R
+
+/* Define to 1 if you have the `getrlimit' function. */
+#undef HAVE_GETRLIMIT
+
+/* Define to 1 if you have the getservbyport_r function. */
+#undef HAVE_GETSERVBYPORT_R
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+#undef HAVE_GLIBC_STRERROR_R
+
+/* Define to 1 if you have a working gmtime_r function. */
+#undef HAVE_GMTIME_R
+
+/* if you have the function gnutls_srp_verifier */
+#undef HAVE_GNUTLS_SRP
+
+/* if you have GSS-API libraries */
+#undef HAVE_GSSAPI
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_KRB5_H
+
+/* if you have GNU GSS */
+#undef HAVE_GSSGNU
+
+/* if you have Heimdal */
+#undef HAVE_GSSHEIMDAL
+
+/* if you have MIT Kerberos */
+#undef HAVE_GSSMIT
+
+/* Define to 1 if you have the `idna_strerror' function. */
+#undef HAVE_IDNA_STRERROR
+
+/* Define to 1 if you have the `idn_free' function. */
+#undef HAVE_IDN_FREE
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+#undef HAVE_IDN_FREE_H
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#undef HAVE_IF_NAMETOINDEX
+
+/* Define to 1 if you have the `inet_addr' function. */
+#undef HAVE_INET_ADDR
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+#undef HAVE_INET_NTOA_R
+
+/* inet_ntoa_r() takes 2 args */
+#undef HAVE_INET_NTOA_R_2
+
+/* inet_ntoa_r() takes 3 args */
+#undef HAVE_INET_NTOA_R_3
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#undef HAVE_INET_NTOP
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#undef HAVE_INET_PTON
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the ioctl function. */
+#undef HAVE_IOCTL
+
+/* Define to 1 if you have the ioctlsocket function. */
+#undef HAVE_IOCTLSOCKET
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+#undef HAVE_IOCTLSOCKET_CAMEL
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+#undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+#undef HAVE_IOCTLSOCKET_FIONBIO
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#undef HAVE_IOCTL_FIONBIO
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#undef HAVE_IOCTL_SIOCGIFADDR
+
+/* Define to 1 if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define to 1 if you have the lber.h header file. */
+#undef HAVE_LBER_H
+
+/* Define to 1 if you have the ldapssl.h header file. */
+#undef HAVE_LDAPSSL_H
+
+/* Define to 1 if you have the ldap.h header file. */
+#undef HAVE_LDAP_H
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+#undef HAVE_LDAP_INIT_FD
+
+/* Use LDAPS implementation */
+#undef HAVE_LDAP_SSL
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+#undef HAVE_LDAP_SSL_H
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+#undef HAVE_LDAP_URL_PARSE
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+#undef HAVE_LIBIDN
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+#undef HAVE_LIBRESOLVE
+
+/* Define to 1 if using libressl. */
+#undef HAVE_LIBRESSL
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+#undef HAVE_LIBRTMP_RTMP_H
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+#undef HAVE_LIBSSH2
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+#undef HAVE_LIBSSH2_H
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
+/* if zlib is available */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* if your compiler supports LL */
+#undef HAVE_LL
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you have a working localtime_r function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#undef HAVE_LONGLONG
+
+/* Define to 1 if you have the malloc.h header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the memory.h header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the memrchr function or macro. */
+#undef HAVE_MEMRCHR
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#undef HAVE_MSG_NOSIGNAL
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+#undef HAVE_NGHTTP2_NGHTTP2_H
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+#undef HAVE_NI_WITHSCOPEID
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+#undef HAVE_OLD_GSSMIT
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+#undef HAVE_OPENSSL_CRYPTO_H
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+#undef HAVE_OPENSSL_ENGINE_H
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+#undef HAVE_OPENSSL_PEM_H
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+#undef HAVE_OPENSSL_PKCS12_H
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
+/* if you have the function SRP_Calc_client_key */
+#undef HAVE_OPENSSL_SRP
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+#undef HAVE_OPENSSL_X509_H
+
+/* Define to 1 if you have the <pem.h> header file. */
+#undef HAVE_PEM_H
+
+/* Define to 1 if you have the `perror' function. */
+#undef HAVE_PERROR
+
+/* Define to 1 if you have the `pipe' function. */
+#undef HAVE_PIPE
+
+/* Define to 1 if you have a working poll function. */
+#undef HAVE_POLL
+
+/* If you have a fine poll */
+#undef HAVE_POLL_FINE
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#undef HAVE_POSIX_STRERROR_R
+
+/* if you have <pthread.h> */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define to 1 if you have the `RAND_egd' function. */
+#undef HAVE_RAND_EGD
+
+/* Define to 1 if you have the `RAND_screen' function. */
+#undef HAVE_RAND_SCREEN
+
+/* Define to 1 if you have the `RAND_status' function. */
+#undef HAVE_RAND_STATUS
+
+/* Define to 1 if you have the recv function. */
+#undef HAVE_RECV
+
+/* Define to 1 if you have the <rsa.h> header file. */
+#undef HAVE_RSA_H
+
+/* Define to 1 if you have the select function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the send function. */
+#undef HAVE_SEND
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#undef HAVE_SETJMP_H
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the `setmode' function. */
+#undef HAVE_SETMODE
+
+/* Define to 1 if you have the `setrlimit' function. */
+#undef HAVE_SETRLIMIT
+
+/* Define to 1 if you have the setsockopt function. */
+#undef HAVE_SETSOCKOPT
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+#undef HAVE_SETSOCKOPT_SO_NONBLOCK
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define to 1 if you have the sigaction function. */
+#undef HAVE_SIGACTION
+
+/* Define to 1 if you have the siginterrupt function. */
+#undef HAVE_SIGINTERRUPT
+
+/* Define to 1 if you have the signal function. */
+#undef HAVE_SIGNAL
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#undef HAVE_SIGSETJMP
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#undef HAVE_SIG_ATOMIC_T
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+#undef HAVE_SIG_ATOMIC_T_VOLATILE
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+
+/* Define to 1 if you have the socket function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the socketpair function. */
+#undef HAVE_SOCKETPAIR
+
+/* Define to 1 if you have the <socket.h> header file. */
+#undef HAVE_SOCKET_H
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+#undef HAVE_SSLV2_CLIENT_METHOD
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+#undef HAVE_SSL_GET_SHUTDOWN
+
+/* Define to 1 if you have the <ssl.h> header file. */
+#undef HAVE_SSL_H
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the strcasecmp function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the strcmpi function. */
+#undef HAVE_STRCMPI
+
+/* Define to 1 if you have the strdup function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the strerror_r function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the stricmp function. */
+#undef HAVE_STRICMP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the strncasecmp function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the strncmpi function. */
+#undef HAVE_STRNCMPI
+
+/* Define to 1 if you have the strnicmp function. */
+#undef HAVE_STRNICMP
+
+/* Define to 1 if you have the <stropts.h> header file. */
+#undef HAVE_STROPTS_H
+
+/* Define to 1 if you have the strstr function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the strtok_r function. */
+#undef HAVE_STRTOK_R
+
+/* Define to 1 if you have the strtoll function. */
+#undef HAVE_STRTOLL
+
+/* if struct sockaddr_storage is defined */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define to 1 if you have the timeval struct. */
+#undef HAVE_STRUCT_TIMEVAL
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#undef HAVE_SYS_POLL_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#undef HAVE_SYS_UTIME_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#undef HAVE_SYS_XATTR_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <tld.h> header file. */
+#undef HAVE_TLD_H
+
+/* Define to 1 if you have the `tld_strerror' function. */
+#undef HAVE_TLD_STRERROR
+
+/* Define to 1 if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `utime' function. */
+#undef HAVE_UTIME
+
+/* Define to 1 if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#undef HAVE_VARIADIC_MACROS_C99
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#undef HAVE_VARIADIC_MACROS_GCC
+
+/* Define to 1 if you have the winber.h header file. */
+#undef HAVE_WINBER_H
+
+/* Define to 1 if you have the windows.h header file. */
+#undef HAVE_WINDOWS_H
+
+/* Define to 1 if you have the winldap.h header file. */
+#undef HAVE_WINLDAP_H
+
+/* Define to 1 if you have the winsock2.h header file. */
+#undef HAVE_WINSOCK2_H
+
+/* Define to 1 if you have the winsock.h header file. */
+#undef HAVE_WINSOCK_H
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#undef HAVE_WRITABLE_ARGV
+
+/* Define to 1 if you have the writev function. */
+#undef HAVE_WRITEV
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+#undef HAVE_WS2TCPIP_H
+
+/* Define to 1 if you have the <x509.h> header file. */
+#undef HAVE_X509_H
+
+/* if you have the zlib.h header file */
+#undef HAVE_ZLIB_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+#undef NEED_LBER_H
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+#undef NEED_MALLOC_H
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+#undef NEED_MEMORY_H
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+#undef NEED_REENTRANT
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+#undef NEED_THREAD_SAFE
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+#undef NTLM_WB_ENABLED
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+#undef NTLM_WB_FILE
+
+/* cpu-machine-OS */
+#undef OS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* a suitable file to read random data from */
+#undef RANDOM_FILE
+
+/* Define to the type of arg 1 for recv. */
+#undef RECV_TYPE_ARG1
+
+/* Define to the type of arg 2 for recv. */
+#undef RECV_TYPE_ARG2
+
+/* Define to the type of arg 3 for recv. */
+#undef RECV_TYPE_ARG3
+
+/* Define to the type of arg 4 for recv. */
+#undef RECV_TYPE_ARG4
+
+/* Define to the function return type for recv. */
+#undef RECV_TYPE_RETV
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type qualifier of arg 5 for select. */
+#undef SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for select. */
+#undef SELECT_TYPE_ARG5
+
+/* Define to the function return type for select. */
+#undef SELECT_TYPE_RETV
+
+/* Define to the type qualifier of arg 2 for send. */
+#undef SEND_QUAL_ARG2
+
+/* Define to the type of arg 1 for send. */
+#undef SEND_TYPE_ARG1
+
+/* Define to the type of arg 2 for send. */
+#undef SEND_TYPE_ARG2
+
+/* Define to the type of arg 3 for send. */
+#undef SEND_TYPE_ARG3
+
+/* Define to the type of arg 4 for send. */
+#undef SEND_TYPE_ARG4
+
+/* Define to the function return type for send. */
+#undef SEND_TYPE_RETV
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of `off_t', as computed by sizeof. */
+#undef SIZEOF_OFF_T
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
+/* The size of `time_t', as computed by sizeof. */
+#undef SIZEOF_TIME_T
+
+/* The size of `void*', as computed by sizeof. */
+#undef SIZEOF_VOIDP
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to the type of arg 3 for strerror_r. */
+#undef STRERROR_R_TYPE_ARG3
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to enable c-ares support */
+#undef USE_ARES
+
+/* if axTLS is enabled */
+#undef USE_AXTLS
+
+/* if CyaSSL is enabled */
+#undef USE_CYASSL
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+#undef USE_DARWINSSL
+
+/* if GnuTLS is enabled */
+#undef USE_GNUTLS
+
+/* if GnuTLS uses nettle as crypto backend */
+#undef USE_GNUTLS_NETTLE
+
+/* if librtmp is in use */
+#undef USE_LIBRTMP
+
+/* if libSSH2 is in use */
+#undef USE_LIBSSH2
+
+/* If you want to build curl with the built-in manual */
+#undef USE_MANUAL
+
+/* Define to enable metalink support */
+#undef USE_METALINK
+
+/* if nghttp2 is in use */
+#undef USE_NGHTTP2
+
+/* if NSS is enabled */
+#undef USE_NSS
+
+/* Use OpenLDAP-specific code */
+#undef USE_OPENLDAP
+
+/* if OpenSSL is in use */
+#undef USE_OPENSSL
+
+/* if PolarSSL is enabled */
+#undef USE_POLARSSL
+
+/* to enable Windows native SSL/TLS support */
+#undef USE_SCHANNEL
+
+/* if you want POSIX threaded DNS lookup */
+#undef USE_THREADS_POSIX
+
+/* Use TLS-SRP authentication */
+#undef USE_TLS_SRP
+
+/* Use Unix domain sockets */
+#undef USE_UNIX_SOCKETS
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+#undef USE_WIN32_IDN
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+#undef USE_WIN32_LARGE_FILES
+
+/* Use Windows LDAP implementation */
+#undef USE_WIN32_LDAP
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+#undef USE_WIN32_SMALL_FILES
+
+/* to enable SSPI support */
+#undef USE_WINDOWS_SSPI
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 to provide own prototypes. */
+#undef WANT_IDN_PROTOTYPES
+
+/* Define to avoid automatic inclusion of winsock.h */
+#undef WIN32_LEAN_AND_MEAN
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+#undef in_addr_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* the signed version of size_t */
+#undef ssize_t
diff --git a/libcurl/src/lib/curl_des.c b/libcurl/src/lib/curl_des.c
new file mode 100644
index 0000000..42c1df9
--- /dev/null
+++ b/libcurl/src/lib/curl_des.c
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM) && (!defined(USE_OPENSSL) || defined(HAVE_BORINGSSL))
+
+#include "curl_des.h"
+
+/*
+ * Curl_des_set_odd_parity()
+ *
+ * This is used to apply odd parity to the given byte array. It is typically
+ * used by when a cryptography engines doesn't have it's own version.
+ *
+ * The function is a port of the Java based oddParity() function over at:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ *
+ * Parameters:
+ *
+ * bytes [in/out] - The data whose parity bits are to be adjusted for
+ * odd parity.
+ * len [out] - The length of the data.
+ */
+void Curl_des_set_odd_parity(unsigned char *bytes, size_t len)
+{
+ size_t i;
+
+ for(i = 0; i < len; i++) {
+ unsigned char b = bytes[i];
+
+ bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^
+ (b >> 4) ^ (b >> 3) ^ (b >> 2) ^
+ (b >> 1)) & 0x01) == 0;
+
+ if(needs_parity)
+ bytes[i] |= 0x01;
+ else
+ bytes[i] &= 0xfe;
+ }
+}
+
+#endif /* USE_NTLM && (!USE_OPENSSL || HAVE_BORINGSSL) */
diff --git a/libcurl/src/lib/curl_des.h b/libcurl/src/lib/curl_des.h
new file mode 100644
index 0000000..b855db4
--- /dev/null
+++ b/libcurl/src/lib/curl_des.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_DES_H
+#define HEADER_CURL_DES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM) && (!defined(USE_OPENSSL) || defined(HAVE_BORINGSSL))
+
+/* Applies odd parity to the given byte array */
+void Curl_des_set_odd_parity(unsigned char *bytes, size_t length);
+
+#endif /* USE_NTLM && (!USE_OPENSSL || HAVE_BORINGSSL) */
+
+#endif /* HEADER_CURL_DES_H */
diff --git a/libcurl/src/lib/curl_endian.c b/libcurl/src/lib/curl_endian.c
new file mode 100644
index 0000000..4279108
--- /dev/null
+++ b/libcurl/src/lib/curl_endian.c
@@ -0,0 +1,236 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_endian.h"
+
+/*
+ * Curl_read16_le()
+ *
+ * This function converts a 16-bit integer from the little endian format, as
+ * used in the incoming package to whatever endian format we're using
+ * natively.
+ *
+ * Parameters:
+ *
+ * buf [in] - A pointer to a 2 byte buffer.
+ *
+ * Returns the integer.
+ */
+CURL_STATIC unsigned short Curl_read16_le(unsigned char *buf)
+{
+ return (unsigned short)(((unsigned short)buf[0]) |
+ ((unsigned short)buf[1] << 8));
+}
+
+/*
+ * Curl_read32_le()
+ *
+ * This function converts a 32-bit integer from the little endian format, as
+ * used in the incoming package to whatever endian format we're using
+ * natively.
+ *
+ * Parameters:
+ *
+ * buf [in] - A pointer to a 4 byte buffer.
+ *
+ * Returns the integer.
+ */
+CURL_STATIC unsigned int Curl_read32_le(unsigned char *buf)
+{
+ return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
+ ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
+}
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+/*
+ * Curl_read64_le()
+ *
+ * This function converts a 64-bit integer from the little endian format, as
+ * used in the incoming package to whatever endian format we're using
+ * natively.
+ *
+ * Parameters:
+ *
+ * buf [in] - A pointer to a 8 byte buffer.
+ *
+ * Returns the integer.
+ */
+#if defined(HAVE_LONGLONG)
+CURL_STATIC unsigned long long Curl_read64_le(unsigned char *buf)
+{
+ return ((unsigned long long)buf[0]) |
+ ((unsigned long long)buf[1] << 8) |
+ ((unsigned long long)buf[2] << 16) |
+ ((unsigned long long)buf[3] << 24) |
+ ((unsigned long long)buf[4] << 32) |
+ ((unsigned long long)buf[5] << 40) |
+ ((unsigned long long)buf[6] << 48) |
+ ((unsigned long long)buf[7] << 56);
+}
+#else
+CURL_STATIC unsigned __int64 Curl_read64_le(unsigned char *buf)
+{
+ return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
+ ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
+ ((unsigned __int64)buf[4] << 32) | ((unsigned __int64)buf[5] << 40) |
+ ((unsigned __int64)buf[6] << 48) | ((unsigned __int64)buf[7] << 56);
+}
+#endif
+
+#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
+
+/*
+ * Curl_read16_be()
+ *
+ * This function converts a 16-bit integer from the big endian format, as
+ * used in the incoming package to whatever endian format we're using
+ * natively.
+ *
+ * Parameters:
+ *
+ * buf [in] - A pointer to a 2 byte buffer.
+ *
+ * Returns the integer.
+ */
+CURL_STATIC unsigned short Curl_read16_be(unsigned char *buf)
+{
+ return (unsigned short)(((unsigned short)buf[0] << 8) |
+ ((unsigned short)buf[1]));
+}
+
+/*
+ * Curl_read32_be()
+ *
+ * This function converts a 32-bit integer from the big endian format, as
+ * used in the incoming package to whatever endian format we're using
+ * natively.
+ *
+ * Parameters:
+ *
+ * buf [in] - A pointer to a 4 byte buffer.
+ *
+ * Returns the integer.
+ */
+CURL_STATIC unsigned int Curl_read32_be(unsigned char *buf)
+{
+ return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
+ ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
+}
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+/*
+ * Curl_read64_be()
+ *
+ * This function converts a 64-bit integer from the big endian format, as
+ * used in the incoming package to whatever endian format we're using
+ * natively.
+ *
+ * Parameters:
+ *
+ * buf [in] - A pointer to a 8 byte buffer.
+ *
+ * Returns the integer.
+ */
+#if defined(HAVE_LONGLONG)
+CURL_STATIC unsigned long long Curl_read64_be(unsigned char *buf)
+{
+ return ((unsigned long long)buf[0] << 56) |
+ ((unsigned long long)buf[1] << 48) |
+ ((unsigned long long)buf[2] << 40) |
+ ((unsigned long long)buf[3] << 32) |
+ ((unsigned long long)buf[4] << 24) |
+ ((unsigned long long)buf[5] << 16) |
+ ((unsigned long long)buf[6] << 8) |
+ ((unsigned long long)buf[7]);
+}
+#else
+CURL_STATIC unsigned __int64 Curl_read64_be(unsigned char *buf)
+{
+ return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
+ ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |
+ ((unsigned __int64)buf[4] << 24) | ((unsigned __int64)buf[5] << 16) |
+ ((unsigned __int64)buf[6] << 8) | ((unsigned __int64)buf[7]);
+}
+#endif
+
+#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
+
+/*
+ * Curl_write16_le()
+ *
+ * This function converts a 16-bit integer from the native endian format,
+ * to little endian format ready for sending down the wire.
+ *
+ * Parameters:
+ *
+ * value [in] - The 16-bit integer value.
+ * buffer [in] - A pointer to the output buffer.
+ */
+CURL_STATIC void Curl_write16_le(const short value, unsigned char *buffer)
+{
+ buffer[0] = (char)(value & 0x00FF);
+ buffer[1] = (char)((value & 0xFF00) >> 8);
+}
+
+/*
+ * Curl_write32_le()
+ *
+ * This function converts a 32-bit integer from the native endian format,
+ * to little endian format ready for sending down the wire.
+ *
+ * Parameters:
+ *
+ * value [in] - The 32-bit integer value.
+ * buffer [in] - A pointer to the output buffer.
+ */
+CURL_STATIC void Curl_write32_le(const int value, unsigned char *buffer)
+{
+ buffer[0] = (char)(value & 0x000000FF);
+ buffer[1] = (char)((value & 0x0000FF00) >> 8);
+ buffer[2] = (char)((value & 0x00FF0000) >> 16);
+ buffer[3] = (char)((value & 0xFF000000) >> 24);
+}
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+/*
+ * Curl_write64_le()
+ *
+ * This function converts a 64-bit integer from the native endian format,
+ * to little endian format ready for sending down the wire.
+ *
+ * Parameters:
+ *
+ * value [in] - The 64-bit integer value.
+ * buffer [in] - A pointer to the output buffer.
+ */
+#if defined(HAVE_LONGLONG)
+CURL_STATIC void Curl_write64_le(const long long value, unsigned char *buffer)
+#else
+CURL_STATIC void Curl_write64_le(const __int64 value, unsigned char *buffer)
+#endif
+{
+ Curl_write32_le((int)value, buffer);
+ Curl_write32_le((int)(value >> 32), buffer + 4);
+}
+#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
diff --git a/libcurl/src/lib/curl_endian.h b/libcurl/src/lib/curl_endian.h
new file mode 100644
index 0000000..3246752
--- /dev/null
+++ b/libcurl/src/lib/curl_endian.h
@@ -0,0 +1,70 @@
+#ifndef HEADER_CURL_ENDIAN_H
+#define HEADER_CURL_ENDIAN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Converts a 16-bit integer from little endian */
+CURL_STATIC unsigned short Curl_read16_le(unsigned char *buf);
+
+/* Converts a 32-bit integer from little endian */
+CURL_STATIC unsigned int Curl_read32_le(unsigned char *buf);
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+/* Converts a 64-bit integer from little endian */
+#if defined(HAVE_LONGLONG)
+CURL_STATIC unsigned long long Curl_read64_le(unsigned char *buf);
+#else
+CURL_STATIC unsigned __int64 Curl_read64_le(unsigned char *buf);
+#endif
+#endif
+
+/* Converts a 16-bit integer from big endian */
+CURL_STATIC unsigned short Curl_read16_be(unsigned char *buf);
+
+/* Converts a 32-bit integer from big endian */
+CURL_STATIC unsigned int Curl_read32_be(unsigned char *buf);
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+/* Converts a 64-bit integer from big endian */
+#if defined(HAVE_LONGLONG)
+CURL_STATIC unsigned long long Curl_read64_be(unsigned char *buf);
+#else
+CURL_STATIC unsigned __int64 Curl_read64_be(unsigned char *buf);
+#endif
+#endif
+
+/* Converts a 16-bit integer to little endian */
+CURL_STATIC void Curl_write16_le(const short value, unsigned char *buffer);
+
+/* Converts a 32-bit integer to little endian */
+CURL_STATIC void Curl_write32_le(const int value, unsigned char *buffer);
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+/* Converts a 64-bit integer to little endian */
+#if defined(HAVE_LONGLONG)
+CURL_STATIC void Curl_write64_le(const long long value, unsigned char *buffer);
+#else
+CURL_STATIC void Curl_write64_le(const __int64 value, unsigned char *buffer);
+#endif
+#endif
+
+#endif /* HEADER_CURL_ENDIAN_H */
diff --git a/libcurl/src/lib/curl_fnmatch.c b/libcurl/src/lib/curl_fnmatch.c
new file mode 100644
index 0000000..d762e25
--- /dev/null
+++ b/libcurl/src/lib/curl_fnmatch.c
@@ -0,0 +1,424 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_fnmatch.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
+#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
+
+#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN
+
+#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1)
+#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2)
+#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3)
+#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4)
+#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5)
+#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6)
+#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7)
+#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8)
+#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9)
+#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
+
+typedef enum {
+ CURLFNM_LOOP_DEFAULT = 0,
+ CURLFNM_LOOP_BACKSLASH
+} loop_state;
+
+typedef enum {
+ CURLFNM_SCHS_DEFAULT = 0,
+ CURLFNM_SCHS_MAYRANGE,
+ CURLFNM_SCHS_MAYRANGE2,
+ CURLFNM_SCHS_RIGHTBR,
+ CURLFNM_SCHS_RIGHTBRLEFTBR
+} setcharset_state;
+
+typedef enum {
+ CURLFNM_PKW_INIT = 0,
+ CURLFNM_PKW_DDOT
+} parsekey_state;
+
+#define SETCHARSET_OK 1
+#define SETCHARSET_FAIL 0
+
+static int parsekeyword(unsigned char **pattern, unsigned char *charset)
+{
+ parsekey_state state = CURLFNM_PKW_INIT;
+#define KEYLEN 10
+ char keyword[KEYLEN] = { 0 };
+ int found = FALSE;
+ int i;
+ unsigned char *p = *pattern;
+ for(i = 0; !found; i++) {
+ char c = *p++;
+ if(i >= KEYLEN)
+ return SETCHARSET_FAIL;
+ switch(state) {
+ case CURLFNM_PKW_INIT:
+ if(ISALPHA(c) && ISLOWER(c))
+ keyword[i] = c;
+ else if(c == ':')
+ state = CURLFNM_PKW_DDOT;
+ else
+ return 0;
+ break;
+ case CURLFNM_PKW_DDOT:
+ if(c == ']')
+ found = TRUE;
+ else
+ return SETCHARSET_FAIL;
+ }
+ }
+#undef KEYLEN
+
+ *pattern = p; /* move caller's pattern pointer */
+ if(strcmp(keyword, "digit") == 0)
+ charset[CURLFNM_DIGIT] = 1;
+ else if(strcmp(keyword, "alnum") == 0)
+ charset[CURLFNM_ALNUM] = 1;
+ else if(strcmp(keyword, "alpha") == 0)
+ charset[CURLFNM_ALPHA] = 1;
+ else if(strcmp(keyword, "xdigit") == 0)
+ charset[CURLFNM_XDIGIT] = 1;
+ else if(strcmp(keyword, "print") == 0)
+ charset[CURLFNM_PRINT] = 1;
+ else if(strcmp(keyword, "graph") == 0)
+ charset[CURLFNM_GRAPH] = 1;
+ else if(strcmp(keyword, "space") == 0)
+ charset[CURLFNM_SPACE] = 1;
+ else if(strcmp(keyword, "blank") == 0)
+ charset[CURLFNM_BLANK] = 1;
+ else if(strcmp(keyword, "upper") == 0)
+ charset[CURLFNM_UPPER] = 1;
+ else if(strcmp(keyword, "lower") == 0)
+ charset[CURLFNM_LOWER] = 1;
+ else
+ return SETCHARSET_FAIL;
+ return SETCHARSET_OK;
+}
+
+/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
+static int setcharset(unsigned char **p, unsigned char *charset)
+{
+ setcharset_state state = CURLFNM_SCHS_DEFAULT;
+ unsigned char rangestart = 0;
+ unsigned char lastchar = 0;
+ bool something_found = FALSE;
+ unsigned char c;
+ for(;;) {
+ c = **p;
+ switch(state) {
+ case CURLFNM_SCHS_DEFAULT:
+ if(ISALNUM(c)) { /* ASCII value */
+ rangestart = c;
+ charset[c] = 1;
+ (*p)++;
+ state = CURLFNM_SCHS_MAYRANGE;
+ something_found = TRUE;
+ }
+ else if(c == ']') {
+ if(something_found)
+ return SETCHARSET_OK;
+ else
+ something_found = TRUE;
+ state = CURLFNM_SCHS_RIGHTBR;
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '[') {
+ char c2 = *((*p)+1);
+ if(c2 == ':') { /* there has to be a keyword */
+ (*p) += 2;
+ if(parsekeyword(p, charset)) {
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ else {
+ charset[c] = 1;
+ (*p)++;
+ }
+ something_found = TRUE;
+ }
+ else if(c == '?' || c == '*') {
+ something_found = TRUE;
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '^' || c == '!') {
+ if(!something_found) {
+ if(charset[CURLFNM_NEGATE]) {
+ charset[c] = 1;
+ something_found = TRUE;
+ }
+ else
+ charset[CURLFNM_NEGATE] = 1; /* negate charset */
+ }
+ else
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '\\') {
+ c = *(++(*p));
+ if(ISPRINT((c))) {
+ something_found = TRUE;
+ state = CURLFNM_SCHS_MAYRANGE;
+ charset[c] = 1;
+ rangestart = c;
+ (*p)++;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ else if(c == '\0') {
+ return SETCHARSET_FAIL;
+ }
+ else {
+ charset[c] = 1;
+ (*p)++;
+ something_found = TRUE;
+ }
+ break;
+ case CURLFNM_SCHS_MAYRANGE:
+ if(c == '-') {
+ charset[c] = 1;
+ (*p)++;
+ lastchar = '-';
+ state = CURLFNM_SCHS_MAYRANGE2;
+ }
+ else if(c == '[') {
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else if(ISALNUM(c)) {
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '\\') {
+ c = *(++(*p));
+ if(ISPRINT(c)) {
+ charset[c] = 1;
+ (*p)++;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ else if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else
+ return SETCHARSET_FAIL;
+ break;
+ case CURLFNM_SCHS_MAYRANGE2:
+ if(c == '\\') {
+ c = *(++(*p));
+ if(!ISPRINT(c))
+ return SETCHARSET_FAIL;
+ }
+ if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else if(c == '\\') {
+ c = *(++(*p));
+ if(ISPRINT(c)) {
+ charset[c] = 1;
+ state = CURLFNM_SCHS_DEFAULT;
+ (*p)++;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ if(c >= rangestart) {
+ if((ISLOWER(c) && ISLOWER(rangestart)) ||
+ (ISDIGIT(c) && ISDIGIT(rangestart)) ||
+ (ISUPPER(c) && ISUPPER(rangestart))) {
+ charset[lastchar] = 0;
+ rangestart++;
+ while(rangestart++ <= c)
+ charset[rangestart-1] = 1;
+ (*p)++;
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ break;
+ case CURLFNM_SCHS_RIGHTBR:
+ if(c == '[') {
+ state = CURLFNM_SCHS_RIGHTBRLEFTBR;
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else if(c == '\0') {
+ return SETCHARSET_FAIL;
+ }
+ else if(ISPRINT(c)) {
+ charset[c] = 1;
+ (*p)++;
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else
+ /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a
+ * nonsense warning 'statement not reached' at end of the fnc when
+ * compiling on Solaris */
+ goto fail;
+ break;
+ case CURLFNM_SCHS_RIGHTBRLEFTBR:
+ if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else {
+ state = CURLFNM_SCHS_DEFAULT;
+ charset[c] = 1;
+ (*p)++;
+ }
+ break;
+ }
+ }
+fail:
+ return SETCHARSET_FAIL;
+}
+
+static int loop(const unsigned char *pattern, const unsigned char *string)
+{
+ loop_state state = CURLFNM_LOOP_DEFAULT;
+ unsigned char *p = (unsigned char *)pattern;
+ unsigned char *s = (unsigned char *)string;
+ unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
+ int rc = 0;
+
+ for(;;) {
+ switch(state) {
+ case CURLFNM_LOOP_DEFAULT:
+ if(*p == '*') {
+ while(*(p+1) == '*') /* eliminate multiple stars */
+ p++;
+ if(*s == '\0' && *(p+1) == '\0')
+ return CURL_FNMATCH_MATCH;
+ rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */
+ if(rc == CURL_FNMATCH_MATCH)
+ return CURL_FNMATCH_MATCH;
+ if(*s) /* let the star eat up one character */
+ s++;
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else if(*p == '?') {
+ if(ISPRINT(*s)) {
+ s++;
+ p++;
+ }
+ else if(*s == '\0')
+ return CURL_FNMATCH_NOMATCH;
+ else
+ return CURL_FNMATCH_FAIL; /* cannot deal with other character */
+ }
+ else if(*p == '\0') {
+ if(*s == '\0')
+ return CURL_FNMATCH_MATCH;
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else if(*p == '\\') {
+ state = CURLFNM_LOOP_BACKSLASH;
+ p++;
+ }
+ else if(*p == '[') {
+ unsigned char *pp = p+1; /* cannot handle with pointer to register */
+ if(setcharset(&pp, charset)) {
+ int found = FALSE;
+ if(charset[(unsigned int)*s])
+ found = TRUE;
+ else if(charset[CURLFNM_ALNUM])
+ found = ISALNUM(*s);
+ else if(charset[CURLFNM_ALPHA])
+ found = ISALPHA(*s);
+ else if(charset[CURLFNM_DIGIT])
+ found = ISDIGIT(*s);
+ else if(charset[CURLFNM_XDIGIT])
+ found = ISXDIGIT(*s);
+ else if(charset[CURLFNM_PRINT])
+ found = ISPRINT(*s);
+ else if(charset[CURLFNM_SPACE])
+ found = ISSPACE(*s);
+ else if(charset[CURLFNM_UPPER])
+ found = ISUPPER(*s);
+ else if(charset[CURLFNM_LOWER])
+ found = ISLOWER(*s);
+ else if(charset[CURLFNM_BLANK])
+ found = ISBLANK(*s);
+ else if(charset[CURLFNM_GRAPH])
+ found = ISGRAPH(*s);
+
+ if(charset[CURLFNM_NEGATE])
+ found = !found;
+
+ if(found) {
+ p = pp+1;
+ s++;
+ memset(charset, 0, CURLFNM_CHSET_SIZE);
+ }
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else
+ return CURL_FNMATCH_FAIL;
+ }
+ else {
+ if(*p++ != *s++)
+ return CURL_FNMATCH_NOMATCH;
+ }
+ break;
+ case CURLFNM_LOOP_BACKSLASH:
+ if(ISPRINT(*p)) {
+ if(*p++ == *s++)
+ state = CURLFNM_LOOP_DEFAULT;
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else
+ return CURL_FNMATCH_FAIL;
+ break;
+ }
+ }
+}
+
+/*
+ * @unittest: 1307
+ */
+CURL_STATIC int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
+{
+ (void)ptr; /* the argument is specified by the curl_fnmatch_callback
+ prototype, but not used by Curl_fnmatch() */
+ if(!pattern || !string) {
+ return CURL_FNMATCH_FAIL;
+ }
+ return loop((unsigned char *)pattern, (unsigned char *)string);
+}
diff --git a/libcurl/src/lib/curl_fnmatch.h b/libcurl/src/lib/curl_fnmatch.h
new file mode 100644
index 0000000..8e9c50a
--- /dev/null
+++ b/libcurl/src/lib/curl_fnmatch.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_FNMATCH_H
+#define HEADER_CURL_FNMATCH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#define CURL_FNMATCH_MATCH 0
+#define CURL_FNMATCH_NOMATCH 1
+#define CURL_FNMATCH_FAIL 2
+
+/* default pattern matching function
+ * =================================
+ * Implemented with recursive backtracking, if you want to use Curl_fnmatch,
+ * please note that there is not implemented UTF/UNICODE support.
+ *
+ * Implemented features:
+ * '?' notation, does not match UTF characters
+ * '*' can also work with UTF string
+ * [a-zA-Z0-9] enumeration support
+ *
+ * keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space
+ * and upper (use as "[[:alnum:]]")
+ */
+CURL_STATIC int Curl_fnmatch(void *ptr, const char *pattern, const char *string);
+
+#endif /* HEADER_CURL_FNMATCH_H */
diff --git a/libcurl/src/lib/curl_gethostname.c b/libcurl/src/lib/curl_gethostname.c
new file mode 100644
index 0000000..2d9909d
--- /dev/null
+++ b/libcurl/src/lib/curl_gethostname.c
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_gethostname.h"
+
+/*
+ * Curl_gethostname() is a wrapper around gethostname() which allows
+ * overriding the host name that the function would normally return.
+ * This capability is used by the test suite to verify exact matching
+ * of NTLM authentication, which exercises libcurl's MD4 and DES code
+ * as well as by the SMTP module when a hostname is not provided.
+ *
+ * For libcurl debug enabled builds host name overriding takes place
+ * when environment variable CURL_GETHOSTNAME is set, using the value
+ * held by the variable to override returned host name.
+ *
+ * Note: The function always returns the un-qualified hostname rather
+ * than being provider dependent.
+ *
+ * For libcurl shared library release builds the test suite preloads
+ * another shared library named libhostname using the LD_PRELOAD
+ * mechanism which intercepts, and might override, the gethostname()
+ * function call. In this case a given platform must support the
+ * LD_PRELOAD mechanism and additionally have environment variable
+ * CURL_GETHOSTNAME set in order to override the returned host name.
+ *
+ * For libcurl static library release builds no overriding takes place.
+ */
+
+CURL_STATIC int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
+
+#ifndef HAVE_GETHOSTNAME
+
+ /* Allow compilation and return failure when unavailable */
+ (void) name;
+ (void) namelen;
+ return -1;
+
+#else
+ int err;
+ char* dot;
+
+#ifdef DEBUGBUILD
+
+ /* Override host name when environment variable CURL_GETHOSTNAME is set */
+ const char *force_hostname = getenv("CURL_GETHOSTNAME");
+ if(force_hostname) {
+ strncpy(name, force_hostname, namelen);
+ err = 0;
+ }
+ else {
+ name[0] = '\0';
+ err = gethostname(name, namelen);
+ }
+
+#else /* DEBUGBUILD */
+
+ /* The call to system's gethostname() might get intercepted by the
+ libhostname library when libcurl is built as a non-debug shared
+ library when running the test suite. */
+ name[0] = '\0';
+ err = gethostname(name, namelen);
+
+#endif
+
+ name[namelen - 1] = '\0';
+
+ if(err)
+ return err;
+
+ /* Truncate domain, leave only machine name */
+ dot = strchr(name, '.');
+ if(dot)
+ *dot = '\0';
+
+ return 0;
+#endif
+
+}
diff --git a/libcurl/src/lib/curl_gethostname.h b/libcurl/src/lib/curl_gethostname.h
new file mode 100644
index 0000000..db1083b
--- /dev/null
+++ b/libcurl/src/lib/curl_gethostname.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_GETHOSTNAME_H
+#define HEADER_CURL_GETHOSTNAME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Hostname buffer size */
+#define HOSTNAME_MAX 1024
+
+/* This returns the local machine's un-qualified hostname */
+CURL_STATIC int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen);
+
+#endif /* HEADER_CURL_GETHOSTNAME_H */
diff --git a/libcurl/src/lib/curl_gssapi.c b/libcurl/src/lib/curl_gssapi.c
new file mode 100644
index 0000000..3707c4d
--- /dev/null
+++ b/libcurl/src/lib/curl_gssapi.c
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2011 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_GSSAPI
+
+#include "curl_gssapi.h"
+#include "sendf.h"
+
+static const char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02";
+gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes };
+static const char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02";
+gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes };
+
+CURL_STATIC OM_uint32 Curl_gss_init_sec_context(
+ struct SessionHandle *data,
+ OM_uint32 *minor_status,
+ gss_ctx_id_t *context,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_buffer_t output_token,
+ const bool mutual_auth,
+ OM_uint32 *ret_flags)
+{
+ OM_uint32 req_flags = GSS_C_REPLAY_FLAG;
+
+ if(mutual_auth)
+ req_flags |= GSS_C_MUTUAL_FLAG;
+
+ if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
+#ifdef GSS_C_DELEG_POLICY_FLAG
+ req_flags |= GSS_C_DELEG_POLICY_FLAG;
+#else
+ infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
+ "compiled in\n");
+#endif
+ }
+
+ if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG)
+ req_flags |= GSS_C_DELEG_FLAG;
+
+ return gss_init_sec_context(minor_status,
+ GSS_C_NO_CREDENTIAL, /* cred_handle */
+ context,
+ target_name,
+ mech_type,
+ req_flags,
+ 0, /* time_req */
+ input_chan_bindings,
+ input_token,
+ NULL, /* actual_mech_type */
+ output_token,
+ ret_flags,
+ NULL /* time_rec */);
+}
+
+/*
+ * Curl_gss_log_error()
+ *
+ * This is used to log a GSS-API error status.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * status [in] - The status code.
+ * prefix [in] - The prefix of the log message.
+ */
+CURL_STATIC void Curl_gss_log_error(struct SessionHandle *data, OM_uint32 status,
+ const char *prefix)
+{
+ OM_uint32 maj_stat;
+ OM_uint32 min_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ char buf[1024];
+ size_t len;
+
+ snprintf(buf, sizeof(buf), "%s", prefix);
+ len = strlen(buf);
+ do {
+ maj_stat = gss_display_status(&min_stat,
+ status,
+ GSS_C_MECH_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &status_string);
+ if(sizeof(buf) > len + status_string.length + 1) {
+ snprintf(buf + len, sizeof(buf) - len,
+ ": %s", (char*)status_string.value);
+ len += status_string.length;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
+
+ infof(data, "%s\n", buf);
+}
+
+#endif /* HAVE_GSSAPI */
diff --git a/libcurl/src/lib/curl_gssapi.h b/libcurl/src/lib/curl_gssapi.h
new file mode 100644
index 0000000..b54891e
--- /dev/null
+++ b/libcurl/src/lib/curl_gssapi.h
@@ -0,0 +1,75 @@
+#ifndef HEADER_CURL_GSSAPI_H
+#define HEADER_CURL_GSSAPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "urldata.h"
+
+#ifdef HAVE_GSSAPI
+
+#ifdef HAVE_GSSGNU
+# include <gss.h>
+#elif defined HAVE_GSSMIT
+ /* MIT style */
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_generic.h>
+# include <gssapi/gssapi_krb5.h>
+#else
+ /* Heimdal-style */
+# include <gssapi.h>
+#endif
+
+extern gss_OID_desc Curl_spnego_mech_oid;
+extern gss_OID_desc Curl_krb5_mech_oid;
+
+/* Common method for using GSS-API */
+CURL_STATIC OM_uint32 Curl_gss_init_sec_context(
+ struct SessionHandle *data,
+ OM_uint32 *minor_status,
+ gss_ctx_id_t *context,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_buffer_t output_token,
+ const bool mutual_auth,
+ OM_uint32 *ret_flags);
+
+/* Helper to log a GSS-API error status */
+CURL_STATIC void Curl_gss_log_error(struct SessionHandle *data, OM_uint32 status,
+ const char *prefix);
+
+/* Provide some definitions missing in old headers */
+#ifdef HAVE_OLD_GSSMIT
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#define NCOMPAT 1
+#endif
+
+/* Define our privacy and integrity protection values */
+#define GSSAUTH_P_NONE 1
+#define GSSAUTH_P_INTEGRITY 2
+#define GSSAUTH_P_PRIVACY 4
+
+#endif /* HAVE_GSSAPI */
+
+#endif /* HEADER_CURL_GSSAPI_H */
diff --git a/libcurl/src/lib/curl_hmac.h b/libcurl/src/lib/curl_hmac.h
new file mode 100644
index 0000000..e184fdf
--- /dev/null
+++ b/libcurl/src/lib/curl_hmac.h
@@ -0,0 +1,67 @@
+#ifndef HEADER_CURL_HMAC_H
+#define HEADER_CURL_HMAC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+typedef void (* HMAC_hinit_func)(void * context);
+typedef void (* HMAC_hupdate_func)(void * context,
+ const unsigned char * data,
+ unsigned int len);
+typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context);
+
+
+/* Per-hash function HMAC parameters. */
+
+typedef struct {
+ HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */
+ HMAC_hupdate_func hmac_hupdate; /* Update context with data. */
+ HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */
+ unsigned int hmac_ctxtsize; /* Context structure size. */
+ unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */
+ unsigned int hmac_resultlen; /* Result length (bytes). */
+} HMAC_params;
+
+
+/* HMAC computation context. */
+
+typedef struct {
+ const HMAC_params * hmac_hash; /* Hash function definition. */
+ void * hmac_hashctxt1; /* Hash function context 1. */
+ void * hmac_hashctxt2; /* Hash function context 2. */
+} HMAC_context;
+
+
+/* Prototypes. */
+
+CURL_STATIC HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams,
+ const unsigned char * key,
+ unsigned int keylen);
+CURL_STATIC int Curl_HMAC_update(HMAC_context * context,
+ const unsigned char * data,
+ unsigned int len);
+CURL_STATIC int Curl_HMAC_final(HMAC_context * context, unsigned char * result);
+
+#endif
+
+#endif /* HEADER_CURL_HMAC_H */
diff --git a/libcurl/src/lib/curl_ldap.h b/libcurl/src/lib/curl_ldap.h
new file mode 100644
index 0000000..93fb4b0
--- /dev/null
+++ b/libcurl/src/lib/curl_ldap.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_LDAP_H
+#define HEADER_CURL_LDAP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_LDAP
+extern const struct Curl_handler Curl_handler_ldap;
+
+#if !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+extern const struct Curl_handler Curl_handler_ldaps;
+#endif
+
+#endif
+#endif /* HEADER_CURL_LDAP_H */
+
diff --git a/libcurl/src/lib/curl_md4.h b/libcurl/src/lib/curl_md4.h
new file mode 100644
index 0000000..b5a6e68
--- /dev/null
+++ b/libcurl/src/lib/curl_md4.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_MD4_H
+#define HEADER_CURL_MD4_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
+ * that we have a local implementation of it */
+#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
+
+CURL_STATIC void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
+
+#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
+
+#endif /* HEADER_CURL_MD4_H */
diff --git a/libcurl/src/lib/curl_md5.h b/libcurl/src/lib/curl_md5.h
new file mode 100644
index 0000000..3626a50
--- /dev/null
+++ b/libcurl/src/lib/curl_md5.h
@@ -0,0 +1,63 @@
+#ifndef HEADER_CURL_MD5_H
+#define HEADER_CURL_MD5_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include "curl_hmac.h"
+
+#define MD5_DIGEST_LEN 16
+
+typedef void (* Curl_MD5_init_func)(void *context);
+typedef void (* Curl_MD5_update_func)(void *context,
+ const unsigned char *data,
+ unsigned int len);
+typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
+
+typedef struct {
+ Curl_MD5_init_func md5_init_func; /* Initialize context procedure */
+ Curl_MD5_update_func md5_update_func; /* Update context with data */
+ Curl_MD5_final_func md5_final_func; /* Get final result procedure */
+ unsigned int md5_ctxtsize; /* Context structure size */
+ unsigned int md5_resultlen; /* Result length (bytes) */
+} MD5_params;
+
+typedef struct {
+ const MD5_params *md5_hash; /* Hash function definition */
+ void *md5_hashctx; /* Hash function context */
+} MD5_context;
+
+extern const MD5_params Curl_DIGEST_MD5[1];
+extern const HMAC_params Curl_HMAC_MD5[1];
+
+CURL_STATIC void Curl_md5it(unsigned char *output,
+ const unsigned char *input);
+
+CURL_STATIC MD5_context * Curl_MD5_init(const MD5_params *md5params);
+CURL_STATIC int Curl_MD5_update(MD5_context *context,
+ const unsigned char *data,
+ unsigned int len);
+CURL_STATIC int Curl_MD5_final(MD5_context *context, unsigned char *result);
+
+#endif
+
+#endif /* HEADER_CURL_MD5_H */
diff --git a/libcurl/src/lib/curl_memory.h b/libcurl/src/lib/curl_memory.h
new file mode 100644
index 0000000..c485591
--- /dev/null
+++ b/libcurl/src/lib/curl_memory.h
@@ -0,0 +1,180 @@
+#ifndef HEADER_CURL_MEMORY_H
+#define HEADER_CURL_MEMORY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Nasty internal details ahead...
+ *
+ * File curl_memory.h must be included by _all_ *.c source files
+ * that use memory related functions strdup, malloc, calloc, realloc
+ * or free, and given source file is used to build libcurl library.
+ * It should be included immediately before memdebug.h as the last files
+ * included to avoid undesired interaction with other memory function
+ * headers in dependent libraries.
+ *
+ * There is nearly no exception to above rule. All libcurl source
+ * files in 'lib' subdirectory as well as those living deep inside
+ * 'packages' subdirectories and linked together in order to build
+ * libcurl library shall follow it.
+ *
+ * File lib/strdup.c is an exception, given that it provides a strdup
+ * clone implementation while using malloc. Extra care needed inside
+ * this one. TODO: revisit this paragraph and related code.
+ *
+ * The need for curl_memory.h inclusion is due to libcurl's feature
+ * of allowing library user to provide memory replacement functions,
+ * memory callbacks, at runtime with curl_global_init_mem()
+ *
+ * Any *.c source file used to build libcurl library that does not
+ * include curl_memory.h and uses any memory function of the five
+ * mentioned above will compile without any indication, but it will
+ * trigger weird memory related issues at runtime.
+ *
+ * OTOH some source files from 'lib' subdirectory may additionally be
+ * used directly as source code when using some curlx_ functions by
+ * third party programs that don't even use libcurl at all. When using
+ * these source files in this way it is necessary these are compiled
+ * with CURLX_NO_MEMORY_CALLBACKS defined, in order to ensure that no
+ * attempt of calling libcurl's memory callbacks is done from code
+ * which can not use this machinery.
+ *
+ * Notice that libcurl's 'memory tracking' system works chaining into
+ * the memory callback machinery. This implies that when compiling
+ * 'lib' source files with CURLX_NO_MEMORY_CALLBACKS defined this file
+ * disengages usage of libcurl's 'memory tracking' system, defining
+ * MEMDEBUG_NODEFINES and overriding CURLDEBUG purpose.
+ *
+ * CURLX_NO_MEMORY_CALLBACKS takes precedence over CURLDEBUG. This is
+ * done in order to allow building a 'memory tracking' enabled libcurl
+ * and at the same time allow building programs which do not use it.
+ *
+ * Programs and libraries in 'tests' subdirectories have specific
+ * purposes and needs, and as such each one will use whatever fits
+ * best, depending additionally wether it links with libcurl or not.
+ *
+ * Caveat emptor. Proper curlx_* separation is a work in progress
+ * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may
+ * still be required. IOW don't use them yet, there are sharp edges.
+ */
+
+#ifdef HEADER_CURL_MEMDEBUG_H
+#error "Header memdebug.h shall not be included before curl_memory.h"
+#endif
+
+#ifndef CURLX_NO_MEMORY_CALLBACKS
+
+#include <curl/curl.h> /* for the callback typedefs */
+
+/*
+ * strdup (and other memory functions) is redefined in complicated
+ * ways, but at this point it must be defined as the system-supplied strdup
+ * so the callback pointer is initialized correctly.
+ */
+#if defined(_WIN32_WCE)
+#define system_strdup _strdup
+#elif !defined(HAVE_STRDUP)
+#define system_strdup curlx_strdup
+#else
+#define system_strdup strdup
+#endif
+
+#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
+#endif
+
+#ifndef __SYMBIAN32__
+/*
+ * If a memory-using function (like curl_getenv) is used before
+ * curl_global_init() is called, we need to have these pointers set already.
+ */
+CURL_STATIC_VAR curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
+CURL_STATIC_VAR curl_free_callback Curl_cfree = (curl_free_callback)free;
+CURL_STATIC_VAR curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
+CURL_STATIC_VAR curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
+CURL_STATIC_VAR curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
+#if defined(WIN32) && defined(UNICODE)
+CURL_STATIC_VAR curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
+#endif
+#else
+/*
+ * Symbian OS doesn't support initialization to code in writeable static data.
+ * Initialization will occur in the curl_global_init() call.
+ */
+CURL_STATIC_VAR curl_malloc_callback Curl_cmalloc;
+CURL_STATIC_VAR curl_free_callback Curl_cfree;
+CURL_STATIC_VAR curl_realloc_callback Curl_crealloc;
+CURL_STATIC_VAR curl_strdup_callback Curl_cstrdup;
+CURL_STATIC_VAR curl_calloc_callback Curl_ccalloc;
+#endif
+
+#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+# pragma warning(default:4232) /* MSVC extension, dllimport identity */
+#endif
+
+#ifndef CURLDEBUG
+
+/*
+ * libcurl's 'memory tracking' system defines strdup, malloc, calloc,
+ * realloc and free, along with others, in memdebug.h in a different
+ * way although still using memory callbacks forward declared above.
+ * When using the 'memory tracking' system (CURLDEBUG defined) we do
+ * not define here the five memory functions given that definitions
+ * from memdebug.h are the ones that shall be used.
+ */
+
+#undef strdup
+#define strdup(ptr) Curl_cstrdup(ptr)
+#undef malloc
+#define malloc(size) Curl_cmalloc(size)
+#undef calloc
+#define calloc(nbelem,size) Curl_ccalloc(nbelem, size)
+#undef realloc
+#define realloc(ptr,size) Curl_crealloc(ptr, size)
+#undef free
+#define free(ptr) Curl_cfree(ptr)
+
+#ifdef WIN32
+# ifdef UNICODE
+# undef wcsdup
+# define wcsdup(ptr) Curl_cwcsdup(ptr)
+# undef _wcsdup
+# define _wcsdup(ptr) Curl_cwcsdup(ptr)
+# undef _tcsdup
+# define _tcsdup(ptr) Curl_cwcsdup(ptr)
+# else
+# undef _tcsdup
+# define _tcsdup(ptr) Curl_cstrdup(ptr)
+# endif
+#endif
+
+#endif /* CURLDEBUG */
+
+#else /* CURLX_NO_MEMORY_CALLBACKS */
+
+#ifndef MEMDEBUG_NODEFINES
+#define MEMDEBUG_NODEFINES
+#endif
+
+#endif /* CURLX_NO_MEMORY_CALLBACKS */
+
+#endif /* HEADER_CURL_MEMORY_H */
diff --git a/libcurl/src/lib/curl_memrchr.c b/libcurl/src/lib/curl_memrchr.c
new file mode 100644
index 0000000..dbdc380
--- /dev/null
+++ b/libcurl/src/lib/curl_memrchr.c
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "curl_memrchr.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef HAVE_MEMRCHR
+
+/*
+ * Curl_memrchr()
+ *
+ * Our memrchr() function clone for systems which lack this function. The
+ * memrchr() function is like the memchr() function, except that it searches
+ * backwards from the end of the n bytes pointed to by s instead of forward
+ * from the beginning.
+ */
+
+CURL_STATIC void *
+Curl_memrchr(const void *s, int c, size_t n)
+{
+ const unsigned char *p = s;
+ const unsigned char *q = s;
+
+ p += n - 1;
+
+ while(p >= q) {
+ if(*p == (unsigned char)c)
+ return (void *)p;
+ p--;
+ }
+
+ return NULL;
+}
+
+#endif /* HAVE_MEMRCHR */
diff --git a/libcurl/src/lib/curl_memrchr.h b/libcurl/src/lib/curl_memrchr.h
new file mode 100644
index 0000000..c566f63
--- /dev/null
+++ b/libcurl/src/lib/curl_memrchr.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_MEMRCHR_H
+#define HEADER_CURL_MEMRCHR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_MEMRCHR
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#else /* HAVE_MEMRCHR */
+
+CURL_STATIC void *Curl_memrchr(const void *s, int c, size_t n);
+
+#define memrchr(x,y,z) Curl_memrchr((x),(y),(z))
+
+#endif /* HAVE_MEMRCHR */
+
+#endif /* HEADER_CURL_MEMRCHR_H */
diff --git a/libcurl/src/lib/curl_multibyte.c b/libcurl/src/lib/curl_multibyte.c
new file mode 100644
index 0000000..811e6d1
--- /dev/null
+++ b/libcurl/src/lib/curl_multibyte.c
@@ -0,0 +1,82 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
+ defined(USE_WIN32_LDAP)) && defined(UNICODE))
+
+ /*
+ * MultiByte conversions using Windows kernel32 library.
+ */
+
+#include "curl_multibyte.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURL_STATIC wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
+{
+ wchar_t *str_w = NULL;
+
+ if(str_utf8) {
+ int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
+ str_utf8, -1, NULL, 0);
+ if(str_w_len > 0) {
+ str_w = malloc(str_w_len * sizeof(wchar_t));
+ if(str_w) {
+ if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w,
+ str_w_len) == 0) {
+ free(str_w);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ return str_w;
+}
+
+CURL_STATIC char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
+{
+ char *str_utf8 = NULL;
+
+ if(str_w) {
+ int str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL,
+ 0, NULL, NULL);
+ if(str_utf8_len > 0) {
+ str_utf8 = malloc(str_utf8_len * sizeof(wchar_t));
+ if(str_utf8) {
+ if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len,
+ NULL, FALSE) == 0) {
+ free(str_utf8);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ return str_utf8;
+}
+
+#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */
diff --git a/libcurl/src/lib/curl_multibyte.h b/libcurl/src/lib/curl_multibyte.h
new file mode 100644
index 0000000..d660333
--- /dev/null
+++ b/libcurl/src/lib/curl_multibyte.h
@@ -0,0 +1,92 @@
+#ifndef HEADER_CURL_MULTIBYTE_H
+#define HEADER_CURL_MULTIBYTE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
+ defined(USE_WIN32_LDAP)) && defined(UNICODE))
+
+ /*
+ * MultiByte conversions using Windows kernel32 library.
+ */
+
+CURL_STATIC wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8);
+CURL_STATIC char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w);
+
+#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */
+
+
+#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \
+ defined(USE_WIN32_LDAP)
+
+/*
+ * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8()
+ * and Curl_unicodefree() main purpose is to minimize the number of
+ * preprocessor conditional directives needed by code using these
+ * to differentiate UNICODE from non-UNICODE builds.
+ *
+ * When building with UNICODE defined, this two macros
+ * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
+ * return a pointer to a newly allocated memory area holding result.
+ * When the result is no longer needed, allocated memory is intended
+ * to be free'ed with Curl_unicodefree().
+ *
+ * When building without UNICODE defined, this macros
+ * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
+ * return the pointer received as argument. Curl_unicodefree() does
+ * no actual free'ing of this pointer it is simply set to NULL.
+ */
+
+#ifdef UNICODE
+
+#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr))
+#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr))
+#define Curl_unicodefree(ptr) \
+ do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE
+
+typedef union {
+ unsigned short *tchar_ptr;
+ const unsigned short *const_tchar_ptr;
+ unsigned short *tbyte_ptr;
+ const unsigned short *const_tbyte_ptr;
+} xcharp_u;
+
+#else
+
+#define Curl_convert_UTF8_to_tchar(ptr) (ptr)
+#define Curl_convert_tchar_to_UTF8(ptr) (ptr)
+#define Curl_unicodefree(ptr) \
+ do {(ptr) = NULL;} WHILE_FALSE
+
+typedef union {
+ char *tchar_ptr;
+ const char *const_tchar_ptr;
+ unsigned char *tbyte_ptr;
+ const unsigned char *const_tbyte_ptr;
+} xcharp_u;
+
+#endif /* UNICODE */
+
+#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */
+
+#endif /* HEADER_CURL_MULTIBYTE_H */
diff --git a/libcurl/src/lib/curl_ntlm.c b/libcurl/src/lib/curl_ntlm.c
new file mode 100644
index 0000000..24162bc
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm.c
@@ -0,0 +1,232 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#include "urldata.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_msgs.h"
+#include "curl_ntlm_wb.h"
+#include "curl_sasl.h"
+#include "url.h"
+#include "curl_printf.h"
+
+#if defined(USE_NSS)
+#include "vtls/nssg.h"
+#elif defined(USE_WINDOWS_SSPI)
+#include "curl_sspi.h"
+#endif
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+CURLcode Curl_input_ntlm(struct connectdata *conn,
+ bool proxy, /* if proxy or not */
+ const char *header) /* rest of the www-authenticate:
+ header */
+{
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ CURLcode result = CURLE_OK;
+
+ ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
+
+ if(checkprefix("NTLM", header)) {
+ header += strlen("NTLM");
+
+ while(*header && ISSPACE(*header))
+ header++;
+
+ if(*header) {
+ result = Curl_sasl_decode_ntlm_type2_message(conn->data, header, ntlm);
+ if(result)
+ return result;
+
+ ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+ }
+ else {
+ if(ntlm->state == NTLMSTATE_TYPE3) {
+ infof(conn->data, "NTLM handshake rejected\n");
+ Curl_http_ntlm_cleanup(conn);
+ ntlm->state = NTLMSTATE_NONE;
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+ else if(ntlm->state >= NTLMSTATE_TYPE1) {
+ infof(conn->data, "NTLM handshake failure (internal error)\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+ }
+ }
+
+ return result;
+}
+
+/*
+ * This is for creating ntlm header output
+ */
+CURL_STATIC CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
+{
+ char *base64 = NULL;
+ size_t len = 0;
+ CURLcode result;
+
+ /* point to the address of the pointer that holds the string to send to the
+ server, which is for a plain host or for a HTTP proxy */
+ char **allocuserpwd;
+
+ /* point to the name and password for this */
+ const char *userp;
+ const char *passwdp;
+
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ struct auth *authp;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->data);
+
+#ifdef USE_NSS
+ if(CURLE_OK != Curl_nss_force_init(conn->data))
+ return CURLE_OUT_OF_MEMORY;
+#endif
+
+ if(proxy) {
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ passwdp = conn->proxypasswd;
+ ntlm = &conn->proxyntlm;
+ authp = &conn->data->state.authproxy;
+ }
+ else {
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ passwdp = conn->passwd;
+ ntlm = &conn->ntlm;
+ authp = &conn->data->state.authhost;
+ }
+ authp->done = FALSE;
+
+ /* not set means empty */
+ if(!userp)
+ userp = "";
+
+ if(!passwdp)
+ passwdp = "";
+
+#ifdef USE_WINDOWS_SSPI
+ if(s_hSecDll == NULL) {
+ /* not thread safe and leaks - use curl_global_init() to avoid */
+ CURLcode err = Curl_sspi_global_init();
+ if(s_hSecDll == NULL)
+ return err;
+ }
+#endif
+
+ switch(ntlm->state) {
+ case NTLMSTATE_TYPE1:
+ default: /* for the weird cases we (re)start here */
+ /* Create a type-1 message */
+ result = Curl_sasl_create_ntlm_type1_message(userp, passwdp, ntlm, &base64,
+ &len);
+ if(result)
+ return result;
+
+ if(base64) {
+ free(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ free(base64);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
+
+ DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
+ }
+ break;
+
+ case NTLMSTATE_TYPE2:
+ /* We already received the type-2 message, create a type-3 message */
+ result = Curl_sasl_create_ntlm_type3_message(conn->data, userp, passwdp,
+ ntlm, &base64, &len);
+ if(result)
+ return result;
+
+ if(base64) {
+ free(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ free(base64);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
+
+ DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
+
+ ntlm->state = NTLMSTATE_TYPE3; /* we send a type-3 */
+ authp->done = TRUE;
+ }
+ break;
+
+ case NTLMSTATE_TYPE3:
+ /* connection is already authenticated,
+ * don't send a header in future requests */
+ Curl_safefree(*allocuserpwd);
+ authp->done = TRUE;
+ break;
+ }
+
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_http_ntlm_cleanup(struct connectdata *conn)
+{
+ Curl_sasl_ntlm_cleanup(&conn->ntlm);
+ Curl_sasl_ntlm_cleanup(&conn->proxyntlm);
+
+#if defined(NTLM_WB_ENABLED)
+ Curl_ntlm_wb_cleanup(conn);
+#endif
+}
+
+#endif /* USE_NTLM */
diff --git a/libcurl/src/lib/curl_ntlm.h b/libcurl/src/lib/curl_ntlm.h
new file mode 100644
index 0000000..4615b95
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm.h
@@ -0,0 +1,40 @@
+#ifndef HEADER_CURL_NTLM_H
+#define HEADER_CURL_NTLM_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
+
+/* this is for ntlm header input */
+CURL_STATIC CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
+ const char *header);
+
+/* this is for creating ntlm header output */
+CURL_STATIC CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
+
+CURL_STATIC void Curl_http_ntlm_cleanup(struct connectdata *conn);
+
+#endif /* !CURL_DISABLE_HTTP && USE_NTLM */
+
+#endif /* HEADER_CURL_NTLM_H */
diff --git a/libcurl/src/lib/curl_ntlm_core.c b/libcurl/src/lib/curl_ntlm_core.c
new file mode 100644
index 0000000..bef48cf
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm_core.c
@@ -0,0 +1,765 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
+
+#ifdef USE_OPENSSL
+
+# ifdef USE_OPENSSL
+# include <openssl/des.h>
+# ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h>
+# endif
+# include <openssl/md5.h>
+# include <openssl/ssl.h>
+# include <openssl/rand.h>
+# else
+# include <des.h>
+# ifndef OPENSSL_NO_MD4
+# include <md4.h>
+# endif
+# include <md5.h>
+# include <ssl.h>
+# include <rand.h>
+# endif
+# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+# define DES_key_schedule des_key_schedule
+# define DES_cblock des_cblock
+# define DES_set_odd_parity des_set_odd_parity
+# define DES_set_key des_set_key
+# define DES_ecb_encrypt des_ecb_encrypt
+# define DESKEY(x) x
+# define DESKEYARG(x) x
+# else
+# define DESKEYARG(x) *x
+# define DESKEY(x) &x
+# endif
+
+#elif defined(USE_GNUTLS_NETTLE)
+
+# include <nettle/des.h>
+# include <nettle/md4.h>
+
+#elif defined(USE_GNUTLS)
+
+# include <gcrypt.h>
+# define MD5_DIGEST_LENGTH 16
+# define MD4_DIGEST_LENGTH 16
+
+#elif defined(USE_NSS)
+
+# include <nss.h>
+# include <pk11pub.h>
+# include <hasht.h>
+# include "curl_md4.h"
+# define MD5_DIGEST_LENGTH MD5_LENGTH
+
+#elif defined(USE_DARWINSSL)
+
+# include <CommonCrypto/CommonCryptor.h>
+# include <CommonCrypto/CommonDigest.h>
+
+#elif defined(USE_OS400CRYPTO)
+# include "cipher.mih" /* mih/cipher */
+# include "curl_md4.h"
+#elif defined(USE_WIN32_CRYPTO)
+# include <wincrypt.h>
+#else
+# error "Can't compile NTLM support without a crypto library."
+#endif
+
+#include "urldata.h"
+#include "non-ascii.h"
+#include "rawstr.h"
+#include "curl_ntlm_core.h"
+#include "curl_md5.h"
+#include "curl_hmac.h"
+#include "warnless.h"
+#include "curl_endian.h"
+#include "curl_des.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define NTLM_HMAC_MD5_LEN (16)
+#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
+#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
+
+/*
+* Turns a 56-bit key into being 64-bit wide.
+*/
+static void extend_key_56_to_64(const unsigned char *key_56, char *key)
+{
+ key[0] = key_56[0];
+ key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+ key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+ key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+ key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+ key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+ key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+ key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+}
+
+#ifdef USE_OPENSSL
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
+ * key schedule ks is also set.
+ */
+static void setup_des_key(const unsigned char *key_56,
+ DES_key_schedule DESKEYARG(ks))
+{
+ DES_cblock key;
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, (char *) key);
+
+ /* Set the key parity to odd */
+#if defined(HAVE_BORINGSSL)
+ Curl_des_set_odd_parity((unsigned char *) &key, sizeof(key));
+#else
+ DES_set_odd_parity(&key);
+#endif
+
+ /* Set the key */
+ DES_set_key(&key, ks);
+}
+
+#elif defined(USE_GNUTLS_NETTLE)
+
+static void setup_des_key(const unsigned char *key_56,
+ struct des_ctx *des)
+{
+ char key[8];
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, key);
+
+ /* Set the key parity to odd */
+ Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
+
+ /* Set the key */
+ des_set_key(des, (const uint8_t *) key);
+}
+
+#elif defined(USE_GNUTLS)
+
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
+ */
+static void setup_des_key(const unsigned char *key_56,
+ gcry_cipher_hd_t *des)
+{
+ char key[8];
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, key);
+
+ /* Set the key parity to odd */
+ Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
+
+ /* Set the key */
+ gcry_cipher_setkey(*des, key, sizeof(key));
+}
+
+#elif defined(USE_NSS)
+
+/*
+ * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
+ * the expanded key. The caller is responsible for giving 64 bit of valid
+ * data is IN and (at least) 64 bit large buffer as OUT.
+ */
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
+ PK11SlotInfo *slot = NULL;
+ char key[8]; /* expanded 64 bit key */
+ SECItem key_item;
+ PK11SymKey *symkey = NULL;
+ SECItem *param = NULL;
+ PK11Context *ctx = NULL;
+ int out_len; /* not used, required by NSS */
+ bool rv = FALSE;
+
+ /* use internal slot for DES encryption (requires NSS to be initialized) */
+ slot = PK11_GetInternalKeySlot();
+ if(!slot)
+ return FALSE;
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, key);
+
+ /* Set the key parity to odd */
+ Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
+
+ /* Import the key */
+ key_item.data = (unsigned char *)key;
+ key_item.len = sizeof(key);
+ symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
+ &key_item, NULL);
+ if(!symkey)
+ goto fail;
+
+ /* Create the DES encryption context */
+ param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
+ if(!param)
+ goto fail;
+ ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
+ if(!ctx)
+ goto fail;
+
+ /* Perform the encryption */
+ if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
+ (unsigned char *)in, /* inbuflen */ 8)
+ && SECSuccess == PK11_Finalize(ctx))
+ rv = /* all OK */ TRUE;
+
+fail:
+ /* cleanup */
+ if(ctx)
+ PK11_DestroyContext(ctx, PR_TRUE);
+ if(symkey)
+ PK11_FreeSymKey(symkey);
+ if(param)
+ SECITEM_FreeItem(param, PR_TRUE);
+ PK11_FreeSlot(slot);
+ return rv;
+}
+
+#elif defined(USE_DARWINSSL)
+
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ char key[8];
+ size_t out_len;
+ CCCryptorStatus err;
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, key);
+
+ /* Set the key parity to odd */
+ Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
+
+ /* Perform the encryption */
+ err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key,
+ kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out,
+ 8 /* outbuflen */, &out_len);
+
+ return err == kCCSuccess;
+}
+
+#elif defined(USE_OS400CRYPTO)
+
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ char key[8];
+ _CIPHER_Control_T ctl;
+
+ /* Setup the cipher control structure */
+ ctl.Func_ID = ENCRYPT_ONLY;
+ ctl.Data_Len = sizeof(key);
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, ctl.Crypto_Key);
+
+ /* Set the key parity to odd */
+ Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len);
+
+ /* Perform the encryption */
+ _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in);
+
+ return TRUE;
+}
+
+#elif defined(USE_WIN32_CRYPTO)
+
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ HCRYPTPROV hprov;
+ HCRYPTKEY hkey;
+ struct {
+ BLOBHEADER hdr;
+ unsigned int len;
+ char key[8];
+ } blob;
+ DWORD len = 8;
+
+ /* Acquire the crypto provider */
+ if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return FALSE;
+
+ /* Setup the key blob structure */
+ memset(&blob, 0, sizeof(blob));
+ blob.hdr.bType = PLAINTEXTKEYBLOB;
+ blob.hdr.bVersion = 2;
+ blob.hdr.aiKeyAlg = CALG_DES;
+ blob.len = sizeof(blob.key);
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, blob.key);
+
+ /* Set the key parity to odd */
+ Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key));
+
+ /* Import the key */
+ if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) {
+ CryptReleaseContext(hprov, 0);
+
+ return FALSE;
+ }
+
+ memcpy(out, in, 8);
+
+ /* Perform the encryption */
+ CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len);
+
+ CryptDestroyKey(hkey);
+ CryptReleaseContext(hprov, 0);
+
+ return TRUE;
+}
+
+#endif /* defined(USE_WIN32_CRYPTO) */
+
+ /*
+ * takes a 21 byte array and treats it as 3 56-bit DES keys. The
+ * 8 byte plaintext is encrypted with each key and the resulting 24
+ * bytes are stored in the results array.
+ */
+CURL_STATIC void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+ const unsigned char *plaintext,
+ unsigned char *results)
+{
+#ifdef USE_OPENSSL
+ DES_key_schedule ks;
+
+ setup_des_key(keys, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(keys + 7, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(keys + 14, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
+ DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS_NETTLE)
+ struct des_ctx des;
+ setup_des_key(keys, &des);
+ des_encrypt(&des, 8, results, plaintext);
+ setup_des_key(keys + 7, &des);
+ des_encrypt(&des, 8, results + 8, plaintext);
+ setup_des_key(keys + 14, &des);
+ des_encrypt(&des, 8, results + 16, plaintext);
+#elif defined(USE_GNUTLS)
+ gcry_cipher_hd_t des;
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys, &des);
+ gcry_cipher_encrypt(des, results, 8, plaintext, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys + 7, &des);
+ gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys + 14, &des);
+ gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
+ gcry_cipher_close(des);
+#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
+ || defined(USE_WIN32_CRYPTO)
+ encrypt_des(plaintext, results, keys);
+ encrypt_des(plaintext, results + 8, keys + 7);
+ encrypt_des(plaintext, results + 16, keys + 14);
+#endif
+}
+
+/*
+ * Set up lanmanager hashed password
+ */
+CURL_STATIC CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *lmbuffer /* 21 bytes */)
+{
+ CURLcode result;
+ unsigned char pw[14];
+ static const unsigned char magic[] = {
+ 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
+ };
+ size_t len = CURLMIN(strlen(password), 14);
+
+ Curl_strntoupper((char *)pw, password, len);
+ memset(&pw[len], 0, 14 - len);
+
+ /*
+ * The LanManager hashed password needs to be created using the
+ * password in the network encoding not the host encoding.
+ */
+ result = Curl_convert_to_network(data, (char *)pw, 14);
+ if(result)
+ return result;
+
+ {
+ /* Create LanManager hashed password. */
+
+#ifdef USE_OPENSSL
+ DES_key_schedule ks;
+
+ setup_des_key(pw, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(pw + 7, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
+ DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS_NETTLE)
+ struct des_ctx des;
+ setup_des_key(pw, &des);
+ des_encrypt(&des, 8, lmbuffer, magic);
+ setup_des_key(pw + 7, &des);
+ des_encrypt(&des, 8, lmbuffer + 8, magic);
+#elif defined(USE_GNUTLS)
+ gcry_cipher_hd_t des;
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(pw, &des);
+ gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(pw + 7, &des);
+ gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
+ gcry_cipher_close(des);
+#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
+ || defined(USE_WIN32_CRYPTO)
+ encrypt_des(magic, lmbuffer, pw);
+ encrypt_des(magic, lmbuffer + 8, pw + 7);
+#endif
+
+ memset(lmbuffer + 16, 0, 21 - 16);
+ }
+
+ return CURLE_OK;
+}
+
+#if USE_NTRESPONSES
+static void ascii_to_unicode_le(unsigned char *dest, const char *src,
+ size_t srclen)
+{
+ size_t i;
+ for(i = 0; i < srclen; i++) {
+ dest[2 * i] = (unsigned char)src[i];
+ dest[2 * i + 1] = '\0';
+ }
+}
+
+#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
+
+static void ascii_uppercase_to_unicode_le(unsigned char *dest,
+ const char *src, size_t srclen)
+{
+ size_t i;
+ for(i = 0; i < srclen; i++) {
+ dest[2 * i] = (unsigned char)(toupper(src[i]));
+ dest[2 * i + 1] = '\0';
+ }
+}
+
+#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */
+
+/*
+ * Set up nt hashed passwords
+ * @unittest: 1600
+ */
+CURL_STATIC CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *ntbuffer /* 21 bytes */)
+{
+ size_t len = strlen(password);
+ unsigned char *pw = malloc(len * 2);
+ CURLcode result;
+ if(!pw)
+ return CURLE_OUT_OF_MEMORY;
+
+ ascii_to_unicode_le(pw, password, len);
+
+ /*
+ * The NT hashed password needs to be created using the password in the
+ * network encoding not the host encoding.
+ */
+ result = Curl_convert_to_network(data, (char *)pw, len * 2);
+ if(result)
+ return result;
+
+ {
+ /* Create NT hashed password. */
+#ifdef USE_OPENSSL
+ MD4_CTX MD4pw;
+ MD4_Init(&MD4pw);
+ MD4_Update(&MD4pw, pw, 2 * len);
+ MD4_Final(ntbuffer, &MD4pw);
+#elif defined(USE_GNUTLS_NETTLE)
+ struct md4_ctx MD4pw;
+ md4_init(&MD4pw);
+ md4_update(&MD4pw, (unsigned int)(2 * len), pw);
+ md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer);
+#elif defined(USE_GNUTLS)
+ gcry_md_hd_t MD4pw;
+ gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
+ gcry_md_write(MD4pw, pw, 2 * len);
+ memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
+ gcry_md_close(MD4pw);
+#elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
+ Curl_md4it(ntbuffer, pw, 2 * len);
+#elif defined(USE_DARWINSSL)
+ (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
+#elif defined(USE_WIN32_CRYPTO)
+ HCRYPTPROV hprov;
+ if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT)) {
+ HCRYPTHASH hhash;
+ if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) {
+ DWORD length = 16;
+ CryptHashData(hhash, pw, (unsigned int)len * 2, 0);
+ CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0);
+ CryptDestroyHash(hhash);
+ }
+ CryptReleaseContext(hprov, 0);
+ }
+#endif
+
+ memset(ntbuffer + 16, 0, 21 - 16);
+ }
+
+ free(pw);
+
+ return CURLE_OK;
+}
+
+#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
+
+/* This returns the HMAC MD5 digest */
+CURL_STATIC CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
+ const unsigned char *data, unsigned int datalen,
+ unsigned char *output)
+{
+ HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
+
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Update the digest with the given challenge */
+ Curl_HMAC_update(ctxt, data, datalen);
+
+ /* Finalise the digest */
+ Curl_HMAC_final(ctxt, output);
+
+ return CURLE_OK;
+}
+
+/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
+ * (uppercase UserName + Domain) as the data
+ */
+CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
+ const char *domain, size_t domlen,
+ unsigned char *ntlmhash,
+ unsigned char *ntlmv2hash)
+{
+ /* Unicode representation */
+ size_t identity_len = (userlen + domlen) * 2;
+ unsigned char *identity = malloc(identity_len);
+ CURLcode result = CURLE_OK;
+
+ if(!identity)
+ return CURLE_OUT_OF_MEMORY;
+
+ ascii_uppercase_to_unicode_le(identity, user, userlen);
+ ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
+
+ result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
+ ntlmv2hash);
+
+ free(identity);
+
+ return result;
+}
+
+/*
+ * Curl_ntlm_core_mk_ntlmv2_resp()
+ *
+ * This creates the NTLMv2 response as set in the ntlm type-3 message.
+ *
+ * Parameters:
+ *
+ * ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
+ * challenge_client [in] - The client nonce (8 bytes)
+ * ntlm [in] - The ntlm data struct being used to read TargetInfo
+ and Server challenge received in the type-2 message
+ * ntresp [out] - The address where a pointer to newly allocated
+ * memory holding the NTLMv2 response.
+ * ntresp_len [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ struct ntlmdata *ntlm,
+ unsigned char **ntresp,
+ unsigned int *ntresp_len)
+{
+/* NTLMv2 response structure :
+------------------------------------------------------------------------------
+0 HMAC MD5 16 bytes
+------BLOB--------------------------------------------------------------------
+16 Signature 0x01010000
+20 Reserved long (0x00000000)
+24 Timestamp LE, 64-bit signed value representing the number of
+ tenths of a microsecond since January 1, 1601.
+32 Client Nonce 8 bytes
+40 Unknown 4 bytes
+44 Target Info N bytes (from the type-2 message)
+44+N Unknown 4 bytes
+------------------------------------------------------------------------------
+*/
+
+ unsigned int len = 0;
+ unsigned char *ptr = NULL;
+ unsigned char hmac_output[NTLM_HMAC_MD5_LEN];
+#if defined(HAVE_LONGLONG)
+ long long tw;
+#else
+ __int64 tw;
+#endif
+ CURLcode result = CURLE_OK;
+
+ /* Calculate the timestamp */
+#ifdef DEBUGBUILD
+ char *force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ tw = 11644473600ULL * 10000000ULL;
+ else
+#endif
+ tw = ((long long)time(NULL) + 11644473600ULL) * 10000000ULL;
+
+ /* Calculate the response len */
+ len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
+
+ /* Allocate the response */
+ ptr = malloc(len);
+ if(!ptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(ptr, 0, len);
+
+ /* Create the BLOB structure */
+ snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
+ NTLMv2_BLOB_SIGNATURE
+ "%c%c%c%c", /* Reserved = 0 */
+ 0, 0, 0, 0);
+
+ Curl_write64_le(tw, ptr + 24);
+ memcpy(ptr + 32, challenge_client, 8);
+ memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
+
+ /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
+ memcpy(ptr + 8, &ntlm->nonce[0], 8);
+ result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
+ NTLMv2_BLOB_LEN + 8, hmac_output);
+ if(result) {
+ free(ptr);
+ return result;
+ }
+
+ /* Concatenate the HMAC MD5 output with the BLOB */
+ memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN);
+
+ /* Return the response */
+ *ntresp = ptr;
+ *ntresp_len = len;
+
+ return result;
+}
+
+/*
+ * Curl_ntlm_core_mk_lmv2_resp()
+ *
+ * This creates the LMv2 response as used in the ntlm type-3 message.
+ *
+ * Parameters:
+ *
+ * ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
+ * challenge_client [in] - The client nonce (8 bytes)
+ * challenge_client [in] - The server challenge (8 bytes)
+ * lmresp [out] - The LMv2 response (24 bytes)
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ unsigned char *challenge_server,
+ unsigned char *lmresp)
+{
+ unsigned char data[16];
+ unsigned char hmac_output[16];
+ CURLcode result = CURLE_OK;
+
+ memcpy(&data[0], challenge_server, 8);
+ memcpy(&data[8], challenge_client, 8);
+
+ result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
+ if(result)
+ return result;
+
+ /* Concatenate the HMAC MD5 output with the client nonce */
+ memcpy(lmresp, hmac_output, 16);
+ memcpy(lmresp+16, challenge_client, 8);
+
+ return result;
+}
+
+#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */
+
+#endif /* USE_NTRESPONSES */
+
+#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
+
+#endif /* USE_NTLM */
diff --git a/libcurl/src/lib/curl_ntlm_core.h b/libcurl/src/lib/curl_ntlm_core.h
new file mode 100644
index 0000000..f089cef
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm_core.h
@@ -0,0 +1,106 @@
+#ifndef HEADER_CURL_NTLM_CORE_H
+#define HEADER_CURL_NTLM_CORE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM)
+
+#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
+
+#ifdef USE_OPENSSL
+# if !defined(OPENSSL_VERSION_NUMBER) && \
+ !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H)
+# error "curl_ntlm_core.h shall not be included before OpenSSL headers."
+# endif
+# ifdef OPENSSL_NO_MD4
+# define USE_NTRESPONSES 0
+# define USE_NTLM2SESSION 0
+# define USE_NTLM_V2 0
+# endif
+#endif
+
+/* Define USE_NTRESPONSES to 1 in order to make the type-3 message include
+ * the NT response message. */
+#ifndef USE_NTRESPONSES
+#define USE_NTRESPONSES 1
+#endif
+
+/* Define USE_NTLM2SESSION to 1 in order to make the type-3 message include the
+ NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a
+ Crypto engine that we have curl_ssl_md5sum() for. */
+#if !defined(USE_NTLM2SESSION) && USE_NTRESPONSES && !defined(USE_WIN32_CRYPTO)
+#define USE_NTLM2SESSION 1
+#endif
+
+/* Define USE_NTLM_V2 to 1 in order to allow the type-3 message to include the
+ LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1
+ and support for 64-bit integers. */
+#if !defined(USE_NTLM_V2) && USE_NTRESPONSES && (CURL_SIZEOF_CURL_OFF_T > 4)
+#define USE_NTLM_V2 1
+#endif
+
+CURL_STATIC void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+ const unsigned char *plaintext,
+ unsigned char *results);
+
+CURL_STATIC CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *lmbuffer /* 21 bytes */);
+
+#if USE_NTRESPONSES
+CURL_STATIC CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *ntbuffer /* 21 bytes */);
+
+#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
+
+CURL_STATIC CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
+ const unsigned char *data, unsigned int datalen,
+ unsigned char *output);
+
+CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
+ const char *domain, size_t domlen,
+ unsigned char *ntlmhash,
+ unsigned char *ntlmv2hash);
+
+CURL_STATIC CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ struct ntlmdata *ntlm,
+ unsigned char **ntresp,
+ unsigned int *ntresp_len);
+
+CURL_STATIC CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ unsigned char *challenge_server,
+ unsigned char *lmresp);
+
+#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */
+
+#endif /* USE_NTRESPONSES */
+
+#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
+
+#endif /* USE_NTLM */
+
+#endif /* HEADER_CURL_NTLM_CORE_H */
diff --git a/libcurl/src/lib/curl_ntlm_msgs.c b/libcurl/src/lib/curl_ntlm_msgs.c
new file mode 100644
index 0000000..c46f2a0
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm_msgs.c
@@ -0,0 +1,819 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#include "urldata.h"
+#include "non-ascii.h"
+#include "sendf.h"
+#include "curl_base64.h"
+#include "curl_ntlm_core.h"
+#include "curl_gethostname.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+
+#include "vtls/vtls.h"
+
+#ifdef USE_NSS
+#include "vtls/nssg.h" /* for Curl_nss_force_init() */
+#endif
+
+#define BUILDING_CURL_NTLM_MSGS_C
+#include "curl_ntlm_msgs.h"
+#include "curl_sasl.h"
+#include "curl_endian.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* "NTLMSSP" signature is always in ASCII regardless of the platform */
+#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
+
+#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
+#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
+ (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+static void ntlm_print_flags(FILE *handle, unsigned long flags)
+{
+ if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
+ if(flags & NTLMFLAG_NEGOTIATE_OEM)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
+ if(flags & NTLMFLAG_REQUEST_TARGET)
+ fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
+ if(flags & (1<<3))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
+ if(flags & NTLMFLAG_NEGOTIATE_SIGN)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
+ if(flags & NTLMFLAG_NEGOTIATE_SEAL)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
+ if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
+ if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
+ if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
+ if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
+ if(flags & (1<<10))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
+ if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
+ if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
+ if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
+ if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
+ if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
+ if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
+ if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
+ if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
+ if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
+ if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
+ fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
+ if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
+ fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
+ if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
+ fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
+ if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
+ if(flags & (1<<24))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
+ if(flags & (1<<25))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
+ if(flags & (1<<26))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
+ if(flags & (1<<27))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
+ if(flags & (1<<28))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
+ if(flags & NTLMFLAG_NEGOTIATE_128)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
+ if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
+ if(flags & NTLMFLAG_NEGOTIATE_56)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
+}
+
+static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
+{
+ const char *p = buf;
+ (void)handle;
+ fprintf(stderr, "0x");
+ while(len-- > 0)
+ fprintf(stderr, "%02.2x", (unsigned int)*p++);
+}
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+/*
+ * ntlm_decode_type2_target()
+ *
+ * This is used to decode the "target info" in the ntlm type-2 message
+ * received.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * buffer [in] - The decoded type-2 message.
+ * size [in] - The input buffer size, at least 32 bytes.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode ntlm_decode_type2_target(struct SessionHandle *data,
+ unsigned char *buffer,
+ size_t size,
+ struct ntlmdata *ntlm)
+{
+ unsigned short target_info_len = 0;
+ unsigned int target_info_offset = 0;
+
+ Curl_safefree(ntlm->target_info);
+ ntlm->target_info_len = 0;
+
+ if(size >= 48) {
+ target_info_len = Curl_read16_le(&buffer[40]);
+ target_info_offset = Curl_read32_le(&buffer[44]);
+ if(target_info_len > 0) {
+ if(((target_info_offset + target_info_len) > size) ||
+ (target_info_offset < 48)) {
+ infof(data, "NTLM handshake failure (bad type-2 message). "
+ "Target Info Offset Len is set incorrect by the peer\n");
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ ntlm->target_info = malloc(target_info_len);
+ if(!ntlm->target_info)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
+ }
+ }
+
+ ntlm->target_info_len = target_info_len;
+
+ return CURLE_OK;
+}
+
+/*
+ NTLM message structure notes:
+
+ A 'short' is a 'network short', a little-endian 16-bit unsigned value.
+
+ A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
+
+ A 'security buffer' represents a triplet used to point to a buffer,
+ consisting of two shorts and one long:
+
+ 1. A 'short' containing the length of the buffer content in bytes.
+ 2. A 'short' containing the allocated space for the buffer in bytes.
+ 3. A 'long' containing the offset to the start of the buffer in bytes,
+ from the beginning of the NTLM message.
+*/
+
+/*
+ * Curl_sasl_decode_ntlm_type2_message()
+ *
+ * This is used to decode an already encoded NTLM type-2 message. The message
+ * is first decoded from a base64 string into a raw NTLM message and checked
+ * for validity before the appropriate data for creating a type-3 message is
+ * written to the given NTLM data structure.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * type2msg [in] - The base64 encoded type-2 message.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
+ const char *header,
+ struct ntlmdata *ntlm)
+{
+ static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
+
+ /* NTLM type-2 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x02000000)
+ 12 Target Name security buffer
+ 20 Flags long
+ 24 Challenge 8 bytes
+ (32) Context 8 bytes (two consecutive longs) (*)
+ (40) Target Information security buffer (*)
+ (48) OS Version Structure 8 bytes (*)
+ 32 (48) (56) Start of data block (*)
+ (*) -> Optional
+ */
+
+ CURLcode result = CURLE_OK;
+ unsigned char *type2 = NULL;
+ size_t type2_len = 0;
+
+#if defined(USE_NSS)
+ /* Make sure the crypto backend is initialized */
+ result = Curl_nss_force_init(data);
+ if(result)
+ return result;
+#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void)data;
+#endif
+
+ /* Decode the base-64 encoded type-2 message */
+ if(strlen(type2msg) && *type2msg != '=') {
+ result = Curl_base64_decode(type2msg, &type2, &type2_len);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid type-2 message */
+ if(!type2) {
+ infof(data, "NTLM handshake failure (empty type-2 message)\n");
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ ntlm->flags = 0;
+
+ if((type2_len < 32) ||
+ (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
+ (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
+ /* This was not a good enough type-2 message */
+ free(type2);
+ infof(data, "NTLM handshake failure (bad type-2 message)\n");
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ ntlm->flags = Curl_read32_le(&type2[20]);
+ memcpy(ntlm->nonce, &type2[24], 8);
+
+ if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
+ result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
+ if(result) {
+ free(type2);
+ infof(data, "NTLM handshake failure (bad type-2 message)\n");
+ return result;
+ }
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
+ ntlm_print_flags(stderr, ntlm->flags);
+ fprintf(stderr, "\n nonce=");
+ ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
+ fprintf(stderr, "\n****\n");
+ fprintf(stderr, "**** Header %s\n ", header);
+ });
+
+ free(type2);
+
+ return result;
+}
+
+/* copy the source to the destination and fill in zeroes in every
+ other destination byte! */
+static void unicodecpy(unsigned char *dest, const char *src, size_t length)
+{
+ size_t i;
+ for(i = 0; i < length; i++) {
+ dest[2 * i] = (unsigned char)src[i];
+ dest[2 * i + 1] = '\0';
+ }
+}
+
+/*
+ * Curl_sasl_create_ntlm_type1_message()
+ *
+ * This is used to generate an already encoded NTLM type-1 message ready for
+ * sending to the recipient using the appropriate compile time crypto API.
+ *
+ * Parameters:
+ *
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen)
+{
+ /* NTLM type-1 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x01000000)
+ 12 Flags long
+ (16) Supplied Domain security buffer (*)
+ (24) Supplied Workstation security buffer (*)
+ (32) OS Version Structure 8 bytes (*)
+ (32) (40) Start of data block (*)
+ (*) -> Optional
+ */
+
+ size_t size;
+
+ unsigned char ntlmbuf[NTLM_BUFSIZE];
+ const char *host = ""; /* empty */
+ const char *domain = ""; /* empty */
+ size_t hostlen = 0;
+ size_t domlen = 0;
+ size_t hostoff = 0;
+ size_t domoff = hostoff + hostlen; /* This is 0: remember that host and
+ domain are empty */
+ (void)userp;
+ (void)passwdp;
+
+ /* Clean up any former leftovers and initialise to defaults */
+ Curl_sasl_ntlm_cleanup(ntlm);
+
+#if USE_NTRESPONSES && USE_NTLM2SESSION
+#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
+#else
+#define NTLM2FLAG 0
+#endif
+ snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x01%c%c%c" /* 32-bit type = 1 */
+ "%c%c%c%c" /* 32-bit NTLM flag field */
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host name offset */
+ "%c%c" /* 2 zeroes */
+ "%s" /* host name */
+ "%s", /* domain string */
+ 0, /* trailing zero */
+ 0, 0, 0, /* part of type-1 long */
+
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0, 0,
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0, 0,
+ host, /* this is empty */
+ domain /* this is empty */);
+
+ /* Initial packet length */
+ size = 32 + hostlen + domlen;
+
+ DEBUG_OUT({
+ fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
+ "0x%08.8x ",
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+ ntlm_print_flags(stderr,
+ NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+ fprintf(stderr, "\n****\n");
+ });
+
+ /* Return with binary blob encoded into base64 */
+ return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+}
+
+/*
+ * Curl_sasl_create_ntlm_type3_message()
+ *
+ * This is used to generate an already encoded NTLM type-3 message ready for
+ * sending to the recipient using the appropriate compile time crypto API.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen)
+{
+ /* NTLM type-3 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x03000000)
+ 12 LM/LMv2 Response security buffer
+ 20 NTLM/NTLMv2 Response security buffer
+ 28 Target Name security buffer
+ 36 User Name security buffer
+ 44 Workstation Name security buffer
+ (52) Session Key security buffer (*)
+ (60) Flags long (*)
+ (64) OS Version Structure 8 bytes (*)
+ 52 (64) (72) Start of data block
+ (*) -> Optional
+ */
+
+ CURLcode result = CURLE_OK;
+ size_t size;
+ unsigned char ntlmbuf[NTLM_BUFSIZE];
+ int lmrespoff;
+ unsigned char lmresp[24]; /* fixed-size */
+#if USE_NTRESPONSES
+ int ntrespoff;
+ unsigned int ntresplen = 24;
+ unsigned char ntresp[24]; /* fixed-size */
+ unsigned char *ptr_ntresp = &ntresp[0];
+ unsigned char *ntlmv2resp = NULL;
+#endif
+ bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
+ char host[HOSTNAME_MAX + 1] = "";
+ const char *user;
+ const char *domain = "";
+ size_t hostoff = 0;
+ size_t useroff = 0;
+ size_t domoff = 0;
+ size_t hostlen = 0;
+ size_t userlen = 0;
+ size_t domlen = 0;
+
+ user = strchr(userp, '\\');
+ if(!user)
+ user = strchr(userp, '/');
+
+ if(user) {
+ domain = userp;
+ domlen = (user - domain);
+ user++;
+ }
+ else
+ user = userp;
+
+ if(user)
+ userlen = strlen(user);
+
+ /* Get the machine's un-qualified host name as NTLM doesn't like the fully
+ qualified domain name */
+ if(Curl_gethostname(host, sizeof(host))) {
+ infof(data, "gethostname() failed, continuing without!\n");
+ hostlen = 0;
+ }
+ else {
+ hostlen = strlen(host);
+ }
+
+#if USE_NTRESPONSES && USE_NTLM_V2
+ if(ntlm->target_info_len) {
+ unsigned char ntbuffer[0x18];
+ unsigned int entropy[2];
+ unsigned char ntlmv2hash[0x18];
+
+ entropy[0] = Curl_rand(data);
+ entropy[1] = Curl_rand(data);
+
+ result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
+ if(result)
+ return result;
+
+ result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
+ ntbuffer, ntlmv2hash);
+ if(result)
+ return result;
+
+ /* LMv2 response */
+ result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
+ (unsigned char *)&entropy[0],
+ &ntlm->nonce[0], lmresp);
+ if(result)
+ return result;
+
+ /* NTLMv2 response */
+ result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
+ (unsigned char *)&entropy[0],
+ ntlm, &ntlmv2resp, &ntresplen);
+ if(result)
+ return result;
+
+ ptr_ntresp = ntlmv2resp;
+ }
+ else
+#endif
+
+#if USE_NTRESPONSES && USE_NTLM2SESSION
+ /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
+ if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
+ unsigned char ntbuffer[0x18];
+ unsigned char tmp[0x18];
+ unsigned char md5sum[MD5_DIGEST_LENGTH];
+ unsigned int entropy[2];
+
+ /* Need to create 8 bytes random data */
+ entropy[0] = Curl_rand(data);
+ entropy[1] = Curl_rand(data);
+
+ /* 8 bytes random data as challenge in lmresp */
+ memcpy(lmresp, entropy, 8);
+
+ /* Pad with zeros */
+ memset(lmresp + 8, 0, 0x10);
+
+ /* Fill tmp with challenge(nonce?) + entropy */
+ memcpy(tmp, &ntlm->nonce[0], 8);
+ memcpy(tmp + 8, entropy, 8);
+
+ result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
+ if(!result)
+ /* We shall only use the first 8 bytes of md5sum, but the des code in
+ Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
+ result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
+ if(result)
+ return result;
+
+ Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
+
+ /* End of NTLM2 Session code */
+
+ }
+ else
+#endif
+ {
+
+#if USE_NTRESPONSES
+ unsigned char ntbuffer[0x18];
+#endif
+ unsigned char lmbuffer[0x18];
+
+#if USE_NTRESPONSES
+ result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
+ if(result)
+ return result;
+
+ Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
+#endif
+
+ result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
+ if(result)
+ return result;
+
+ Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
+
+ /* A safer but less compatible alternative is:
+ * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
+ * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
+ }
+
+ if(unicode) {
+ domlen = domlen * 2;
+ userlen = userlen * 2;
+ hostlen = hostlen * 2;
+ }
+
+ lmrespoff = 64; /* size of the message header */
+#if USE_NTRESPONSES
+ ntrespoff = lmrespoff + 0x18;
+ domoff = ntrespoff + ntresplen;
+#else
+ domoff = lmrespoff + 0x18;
+#endif
+ useroff = domoff + domlen;
+ hostoff = useroff + userlen;
+
+ /* Create the big type-3 message binary blob */
+ size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x03%c%c%c" /* 32-bit type = 3 */
+
+ "%c%c" /* LanManager length */
+ "%c%c" /* LanManager allocated space */
+ "%c%c" /* LanManager offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* NT-response length */
+ "%c%c" /* NT-response allocated space */
+ "%c%c" /* NT-response offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* user length */
+ "%c%c" /* user allocated space */
+ "%c%c" /* user offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* session key length (unknown purpose) */
+ "%c%c" /* session key allocated space (unknown purpose) */
+ "%c%c" /* session key offset (unknown purpose) */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c%c%c", /* flags */
+
+ /* domain string */
+ /* user string */
+ /* host string */
+ /* LanManager response */
+ /* NT response */
+
+ 0, /* zero termination */
+ 0, 0, 0, /* type-3 long, the 24 upper bits */
+
+ SHORTPAIR(0x18), /* LanManager response length, twice */
+ SHORTPAIR(0x18),
+ SHORTPAIR(lmrespoff),
+ 0x0, 0x0,
+
+#if USE_NTRESPONSES
+ SHORTPAIR(ntresplen), /* NT-response length, twice */
+ SHORTPAIR(ntresplen),
+ SHORTPAIR(ntrespoff),
+ 0x0, 0x0,
+#else
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+#endif
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0x0, 0x0,
+
+ SHORTPAIR(userlen),
+ SHORTPAIR(userlen),
+ SHORTPAIR(useroff),
+ 0x0, 0x0,
+
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0x0, 0x0,
+
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+
+ LONGQUARTET(ntlm->flags));
+
+ DEBUGASSERT(size == 64);
+ DEBUGASSERT(size == (size_t)lmrespoff);
+
+ /* We append the binary hashes */
+ if(size < (NTLM_BUFSIZE - 0x18)) {
+ memcpy(&ntlmbuf[size], lmresp, 0x18);
+ size += 0x18;
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "**** TYPE3 header lmresp=");
+ ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
+ });
+
+#if USE_NTRESPONSES
+ if(size < (NTLM_BUFSIZE - ntresplen)) {
+ DEBUGASSERT(size == (size_t)ntrespoff);
+ memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
+ size += ntresplen;
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "\n ntresp=");
+ ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
+ });
+
+ free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
+
+#endif
+
+ DEBUG_OUT({
+ fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
+ LONGQUARTET(ntlm->flags), ntlm->flags);
+ ntlm_print_flags(stderr, ntlm->flags);
+ fprintf(stderr, "\n****\n");
+ });
+
+ /* Make sure that the domain, user and host strings fit in the
+ buffer before we copy them there. */
+ if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
+ failf(data, "user + domain + host name too big");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ DEBUGASSERT(size == domoff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], domain, domlen / 2);
+ else
+ memcpy(&ntlmbuf[size], domain, domlen);
+
+ size += domlen;
+
+ DEBUGASSERT(size == useroff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], user, userlen / 2);
+ else
+ memcpy(&ntlmbuf[size], user, userlen);
+
+ size += userlen;
+
+ DEBUGASSERT(size == hostoff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], host, hostlen / 2);
+ else
+ memcpy(&ntlmbuf[size], host, hostlen);
+
+ size += hostlen;
+
+ /* Convert domain, user, and host to ASCII but leave the rest as-is */
+ result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
+ size - domoff);
+ if(result)
+ return CURLE_CONV_FAILED;
+
+ /* Return with binary blob encoded into base64 */
+ result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+
+ Curl_sasl_ntlm_cleanup(ntlm);
+
+ return result;
+}
+
+#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
diff --git a/libcurl/src/lib/curl_ntlm_msgs.h b/libcurl/src/lib/curl_ntlm_msgs.h
new file mode 100644
index 0000000..2a71431
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm_msgs.h
@@ -0,0 +1,143 @@
+#ifndef HEADER_CURL_NTLM_MSGS_H
+#define HEADER_CURL_NTLM_MSGS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NTLM
+
+/* NTLM buffer fixed size, large enough for long user + host + domain */
+#define NTLM_BUFSIZE 1024
+
+/* Stuff only required for curl_ntlm_msgs.c */
+#ifdef BUILDING_CURL_NTLM_MSGS_C
+
+/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
+
+#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
+/* Indicates that Unicode strings are supported for use in security buffer
+ data. */
+
+#define NTLMFLAG_NEGOTIATE_OEM (1<<1)
+/* Indicates that OEM strings are supported for use in security buffer data. */
+
+#define NTLMFLAG_REQUEST_TARGET (1<<2)
+/* Requests that the server's authentication realm be included in the Type 2
+ message. */
+
+/* unknown (1<<3) */
+#define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
+/* Specifies that authenticated communication between the client and server
+ should carry a digital signature (message integrity). */
+
+#define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
+/* Specifies that authenticated communication between the client and server
+ should be encrypted (message confidentiality). */
+
+#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
+/* Indicates that datagram authentication is being used. */
+
+#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
+/* Indicates that the LAN Manager session key should be used for signing and
+ sealing authenticated communications. */
+
+#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
+/* unknown purpose */
+
+#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
+/* Indicates that NTLM authentication is being used. */
+
+/* unknown (1<<10) */
+
+#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11)
+/* Sent by the client in the Type 3 message to indicate that an anonymous
+ context has been established. This also affects the response fields. */
+
+#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
+/* Sent by the client in the Type 1 message to indicate that a desired
+ authentication realm is included in the message. */
+
+#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
+/* Sent by the client in the Type 1 message to indicate that the client
+ workstation's name is included in the message. */
+
+#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
+/* Sent by the server to indicate that the server and client are on the same
+ machine. Implies that the client may use a pre-established local security
+ context rather than responding to the challenge. */
+
+#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
+/* Indicates that authenticated communication between the client and server
+ should be signed with a "dummy" signature. */
+
+#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
+/* Sent by the server in the Type 2 message to indicate that the target
+ authentication realm is a domain. */
+
+#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
+/* Sent by the server in the Type 2 message to indicate that the target
+ authentication realm is a server. */
+
+#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
+/* Sent by the server in the Type 2 message to indicate that the target
+ authentication realm is a share. Presumably, this is for share-level
+ authentication. Usage is unclear. */
+
+#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
+/* Indicates that the NTLM2 signing and sealing scheme should be used for
+ protecting authenticated communications. */
+
+#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
+/* unknown purpose */
+
+#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
+/* unknown purpose */
+
+#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
+/* unknown purpose */
+
+#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
+/* Sent by the server in the Type 2 message to indicate that it is including a
+ Target Information block in the message. */
+
+/* unknown (1<24) */
+/* unknown (1<25) */
+/* unknown (1<26) */
+/* unknown (1<27) */
+/* unknown (1<28) */
+
+#define NTLMFLAG_NEGOTIATE_128 (1<<29)
+/* Indicates that 128-bit encryption is supported. */
+
+#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
+/* Indicates that the client will provide an encrypted master key in
+ the "Session Key" field of the Type 3 message. */
+
+#define NTLMFLAG_NEGOTIATE_56 (1<<31)
+/* Indicates that 56-bit encryption is supported. */
+
+#endif /* BUILDING_CURL_NTLM_MSGS_C */
+
+#endif /* USE_NTLM */
+
+#endif /* HEADER_CURL_NTLM_MSGS_H */
diff --git a/libcurl/src/lib/curl_ntlm_wb.c b/libcurl/src/lib/curl_ntlm_wb.c
new file mode 100644
index 0000000..b209c53
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm_wb.c
@@ -0,0 +1,431 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
+ defined(NTLM_WB_ENABLED)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "select.h"
+#include "curl_ntlm_msgs.h"
+#include "curl_ntlm_wb.h"
+#include "url.h"
+#include "strerror.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+/* Portable 'sclose_nolog' used only in child process instead of 'sclose'
+ to avoid fooling the socket leak detector */
+#if defined(HAVE_CLOSESOCKET)
+# define sclose_nolog(x) closesocket((x))
+#elif defined(HAVE_CLOSESOCKET_CAMEL)
+# define sclose_nolog(x) CloseSocket((x))
+#else
+# define sclose_nolog(x) close((x))
+#endif
+
+CURL_STATIC void Curl_ntlm_wb_cleanup(struct connectdata *conn)
+{
+ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
+ sclose(conn->ntlm_auth_hlpr_socket);
+ conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+ }
+
+ if(conn->ntlm_auth_hlpr_pid) {
+ int i;
+ for(i = 0; i < 4; i++) {
+ pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG);
+ if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD)
+ break;
+ switch(i) {
+ case 0:
+ kill(conn->ntlm_auth_hlpr_pid, SIGTERM);
+ break;
+ case 1:
+ /* Give the process another moment to shut down cleanly before
+ bringing down the axe */
+ Curl_wait_ms(1);
+ break;
+ case 2:
+ kill(conn->ntlm_auth_hlpr_pid, SIGKILL);
+ break;
+ case 3:
+ break;
+ }
+ }
+ conn->ntlm_auth_hlpr_pid = 0;
+ }
+
+ free(conn->challenge_header);
+ conn->challenge_header = NULL;
+ free(conn->response_header);
+ conn->response_header = NULL;
+}
+
+static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
+{
+ curl_socket_t sockfds[2];
+ pid_t child_pid;
+ const char *username;
+ char *slash, *domain = NULL;
+ const char *ntlm_auth = NULL;
+ char *ntlm_auth_alloc = NULL;
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
+ struct passwd pw, *pw_res;
+ char pwbuf[1024];
+#endif
+ int error;
+
+ /* Return if communication with ntlm_auth already set up */
+ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
+ conn->ntlm_auth_hlpr_pid)
+ return CURLE_OK;
+
+ username = userp;
+ /* The real ntlm_auth really doesn't like being invoked with an
+ empty username. It won't make inferences for itself, and expects
+ the client to do so (mostly because it's really designed for
+ servers like squid to use for auth, and client support is an
+ afterthought for it). So try hard to provide a suitable username
+ if we don't already have one. But if we can't, provide the
+ empty one anyway. Perhaps they have an implementation of the
+ ntlm_auth helper which *doesn't* need it so we might as well try */
+ if(!username || !username[0]) {
+ username = getenv("NTLMUSER");
+ if(!username || !username[0])
+ username = getenv("LOGNAME");
+ if(!username || !username[0])
+ username = getenv("USER");
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
+ if((!username || !username[0]) &&
+ !getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) &&
+ pw_res) {
+ username = pw.pw_name;
+ }
+#endif
+ if(!username || !username[0])
+ username = userp;
+ }
+ slash = strpbrk(username, "\\/");
+ if(slash) {
+ if((domain = strdup(username)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ slash = domain + (slash - username);
+ *slash = '\0';
+ username = username + (slash - domain) + 1;
+ }
+
+ /* For testing purposes, when DEBUGBUILD is defined and environment
+ variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform
+ NTLM challenge/response which only accepts commands and output
+ strings pre-written in test case definitions */
+#ifdef DEBUGBUILD
+ ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE");
+ if(ntlm_auth_alloc)
+ ntlm_auth = ntlm_auth_alloc;
+ else
+#endif
+ ntlm_auth = NTLM_WB_FILE;
+
+ if(access(ntlm_auth, X_OK) != 0) {
+ error = ERRNO;
+ failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
+ ntlm_auth, error, Curl_strerror(conn, error));
+ goto done;
+ }
+
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
+ error = ERRNO;
+ failf(conn->data, "Could not open socket pair. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ goto done;
+ }
+
+ child_pid = fork();
+ if(child_pid == -1) {
+ error = ERRNO;
+ sclose(sockfds[0]);
+ sclose(sockfds[1]);
+ failf(conn->data, "Could not fork. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ goto done;
+ }
+ else if(!child_pid) {
+ /*
+ * child process
+ */
+
+ /* Don't use sclose in the child since it fools the socket leak detector */
+ sclose_nolog(sockfds[0]);
+ if(dup2(sockfds[1], STDIN_FILENO) == -1) {
+ error = ERRNO;
+ failf(conn->data, "Could not redirect child stdin. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
+ error = ERRNO;
+ failf(conn->data, "Could not redirect child stdout. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ if(domain)
+ execl(ntlm_auth, ntlm_auth,
+ "--helper-protocol", "ntlmssp-client-1",
+ "--use-cached-creds",
+ "--username", username,
+ "--domain", domain,
+ NULL);
+ else
+ execl(ntlm_auth, ntlm_auth,
+ "--helper-protocol", "ntlmssp-client-1",
+ "--use-cached-creds",
+ "--username", username,
+ NULL);
+
+ error = ERRNO;
+ sclose_nolog(sockfds[1]);
+ failf(conn->data, "Could not execl(). errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ sclose(sockfds[1]);
+ conn->ntlm_auth_hlpr_socket = sockfds[0];
+ conn->ntlm_auth_hlpr_pid = child_pid;
+ free(domain);
+ free(ntlm_auth_alloc);
+ return CURLE_OK;
+
+done:
+ free(domain);
+ free(ntlm_auth_alloc);
+ return CURLE_REMOTE_ACCESS_DENIED;
+}
+
+static CURLcode ntlm_wb_response(struct connectdata *conn,
+ const char *input, curlntlm state)
+{
+ char *buf = malloc(NTLM_BUFSIZE);
+ size_t len_in = strlen(input), len_out = 0;
+
+ if(!buf)
+ return CURLE_OUT_OF_MEMORY;
+
+ while(len_in > 0) {
+ ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
+ if(written == -1) {
+ /* Interrupted by a signal, retry it */
+ if(errno == EINTR)
+ continue;
+ /* write failed if other errors happen */
+ goto done;
+ }
+ input += written;
+ len_in -= written;
+ }
+ /* Read one line */
+ while(1) {
+ ssize_t size;
+ char *newbuf;
+
+ size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
+ if(size == -1) {
+ if(errno == EINTR)
+ continue;
+ goto done;
+ }
+ else if(size == 0)
+ goto done;
+
+ len_out += size;
+ if(buf[len_out - 1] == '\n') {
+ buf[len_out - 1] = '\0';
+ break;
+ }
+ newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
+ if(!newbuf) {
+ free(buf);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ buf = newbuf;
+ }
+
+ /* Samba/winbind installed but not configured */
+ if(state == NTLMSTATE_TYPE1 &&
+ len_out == 3 &&
+ buf[0] == 'P' && buf[1] == 'W')
+ return CURLE_REMOTE_ACCESS_DENIED;
+ /* invalid response */
+ if(len_out < 4)
+ goto done;
+ if(state == NTLMSTATE_TYPE1 &&
+ (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
+ goto done;
+ if(state == NTLMSTATE_TYPE2 &&
+ (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') &&
+ (buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
+ goto done;
+
+ conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
+ free(buf);
+ return CURLE_OK;
+done:
+ free(buf);
+ return CURLE_REMOTE_ACCESS_DENIED;
+}
+
+/*
+ * This is for creating ntlm header output by delegating challenge/response
+ * to Samba's winbind daemon helper ntlm_auth.
+ */
+CURL_STATIC CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
+ bool proxy)
+{
+ /* point to the address of the pointer that holds the string to send to the
+ server, which is for a plain host or for a HTTP proxy */
+ char **allocuserpwd;
+ /* point to the name and password for this */
+ const char *userp;
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ struct auth *authp;
+
+ CURLcode res = CURLE_OK;
+ char *input;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->data);
+
+ if(proxy) {
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ ntlm = &conn->proxyntlm;
+ authp = &conn->data->state.authproxy;
+ }
+ else {
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ ntlm = &conn->ntlm;
+ authp = &conn->data->state.authhost;
+ }
+ authp->done = FALSE;
+
+ /* not set means empty */
+ if(!userp)
+ userp="";
+
+ switch(ntlm->state) {
+ case NTLMSTATE_TYPE1:
+ default:
+ /* Use Samba's 'winbind' daemon to support NTLM authentication,
+ * by delegating the NTLM challenge/response protocal to a helper
+ * in ntlm_auth.
+ * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
+ * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
+ * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
+ * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this
+ * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute
+ * filename of ntlm_auth helper.
+ * If NTLM authentication using winbind fails, go back to original
+ * request handling process.
+ */
+ /* Create communication with ntlm_auth */
+ res = ntlm_wb_init(conn, userp);
+ if(res)
+ return res;
+ res = ntlm_wb_response(conn, "YR\n", ntlm->state);
+ if(res)
+ return res;
+
+ free(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+ proxy ? "Proxy-" : "",
+ conn->response_header);
+ DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
+ free(conn->response_header);
+ conn->response_header = NULL;
+ break;
+ case NTLMSTATE_TYPE2:
+ input = aprintf("TT %s\n", conn->challenge_header);
+ if(!input)
+ return CURLE_OUT_OF_MEMORY;
+ res = ntlm_wb_response(conn, input, ntlm->state);
+ free(input);
+ input = NULL;
+ if(res)
+ return res;
+
+ free(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+ proxy ? "Proxy-" : "",
+ conn->response_header);
+ DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
+ ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
+ authp->done = TRUE;
+ Curl_ntlm_wb_cleanup(conn);
+ break;
+ case NTLMSTATE_TYPE3:
+ /* connection is already authenticated,
+ * don't send a header in future requests */
+ free(*allocuserpwd);
+ *allocuserpwd=NULL;
+ authp->done = TRUE;
+ break;
+ }
+
+ return CURLE_OK;
+}
+
+#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
diff --git a/libcurl/src/lib/curl_ntlm_wb.h b/libcurl/src/lib/curl_ntlm_wb.h
new file mode 100644
index 0000000..f4dd4e9
--- /dev/null
+++ b/libcurl/src/lib/curl_ntlm_wb.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_NTLM_WB_H
+#define HEADER_CURL_NTLM_WB_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
+ defined(NTLM_WB_ENABLED)
+
+/* this is for creating ntlm header output by delegating challenge/response
+ to Samba's winbind daemon helper ntlm_auth */
+CURL_STATIC CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
+
+CURL_STATIC void Curl_ntlm_wb_cleanup(struct connectdata *conn);
+
+#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
+
+#endif /* HEADER_CURL_NTLM_WB_H */
diff --git a/libcurl/src/lib/curl_printf.h b/libcurl/src/lib/curl_printf.h
new file mode 100644
index 0000000..086923f
--- /dev/null
+++ b/libcurl/src/lib/curl_printf.h
@@ -0,0 +1,56 @@
+#ifndef HEADER_CURL_PRINTF_H
+#define HEADER_CURL_PRINTF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * This header should be included by ALL code in libcurl that uses any
+ * *rintf() functions.
+ */
+
+#include <curl/mprintf.h>
+
+# undef printf
+# undef fprintf
+# undef snprintf
+# undef vprintf
+# undef vfprintf
+# undef vsnprintf
+# undef aprintf
+# undef vaprintf
+# define printf curl_mprintf
+# define fprintf curl_mfprintf
+# define snprintf curl_msnprintf
+# define vprintf curl_mvprintf
+# define vfprintf curl_mvfprintf
+# define vsnprintf curl_mvsnprintf
+# define aprintf curl_maprintf
+# define vaprintf curl_mvaprintf
+
+/* We define away the sprintf functions unconditonally since we don't want
+ internal code to be using them, intentionally or by mistake!*/
+# undef sprintf
+# undef vsprintf
+# define sprintf sprintf_was_used
+# define vsprintf vsprintf_was_used
+
+#endif /* HEADER_CURL_PRINTF_H */
diff --git a/libcurl/src/lib/curl_rtmp.c b/libcurl/src/lib/curl_rtmp.c
new file mode 100644
index 0000000..2938972
--- /dev/null
+++ b/libcurl/src/lib/curl_rtmp.c
@@ -0,0 +1,306 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_LIBRTMP
+
+#include "urldata.h"
+#include "nonblock.h" /* for curlx_nonblock */
+#include "progress.h" /* for Curl_pgrsSetUploadSize */
+#include "transfer.h"
+#include "warnless.h"
+#include <curl/curl.h>
+#include <librtmp/rtmp.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef _WIN32
+#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
+#define SET_RCVTIMEO(tv,s) int tv = s*1000
+#else
+#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
+#endif
+
+#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
+
+static CURLcode rtmp_setup_connection(struct connectdata *conn);
+static CURLcode rtmp_do(struct connectdata *conn, bool *done);
+static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature);
+static CURLcode rtmp_connect(struct connectdata *conn, bool *done);
+static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead);
+
+static Curl_recv rtmp_recv;
+static Curl_send rtmp_send;
+
+/*
+ * RTMP protocol handler.h, based on http://rtmpdump.mplayerhq.hu
+ */
+
+const struct Curl_handler Curl_handler_rtmp = {
+ "RTMP", /* scheme */
+ rtmp_setup_connection, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMP, /* defport */
+ CURLPROTO_RTMP, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpt = {
+ "RTMPT", /* scheme */
+ rtmp_setup_connection, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPT, /* defport */
+ CURLPROTO_RTMPT, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpe = {
+ "RTMPE", /* scheme */
+ rtmp_setup_connection, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMP, /* defport */
+ CURLPROTO_RTMPE, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpte = {
+ "RTMPTE", /* scheme */
+ rtmp_setup_connection, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPT, /* defport */
+ CURLPROTO_RTMPTE, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmps = {
+ "RTMPS", /* scheme */
+ rtmp_setup_connection, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPS, /* defport */
+ CURLPROTO_RTMPS, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpts = {
+ "RTMPTS", /* scheme */
+ rtmp_setup_connection, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPS, /* defport */
+ CURLPROTO_RTMPTS, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+static CURLcode rtmp_setup_connection(struct connectdata *conn)
+{
+ RTMP *r = RTMP_Alloc();
+ if(!r)
+ return CURLE_OUT_OF_MEMORY;
+
+ RTMP_Init(r);
+ RTMP_SetBufferMS(r, DEF_BUFTIME);
+ if(!RTMP_SetupURL(r, conn->data->change.url)) {
+ RTMP_Free(r);
+ return CURLE_URL_MALFORMAT;
+ }
+ conn->proto.generic = r;
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
+{
+ RTMP *r = conn->proto.generic;
+ SET_RCVTIMEO(tv, 10);
+
+ r->m_sb.sb_socket = conn->sock[FIRSTSOCKET];
+
+ /* We have to know if it's a write before we send the
+ * connect request packet
+ */
+ if(conn->data->set.upload)
+ r->Link.protocol |= RTMP_FEATURE_WRITE;
+
+ /* For plain streams, use the buffer toggle trick to keep data flowing */
+ if(!(r->Link.lFlags & RTMP_LF_LIVE) &&
+ !(r->Link.protocol & RTMP_FEATURE_HTTP))
+ r->Link.lFlags |= RTMP_LF_BUFX;
+
+ (void)curlx_nonblock(r->m_sb.sb_socket, FALSE);
+ setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO,
+ (char *)&tv, sizeof(tv));
+
+ if(!RTMP_Connect1(r, NULL))
+ return CURLE_FAILED_INIT;
+
+ /* Clients must send a periodic BytesReceived report to the server */
+ r->m_bSendCounter = true;
+
+ *done = TRUE;
+ conn->recv[FIRSTSOCKET] = rtmp_recv;
+ conn->send[FIRSTSOCKET] = rtmp_send;
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_do(struct connectdata *conn, bool *done)
+{
+ RTMP *r = conn->proto.generic;
+
+ if(!RTMP_ConnectStream(r, 0))
+ return CURLE_FAILED_INIT;
+
+ if(conn->data->set.upload) {
+ Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize);
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+ }
+ else
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+ *done = TRUE;
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ (void)conn; /* unused */
+ (void)status; /* unused */
+ (void)premature; /* unused */
+
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ RTMP *r = conn->proto.generic;
+ (void)dead_connection;
+ if(r) {
+ conn->proto.generic = NULL;
+ RTMP_Close(r);
+ RTMP_Free(r);
+ }
+ return CURLE_OK;
+}
+
+static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
+ size_t len, CURLcode *err)
+{
+ RTMP *r = conn->proto.generic;
+ ssize_t nread;
+
+ (void)sockindex; /* unused */
+
+ nread = RTMP_Read(r, buf, curlx_uztosi(len));
+ if(nread < 0) {
+ if(r->m_read.status == RTMP_READ_COMPLETE ||
+ r->m_read.status == RTMP_READ_EOF) {
+ conn->data->req.size = conn->data->req.bytecount;
+ nread = 0;
+ }
+ else
+ *err = CURLE_RECV_ERROR;
+ }
+ return nread;
+}
+
+static ssize_t rtmp_send(struct connectdata *conn, int sockindex,
+ const void *buf, size_t len, CURLcode *err)
+{
+ RTMP *r = conn->proto.generic;
+ ssize_t num;
+
+ (void)sockindex; /* unused */
+
+ num = RTMP_Write(r, (char *)buf, curlx_uztosi(len));
+ if(num < 0)
+ *err = CURLE_SEND_ERROR;
+
+ return num;
+}
+#endif /* USE_LIBRTMP */
diff --git a/libcurl/src/lib/curl_rtmp.h b/libcurl/src/lib/curl_rtmp.h
new file mode 100644
index 0000000..4a9e9e6
--- /dev/null
+++ b/libcurl/src/lib/curl_rtmp.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_RTMP_H
+#define HEADER_CURL_RTMP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef USE_LIBRTMP
+extern const struct Curl_handler Curl_handler_rtmp;
+extern const struct Curl_handler Curl_handler_rtmpt;
+extern const struct Curl_handler Curl_handler_rtmpe;
+extern const struct Curl_handler Curl_handler_rtmpte;
+extern const struct Curl_handler Curl_handler_rtmps;
+extern const struct Curl_handler Curl_handler_rtmpts;
+#endif
+
+#endif /* HEADER_CURL_RTMP_H */
diff --git a/libcurl/src/lib/curl_sasl.c b/libcurl/src/lib/curl_sasl.c
new file mode 100644
index 0000000..86a4af0
--- /dev/null
+++ b/libcurl/src/lib/curl_sasl.c
@@ -0,0 +1,1667 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2617 Basic and Digest Access Authentication
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+
+#include "curl_base64.h"
+#include "curl_md5.h"
+#include "vtls/vtls.h"
+#include "curl_hmac.h"
+#include "curl_sasl.h"
+#include "warnless.h"
+#include "strtok.h"
+#include "strequal.h"
+#include "rawstr.h"
+#include "sendf.h"
+#include "non-ascii.h" /* included for Curl_convert_... prototypes */
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* Supported mechanisms */
+const struct {
+ const char *name; /* Name */
+ size_t len; /* Name length */
+ unsigned int bit; /* Flag bit */
+} mechtable[] = {
+ { "LOGIN", 5, SASL_MECH_LOGIN },
+ { "PLAIN", 5, SASL_MECH_PLAIN },
+ { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 },
+ { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 },
+ { "GSSAPI", 6, SASL_MECH_GSSAPI },
+ { "EXTERNAL", 8, SASL_MECH_EXTERNAL },
+ { "NTLM", 4, SASL_MECH_NTLM },
+ { "XOAUTH2", 7, SASL_MECH_XOAUTH2 },
+ { ZERO_NULL, 0, 0 }
+};
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI)
+#define DIGEST_QOP_VALUE_AUTH (1 << 0)
+#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
+#define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2)
+
+#define DIGEST_QOP_VALUE_STRING_AUTH "auth"
+#define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int"
+#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"
+
+#define DIGEST_MAX_VALUE_LENGTH 256
+#define DIGEST_MAX_CONTENT_LENGTH 1024
+
+/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
+ It converts digest text to ASCII so the MD5 will be correct for
+ what ultimately goes over the network.
+*/
+#define CURL_OUTPUT_DIGEST_CONV(a, b) \
+ result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
+ if(result) { \
+ free(b); \
+ return result; \
+ }
+
+/*
+ * Returns 0 on success and then the buffers are filled in fine.
+ *
+ * Non-zero means failure to parse.
+ */
+static int sasl_digest_get_pair(const char *str, char *value, char *content,
+ const char **endptr)
+{
+ int c;
+ bool starts_with_quote = FALSE;
+ bool escape = FALSE;
+
+ for(c = DIGEST_MAX_VALUE_LENGTH - 1; (*str && (*str != '=') && c--); )
+ *value++ = *str++;
+ *value = 0;
+
+ if('=' != *str++)
+ /* eek, no match */
+ return 1;
+
+ if('\"' == *str) {
+ /* this starts with a quote so it must end with one as well! */
+ str++;
+ starts_with_quote = TRUE;
+ }
+
+ for(c = DIGEST_MAX_CONTENT_LENGTH - 1; *str && c--; str++) {
+ switch(*str) {
+ case '\\':
+ if(!escape) {
+ /* possibly the start of an escaped quote */
+ escape = TRUE;
+ *content++ = '\\'; /* even though this is an escape character, we still
+ store it as-is in the target buffer */
+ continue;
+ }
+ break;
+ case ',':
+ if(!starts_with_quote) {
+ /* this signals the end of the content if we didn't get a starting
+ quote and then we do "sloppy" parsing */
+ c = 0; /* the end */
+ continue;
+ }
+ break;
+ case '\r':
+ case '\n':
+ /* end of string */
+ c = 0;
+ continue;
+ case '\"':
+ if(!escape && starts_with_quote) {
+ /* end of string */
+ c = 0;
+ continue;
+ }
+ break;
+ }
+ escape = FALSE;
+ *content++ = *str;
+ }
+ *content = 0;
+
+ *endptr = str;
+
+ return 0; /* all is fine! */
+}
+
+/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
+static void sasl_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
+ unsigned char *dest) /* 33 bytes */
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ snprintf((char *)&dest[i*2], 3, "%02x", source[i]);
+}
+
+/* Perform quoted-string escaping as described in RFC2616 and its errata */
+static char *sasl_digest_string_quoted(const char *source)
+{
+ char *dest, *d;
+ const char *s = source;
+ size_t n = 1; /* null terminator */
+
+ /* Calculate size needed */
+ while(*s) {
+ ++n;
+ if(*s == '"' || *s == '\\') {
+ ++n;
+ }
+ ++s;
+ }
+
+ dest = malloc(n);
+ if(dest) {
+ s = source;
+ d = dest;
+ while(*s) {
+ if(*s == '"' || *s == '\\') {
+ *d++ = '\\';
+ }
+ *d++ = *s++;
+ }
+ *d = 0;
+ }
+
+ return dest;
+}
+
+/* Retrieves the value for a corresponding key from the challenge string
+ * returns TRUE if the key could be found, FALSE if it does not exists
+ */
+static bool sasl_digest_get_key_value(const char *chlg,
+ const char *key,
+ char *value,
+ size_t max_val_len,
+ char end_char)
+{
+ char *find_pos;
+ size_t i;
+
+ find_pos = strstr(chlg, key);
+ if(!find_pos)
+ return FALSE;
+
+ find_pos += strlen(key);
+
+ for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i)
+ value[i] = *find_pos++;
+ value[i] = '\0';
+
+ return TRUE;
+}
+
+static CURLcode sasl_digest_get_qop_values(const char *options, int *value)
+{
+ char *tmp;
+ char *token;
+ char *tok_buf;
+
+ /* Initialise the output */
+ *value = 0;
+
+ /* Tokenise the list of qop values. Use a temporary clone of the buffer since
+ strtok_r() ruins it. */
+ tmp = strdup(options);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ token = strtok_r(tmp, ",", &tok_buf);
+ while(token != NULL) {
+ if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH))
+ *value |= DIGEST_QOP_VALUE_AUTH;
+ else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
+ *value |= DIGEST_QOP_VALUE_AUTH_INT;
+ else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
+ *value |= DIGEST_QOP_VALUE_AUTH_CONF;
+
+ token = strtok_r(NULL, ",", &tok_buf);
+ }
+
+ free(tmp);
+
+ return CURLE_OK;
+}
+#endif /* !CURL_DISABLE_CRYPTO_AUTH && !USE_WINDOWS_SSPI */
+
+#if !defined(USE_WINDOWS_SSPI)
+/*
+ * Curl_sasl_build_spn()
+ *
+ * This is used to build a SPN string in the format service/host.
+ *
+ * Parameters:
+ *
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * host [in] - The host name or realm.
+ *
+ * Returns a pointer to the newly allocated SPN.
+ */
+CURL_STATIC char *Curl_sasl_build_spn(const char *service, const char *host)
+{
+ /* Generate and return our SPN */
+ return aprintf("%s/%s", service, host);
+}
+#endif
+
+/*
+ * sasl_create_plain_message()
+ *
+ * This is used to generate an already encoded PLAIN message ready
+ * for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_create_plain_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result;
+ char *plainauth;
+ size_t ulen;
+ size_t plen;
+
+ ulen = strlen(userp);
+ plen = strlen(passwdp);
+
+ plainauth = malloc(2 * ulen + plen + 2);
+ if(!plainauth) {
+ *outlen = 0;
+ *outptr = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Calculate the reply */
+ memcpy(plainauth, userp, ulen);
+ plainauth[ulen] = '\0';
+ memcpy(plainauth + ulen + 1, userp, ulen);
+ plainauth[2 * ulen + 1] = '\0';
+ memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
+
+ /* Base64 encode the reply */
+ result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
+ outlen);
+ free(plainauth);
+ return result;
+}
+
+/*
+ * sasl_create_login_message()
+ *
+ * This is used to generate an already encoded LOGIN message containing the
+ * user name or password ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * valuep [in] - The user name or user's password.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_create_login_message(struct SessionHandle *data,
+ const char *valuep, char **outptr,
+ size_t *outlen)
+{
+ size_t vlen = strlen(valuep);
+
+ if(!vlen) {
+ /* Calculate an empty reply */
+ *outptr = strdup("=");
+ if(*outptr) {
+ *outlen = (size_t) 1;
+ return CURLE_OK;
+ }
+
+ *outlen = 0;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Base64 encode the value */
+ return Curl_base64_encode(data, valuep, vlen, outptr, outlen);
+}
+
+/*
+ * sasl_create_external_message()
+ *
+ * This is used to generate an already encoded EXTERNAL message containing
+ * the user name ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * user [in] - The user name.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_create_external_message(struct SessionHandle *data,
+ const char *user, char **outptr,
+ size_t *outlen)
+{
+ /* This is the same formatting as the login message. */
+ return sasl_create_login_message(data, user, outptr, outlen);
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ /*
+ * sasl_decode_cram_md5_message()
+ *
+ * This is used to decode an already encoded CRAM-MD5 challenge message.
+ *
+ * Parameters:
+ *
+ * chlg64 [in] - The base64 encoded challenge message.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_decode_cram_md5_message(const char *chlg64, char **outptr,
+ size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlg64len = strlen(chlg64);
+
+ *outptr = NULL;
+ *outlen = 0;
+
+ /* Decode the challenge if necessary */
+ if(chlg64len && *chlg64 != '=')
+ result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen);
+
+ return result;
+ }
+
+ /*
+ * sasl_create_cram_md5_message()
+ *
+ * This is used to generate an already encoded CRAM-MD5 response message ready
+ * for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg [in] - The challenge.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_create_cram_md5_message(struct SessionHandle *data,
+ const char *chlg,
+ const char *userp,
+ const char *passwdp,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlglen = 0;
+ HMAC_context *ctxt;
+ unsigned char digest[MD5_DIGEST_LEN];
+ char *response;
+
+ if(chlg)
+ chlglen = strlen(chlg);
+
+ /* Compute the digest using the password as the key */
+ ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
+ (const unsigned char *) passwdp,
+ curlx_uztoui(strlen(passwdp)));
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Update the digest with the given challenge */
+ if(chlglen > 0)
+ Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
+ curlx_uztoui(chlglen));
+
+ /* Finalise the digest */
+ Curl_HMAC_final(ctxt, digest);
+
+ /* Generate the response */
+ response = aprintf(
+ "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ userp, digest[0], digest[1], digest[2], digest[3], digest[4],
+ digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
+ digest[11], digest[12], digest[13], digest[14], digest[15]);
+ if(!response)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, response, 0, outptr, outlen);
+
+ free(response);
+
+ return result;
+}
+
+#ifndef USE_WINDOWS_SSPI
+/*
+ * sasl_decode_digest_md5_message()
+ *
+ * This is used internally to decode an already encoded DIGEST-MD5 challenge
+ * message into the seperate attributes.
+ *
+ * Parameters:
+ *
+ * chlg64 [in] - The base64 encoded challenge message.
+ * nonce [in/out] - The buffer where the nonce will be stored.
+ * nlen [in] - The length of the nonce buffer.
+ * realm [in/out] - The buffer where the realm will be stored.
+ * rlen [in] - The length of the realm buffer.
+ * alg [in/out] - The buffer where the algorithm will be stored.
+ * alen [in] - The length of the algorithm buffer.
+ * qop [in/out] - The buffer where the qop-options will be stored.
+ * qlen [in] - The length of the qop buffer.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_decode_digest_md5_message(const char *chlg64,
+ char *nonce, size_t nlen,
+ char *realm, size_t rlen,
+ char *alg, size_t alen,
+ char *qop, size_t qlen)
+{
+ CURLcode result = CURLE_OK;
+ unsigned char *chlg = NULL;
+ size_t chlglen = 0;
+ size_t chlg64len = strlen(chlg64);
+
+ /* Decode the base-64 encoded challenge message */
+ if(chlg64len && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Retrieve nonce string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "nonce=\"", nonce, nlen, '\"')) {
+ free(chlg);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Retrieve realm string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "realm=\"", realm, rlen, '\"')) {
+ /* Challenge does not have a realm, set empty string [RFC2831] page 6 */
+ strcpy(realm, "");
+ }
+
+ /* Retrieve algorithm string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "algorithm=", alg, alen, ',')) {
+ free(chlg);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Retrieve qop-options string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "qop=\"", qop, qlen, '\"')) {
+ free(chlg);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ free(chlg);
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sasl_create_digest_md5_message()
+ *
+ * This is used to generate an already encoded DIGEST-MD5 response message
+ * ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg64 [in] - The base64 encoded challenge message.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
+ const char *chlg64,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t i;
+ MD5_context *ctxt;
+ char *response = NULL;
+ unsigned char digest[MD5_DIGEST_LEN];
+ char HA1_hex[2 * MD5_DIGEST_LEN + 1];
+ char HA2_hex[2 * MD5_DIGEST_LEN + 1];
+ char resp_hash_hex[2 * MD5_DIGEST_LEN + 1];
+ char nonce[64];
+ char realm[128];
+ char algorithm[64];
+ char qop_options[64];
+ int qop_values;
+ char cnonce[33];
+ unsigned int entropy[4];
+ char nonceCount[] = "00000001";
+ char method[] = "AUTHENTICATE";
+ char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
+ char *spn = NULL;
+
+ /* Decode the challange message */
+ result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
+ realm, sizeof(realm),
+ algorithm, sizeof(algorithm),
+ qop_options, sizeof(qop_options));
+ if(result)
+ return result;
+
+ /* We only support md5 sessions */
+ if(strcmp(algorithm, "md5-sess") != 0)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Get the qop-values from the qop-options */
+ result = sasl_digest_get_qop_values(qop_options, &qop_values);
+ if(result)
+ return result;
+
+ /* We only support auth quality-of-protection */
+ if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Generate 16 bytes of random data */
+ entropy[0] = Curl_rand(data);
+ entropy[1] = Curl_rand(data);
+ entropy[2] = Curl_rand(data);
+ entropy[3] = Curl_rand(data);
+
+ /* Convert the random data into a 32 byte hex string */
+ snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
+ entropy[0], entropy[1], entropy[2], entropy[3]);
+
+ /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_MD5_update(ctxt, (const unsigned char *) userp,
+ curlx_uztoui(strlen(userp)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) realm,
+ curlx_uztoui(strlen(realm)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) passwdp,
+ curlx_uztoui(strlen(passwdp)));
+ Curl_MD5_final(ctxt, digest);
+
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN);
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) nonce,
+ curlx_uztoui(strlen(nonce)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
+ curlx_uztoui(strlen(cnonce)));
+ Curl_MD5_final(ctxt, digest);
+
+ /* Convert calculated 16 octet hex into 32 bytes string */
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
+
+ /* Generate our SPN */
+ spn = Curl_sasl_build_spn(service, realm);
+ if(!spn)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Calculate H(A2) */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt) {
+ free(spn);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_MD5_update(ctxt, (const unsigned char *) method,
+ curlx_uztoui(strlen(method)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) spn,
+ curlx_uztoui(strlen(spn)));
+ Curl_MD5_final(ctxt, digest);
+
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
+
+ /* Now calculate the response hash */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt) {
+ free(spn);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN);
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) nonce,
+ curlx_uztoui(strlen(nonce)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+
+ Curl_MD5_update(ctxt, (const unsigned char *) nonceCount,
+ curlx_uztoui(strlen(nonceCount)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
+ curlx_uztoui(strlen(cnonce)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) qop,
+ curlx_uztoui(strlen(qop)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+
+ Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN);
+ Curl_MD5_final(ctxt, digest);
+
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
+
+ /* Generate the response */
+ response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
+ "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s,"
+ "qop=%s",
+ userp, realm, nonce,
+ cnonce, nonceCount, spn, resp_hash_hex, qop);
+ free(spn);
+ if(!response)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, response, 0, outptr, outlen);
+
+ free(response);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_decode_digest_http_message()
+ *
+ * This is used to decode a HTTP DIGEST challenge message into the seperate
+ * attributes.
+ *
+ * Parameters:
+ *
+ * chlg [in] - The challenge message.
+ * digest [in/out] - The digest data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_decode_digest_http_message(const char *chlg,
+ struct digestdata *digest)
+{
+ bool before = FALSE; /* got a nonce before */
+ bool foundAuth = FALSE;
+ bool foundAuthInt = FALSE;
+ char *token = NULL;
+ char *tmp = NULL;
+
+ /* If we already have received a nonce, keep that in mind */
+ if(digest->nonce)
+ before = TRUE;
+
+ /* Clean up any former leftovers and initialise to defaults */
+ Curl_sasl_digest_cleanup(digest);
+
+ for(;;) {
+ char value[DIGEST_MAX_VALUE_LENGTH];
+ char content[DIGEST_MAX_CONTENT_LENGTH];
+
+ /* Pass all additional spaces here */
+ while(*chlg && ISSPACE(*chlg))
+ chlg++;
+
+ /* Extract a value=content pair */
+ if(!sasl_digest_get_pair(chlg, value, content, &chlg)) {
+ if(Curl_raw_equal(value, "nonce")) {
+ digest->nonce = strdup(content);
+ if(!digest->nonce)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else if(Curl_raw_equal(value, "stale")) {
+ if(Curl_raw_equal(content, "true")) {
+ digest->stale = TRUE;
+ digest->nc = 1; /* we make a new nonce now */
+ }
+ }
+ else if(Curl_raw_equal(value, "realm")) {
+ digest->realm = strdup(content);
+ if(!digest->realm)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else if(Curl_raw_equal(value, "opaque")) {
+ digest->opaque = strdup(content);
+ if(!digest->opaque)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else if(Curl_raw_equal(value, "qop")) {
+ char *tok_buf;
+ /* Tokenize the list and choose auth if possible, use a temporary
+ clone of the buffer since strtok_r() ruins it */
+ tmp = strdup(content);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ token = strtok_r(tmp, ",", &tok_buf);
+ while(token != NULL) {
+ if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
+ foundAuth = TRUE;
+ }
+ else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) {
+ foundAuthInt = TRUE;
+ }
+ token = strtok_r(NULL, ",", &tok_buf);
+ }
+
+ free(tmp);
+
+ /* Select only auth or auth-int. Otherwise, ignore */
+ if(foundAuth) {
+ digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH);
+ if(!digest->qop)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else if(foundAuthInt) {
+ digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT);
+ if(!digest->qop)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else if(Curl_raw_equal(value, "algorithm")) {
+ digest->algorithm = strdup(content);
+ if(!digest->algorithm)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(Curl_raw_equal(content, "MD5-sess"))
+ digest->algo = CURLDIGESTALGO_MD5SESS;
+ else if(Curl_raw_equal(content, "MD5"))
+ digest->algo = CURLDIGESTALGO_MD5;
+ else
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+ else {
+ /* unknown specifier, ignore it! */
+ }
+ }
+ else
+ break; /* we're done here */
+
+ /* Pass all additional spaces here */
+ while(*chlg && ISSPACE(*chlg))
+ chlg++;
+
+ /* Allow the list to be comma-separated */
+ if(',' == *chlg)
+ chlg++;
+ }
+
+ /* We had a nonce since before, and we got another one now without
+ 'stale=true'. This means we provided bad credentials in the previous
+ request */
+ if(before && !digest->stale)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* We got this header without a nonce, that's a bad Digest line! */
+ if(!digest->nonce)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sasl_create_digest_http_message()
+ *
+ * This is used to generate a HTTP DIGEST response message ready for sending
+ * to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * request [in] - The HTTP request.
+ * uripath [in] - The path of the HTTP uri.
+ * digest [in/out] - The digest data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const unsigned char *request,
+ const unsigned char *uripath,
+ struct digestdata *digest,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result;
+ unsigned char md5buf[16]; /* 16 bytes/128 bits */
+ unsigned char request_digest[33];
+ unsigned char *md5this;
+ unsigned char ha1[33];/* 32 digits and 1 zero byte */
+ unsigned char ha2[33];/* 32 digits and 1 zero byte */
+ char cnoncebuf[33];
+ char *cnonce = NULL;
+ size_t cnonce_sz = 0;
+ char *userp_quoted;
+ char *response = NULL;
+ char *tmp = NULL;
+
+ if(!digest->nc)
+ digest->nc = 1;
+
+ if(!digest->cnonce) {
+ snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
+ Curl_rand(data), Curl_rand(data),
+ Curl_rand(data), Curl_rand(data));
+
+ result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
+ &cnonce, &cnonce_sz);
+ if(result)
+ return result;
+
+ digest->cnonce = cnonce;
+ }
+
+ /*
+ if the algorithm is "MD5" or unspecified (which then defaults to MD5):
+
+ A1 = unq(username-value) ":" unq(realm-value) ":" passwd
+
+ if the algorithm is "MD5-sess" then:
+
+ A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
+ ":" unq(nonce-value) ":" unq(cnonce-value)
+ */
+
+ md5this = (unsigned char *)
+ aprintf("%s:%s:%s", userp, digest->realm, passwdp);
+ if(!md5this)
+ return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, md5this);
+ free(md5this);
+ sasl_digest_md5_to_ascii(md5buf, ha1);
+
+ if(digest->algo == CURLDIGESTALGO_MD5SESS) {
+ /* nonce and cnonce are OUTSIDE the hash */
+ tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, (unsigned char *)tmp);
+ free(tmp);
+ sasl_digest_md5_to_ascii(md5buf, ha1);
+ }
+
+ /*
+ If the "qop" directive's value is "auth" or is unspecified, then A2 is:
+
+ A2 = Method ":" digest-uri-value
+
+ If the "qop" value is "auth-int", then A2 is:
+
+ A2 = Method ":" digest-uri-value ":" H(entity-body)
+
+ (The "Method" value is the HTTP request method as specified in section
+ 5.1.1 of RFC 2616)
+ */
+
+ md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
+
+ if(digest->qop && Curl_raw_equal(digest->qop, "auth-int")) {
+ /* We don't support auth-int for PUT or POST at the moment.
+ TODO: replace md5 of empty string with entity-body for PUT/POST */
+ unsigned char *md5this2 = (unsigned char *)
+ aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
+ free(md5this);
+ md5this = md5this2;
+ }
+
+ if(!md5this)
+ return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, md5this);
+ free(md5this);
+ sasl_digest_md5_to_ascii(md5buf, ha2);
+
+ if(digest->qop) {
+ md5this = (unsigned char *)aprintf("%s:%s:%08x:%s:%s:%s",
+ ha1,
+ digest->nonce,
+ digest->nc,
+ digest->cnonce,
+ digest->qop,
+ ha2);
+ }
+ else {
+ md5this = (unsigned char *)aprintf("%s:%s:%s",
+ ha1,
+ digest->nonce,
+ ha2);
+ }
+
+ if(!md5this)
+ return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, md5this);
+ free(md5this);
+ sasl_digest_md5_to_ascii(md5buf, request_digest);
+
+ /* for test case 64 (snooped from a Mozilla 1.3a request)
+
+ Authorization: Digest username="testuser", realm="testrealm", \
+ nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
+
+ Digest parameters are all quoted strings. Username which is provided by
+ the user will need double quotes and backslashes within it escaped. For
+ the other fields, this shouldn't be an issue. realm, nonce, and opaque
+ are copied as is from the server, escapes and all. cnonce is generated
+ with web-safe characters. uri is already percent encoded. nc is 8 hex
+ characters. algorithm and qop with standard values only contain web-safe
+ chracters.
+ */
+ userp_quoted = sasl_digest_string_quoted(userp);
+ if(!userp_quoted)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(digest->qop) {
+ response = aprintf("username=\"%s\", "
+ "realm=\"%s\", "
+ "nonce=\"%s\", "
+ "uri=\"%s\", "
+ "cnonce=\"%s\", "
+ "nc=%08x, "
+ "qop=%s, "
+ "response=\"%s\"",
+ userp_quoted,
+ digest->realm,
+ digest->nonce,
+ uripath,
+ digest->cnonce,
+ digest->nc,
+ digest->qop,
+ request_digest);
+
+ if(Curl_raw_equal(digest->qop, "auth"))
+ digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0
+ padded which tells to the server how many times you are
+ using the same nonce in the qop=auth mode */
+ }
+ else {
+ response = aprintf("username=\"%s\", "
+ "realm=\"%s\", "
+ "nonce=\"%s\", "
+ "uri=\"%s\", "
+ "response=\"%s\"",
+ userp_quoted,
+ digest->realm,
+ digest->nonce,
+ uripath,
+ request_digest);
+ }
+ free(userp_quoted);
+ if(!response)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Add the optional fields */
+ if(digest->opaque) {
+ /* Append the opaque */
+ tmp = aprintf("%s, opaque=\"%s\"", response, digest->opaque);
+ free(response);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ response = tmp;
+ }
+
+ if(digest->algorithm) {
+ /* Append the algorithm */
+ tmp = aprintf("%s, algorithm=\"%s\"", response, digest->algorithm);
+ free(response);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ response = tmp;
+ }
+
+ /* Return the output */
+ *outptr = response;
+ *outlen = strlen(response);
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sasl_digest_cleanup()
+ *
+ * This is used to clean up the digest specific data.
+ *
+ * Parameters:
+ *
+ * digest [in/out] - The digest data struct being cleaned up.
+ *
+ */
+CURL_STATIC void Curl_sasl_digest_cleanup(struct digestdata *digest)
+{
+ Curl_safefree(digest->nonce);
+ Curl_safefree(digest->cnonce);
+ Curl_safefree(digest->realm);
+ Curl_safefree(digest->opaque);
+ Curl_safefree(digest->qop);
+ Curl_safefree(digest->algorithm);
+
+ digest->nc = 0;
+ digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */
+ digest->stale = FALSE; /* default means normal, not stale */
+}
+#endif /* !USE_WINDOWS_SSPI */
+
+#endif /* CURL_DISABLE_CRYPTO_AUTH */
+
+#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
+/*
+ * Curl_sasl_ntlm_cleanup()
+ *
+ * This is used to clean up the ntlm specific data.
+ *
+ * Parameters:
+ *
+ * ntlm [in/out] - The ntlm data struct being cleaned up.
+ *
+ */
+CURL_STATIC void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm)
+{
+ /* Free the target info */
+ Curl_safefree(ntlm->target_info);
+
+ /* Reset any variables */
+ ntlm->target_info_len = 0;
+ }
+#endif /* USE_NTLM && !USE_WINDOWS_SSPI*/
+
+/*
+ * sasl_create_xoauth2_message()
+ *
+ * This is used to generate an already encoded OAuth 2.0 message ready for
+ * sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * user [in] - The user name.
+ * bearer [in] - The bearer token.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_create_xoauth2_message(struct SessionHandle *data,
+ const char *user,
+ const char *bearer,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ char *xoauth = NULL;
+
+ /* Generate the message */
+ xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
+ if(!xoauth)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Base64 encode the reply */
+ result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
+
+ free(xoauth);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_cleanup()
+ *
+ * This is used to cleanup any libraries or curl modules used by the sasl
+ * functions.
+ *
+ * Parameters:
+ *
+ * conn [in] - The connection data.
+ * authused [in] - The authentication mechanism used.
+ */
+CURL_STATIC void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
+{
+#if defined(USE_KERBEROS5)
+ /* Cleanup the gssapi structure */
+ if(authused == SASL_MECH_GSSAPI) {
+ Curl_sasl_gssapi_cleanup(&conn->krb5);
+ }
+#endif
+
+#if defined(USE_NTLM)
+ /* Cleanup the ntlm structure */
+ if(authused == SASL_MECH_NTLM) {
+ Curl_ntlm_sspi_cleanup(&conn->ntlm);
+ }
+#endif
+
+#if !defined(USE_KERBEROS5) && !defined(USE_NTLM)
+ /* Reserved for future use */
+ (void)conn;
+ (void)authused;
+#endif
+}
+
+/*
+ * Curl_sasl_decode_mech()
+ *
+ * Convert a SASL mechanism name into a token.
+ *
+ * Parameters:
+ *
+ * ptr [in] - The mechanism string.
+ * maxlen [in] - Maximum mechanism string length.
+ * len [out] - If not NULL, effective name length.
+ *
+ * Returns the SASL mechanism token or 0 if no match.
+ */
+CURL_STATIC unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len)
+{
+ unsigned int i;
+ char c;
+
+ for(i = 0; mechtable[i].name; i++) {
+ if(maxlen >= mechtable[i].len &&
+ !memcmp(ptr, mechtable[i].name, mechtable[i].len)) {
+ if(len)
+ *len = mechtable[i].len;
+
+ if(maxlen == mechtable[i].len)
+ return mechtable[i].bit;
+
+ c = ptr[mechtable[i].len];
+ if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_')
+ return mechtable[i].bit;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Curl_sasl_parse_url_auth_option()
+ *
+ * Parse the URL login options.
+ */
+CURL_STATIC CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
+ const char *value, size_t len)
+{
+ CURLcode result = CURLE_OK;
+ unsigned int mechbit;
+ size_t mechlen;
+
+ if(!len)
+ return CURLE_URL_MALFORMAT;
+
+ if(sasl->resetprefs) {
+ sasl->resetprefs = FALSE;
+ sasl->prefmech = SASL_AUTH_NONE;
+ }
+
+ if(strnequal(value, "*", len))
+ sasl->prefmech = SASL_AUTH_DEFAULT;
+ else if((mechbit = Curl_sasl_decode_mech(value, len, &mechlen)) &&
+ mechlen == len)
+ sasl->prefmech |= mechbit;
+ else
+ result = CURLE_URL_MALFORMAT;
+
+ return result;
+}
+
+/*
+ * Curl_sasl_init()
+ *
+ * Initializes the SASL structure.
+ */
+CURL_STATIC void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params)
+{
+ sasl->params = params; /* Set protocol dependent parameters */
+ sasl->state = SASL_STOP; /* Not yet running */
+ sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */
+ sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */
+ sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */
+ sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */
+ sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */
+ sasl->force_ir = FALSE; /* Respect external option */
+}
+
+/*
+ * state()
+ *
+ * This is the ONLY way to change SASL state!
+ */
+static void state(struct SASL *sasl, struct connectdata *conn,
+ saslstate newstate)
+{
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[]={
+ "STOP",
+ "PLAIN",
+ "LOGIN",
+ "LOGIN_PASSWD",
+ "EXTERNAL",
+ "CRAMMD5",
+ "DIGESTMD5",
+ "DIGESTMD5_RESP",
+ "NTLM",
+ "NTLM_TYPE2MSG",
+ "GSSAPI",
+ "GSSAPI_TOKEN",
+ "GSSAPI_NO_DATA",
+ "XOAUTH2",
+ "CANCEL",
+ "FINAL",
+ /* LAST */
+ };
+
+ if(sasl->state != newstate)
+ infof(conn->data, "SASL %p state change from %s to %s\n",
+ (void *)sasl, names[sasl->state], names[newstate]);
+#else
+ (void) conn;
+#endif
+
+ sasl->state = newstate;
+}
+
+/*
+ * Curl_sasl_can_authenticate()
+ *
+ * Check if we have enough auth data and capabilities to authenticate.
+ */
+CURL_STATIC bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn)
+{
+ /* Have credentials been provided? */
+ if(conn->bits.user_passwd)
+ return TRUE;
+
+ /* EXTERNAL can authenticate without a user name and/or password */
+ if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ * Curl_sasl_start()
+ *
+ * Calculate the required login details for SASL authentication.
+ */
+CURL_STATIC CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
+ bool force_ir, saslprogress *progress)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ unsigned int enabledmechs;
+ const char *mech = NULL;
+ char *resp = NULL;
+ size_t len = 0;
+ saslstate state1 = SASL_STOP;
+ saslstate state2 = SASL_FINAL;
+
+ sasl->force_ir = force_ir; /* Latch for future use */
+ sasl->authused = 0; /* No mechanism used yet */
+ enabledmechs = sasl->authmechs & sasl->prefmech;
+ *progress = SASL_IDLE;
+
+ /* Calculate the supported authentication mechanism, by decreasing order of
+ security, as well as the initial response where appropriate */
+ if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) {
+ mech = SASL_MECH_STRING_EXTERNAL;
+ state1 = SASL_EXTERNAL;
+ sasl->authused = SASL_MECH_EXTERNAL;
+
+ if(force_ir || data->set.sasl_ir)
+ result = sasl_create_external_message(data, conn->user, &resp, &len);
+ }
+ else if(conn->bits.user_passwd) {
+#if defined(USE_KERBEROS5)
+ if(enabledmechs & SASL_MECH_GSSAPI) {
+ sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
+ mech = SASL_MECH_STRING_GSSAPI;
+ state1 = SASL_GSSAPI;
+ state2 = SASL_GSSAPI_TOKEN;
+ sasl->authused = SASL_MECH_GSSAPI;
+
+ if(force_ir || data->set.sasl_ir)
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd,
+ sasl->params->service,
+ sasl->mutual_auth,
+ NULL, &conn->krb5,
+ &resp, &len);
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(enabledmechs & SASL_MECH_DIGEST_MD5) {
+ mech = SASL_MECH_STRING_DIGEST_MD5;
+ state1 = SASL_DIGESTMD5;
+ sasl->authused = SASL_MECH_DIGEST_MD5;
+ }
+ else if(enabledmechs & SASL_MECH_CRAM_MD5) {
+ mech = SASL_MECH_STRING_CRAM_MD5;
+ state1 = SASL_CRAMMD5;
+ sasl->authused = SASL_MECH_CRAM_MD5;
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ if(enabledmechs & SASL_MECH_NTLM) {
+ mech = SASL_MECH_STRING_NTLM;
+ state1 = SASL_NTLM;
+ state2 = SASL_NTLM_TYPE2MSG;
+ sasl->authused = SASL_MECH_NTLM;
+
+ if(force_ir || data->set.sasl_ir)
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm, &resp, &len);
+ }
+ else
+#endif
+ if((enabledmechs & SASL_MECH_XOAUTH2) || conn->xoauth2_bearer) {
+ mech = SASL_MECH_STRING_XOAUTH2;
+ state1 = SASL_XOAUTH2;
+ sasl->authused = SASL_MECH_XOAUTH2;
+
+ if(force_ir || data->set.sasl_ir)
+ result = sasl_create_xoauth2_message(data, conn->user,
+ conn->xoauth2_bearer,
+ &resp, &len);
+ }
+ else if(enabledmechs & SASL_MECH_LOGIN) {
+ mech = SASL_MECH_STRING_LOGIN;
+ state1 = SASL_LOGIN;
+ state2 = SASL_LOGIN_PASSWD;
+ sasl->authused = SASL_MECH_LOGIN;
+
+ if(force_ir || data->set.sasl_ir)
+ result = sasl_create_login_message(data, conn->user, &resp, &len);
+ }
+ else if(enabledmechs & SASL_MECH_PLAIN) {
+ mech = SASL_MECH_STRING_PLAIN;
+ state1 = SASL_PLAIN;
+ sasl->authused = SASL_MECH_PLAIN;
+
+ if(force_ir || data->set.sasl_ir)
+ result = sasl_create_plain_message(data, conn->user, conn->passwd,
+ &resp, &len);
+ }
+ }
+
+ if(!result) {
+ if(resp && sasl->params->maxirlen &&
+ strlen(mech) + len > sasl->params->maxirlen) {
+ free(resp);
+ resp = NULL;
+ }
+
+ if(mech) {
+ result = sasl->params->sendauth(conn, mech, resp);
+ if(!result) {
+ *progress = SASL_INPROGRESS;
+ state(sasl, conn, resp? state2: state1);
+ }
+ }
+ }
+
+ free(resp);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_continue()
+ *
+ * Continue the authentication.
+ */
+CURL_STATIC CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
+ int code, saslprogress *progress)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ saslstate newstate = SASL_FINAL;
+ char *resp = NULL;
+#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+ char *serverdata;
+ char *chlg = NULL;
+ size_t chlglen = 0;
+#endif
+ size_t len = 0;
+
+ *progress = SASL_INPROGRESS;
+
+ if(sasl->state == SASL_FINAL) {
+ if(code != sasl->params->finalcode)
+ result = CURLE_LOGIN_DENIED;
+ *progress = SASL_DONE;
+ state(sasl, conn, SASL_STOP);
+ return result;
+ }
+
+ if(sasl->state != SASL_CANCEL && code != sasl->params->contcode) {
+ *progress = SASL_DONE;
+ state(sasl, conn, SASL_STOP);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ switch(sasl->state) {
+ case SASL_STOP:
+ *progress = SASL_DONE;
+ return result;
+ case SASL_PLAIN:
+ result = sasl_create_plain_message(data, conn->user, conn->passwd, &resp,
+ &len);
+ break;
+ case SASL_LOGIN:
+ result = sasl_create_login_message(data, conn->user, &resp, &len);
+ newstate = SASL_LOGIN_PASSWD;
+ break;
+ case SASL_LOGIN_PASSWD:
+ result = sasl_create_login_message(data, conn->passwd, &resp, &len);
+ break;
+ case SASL_EXTERNAL:
+ result = sasl_create_external_message(data, conn->user, &resp, &len);
+ break;
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ case SASL_CRAMMD5:
+ sasl->params->getmessage(data->state.buffer, &serverdata);
+ result = sasl_decode_cram_md5_message(serverdata, &chlg, &chlglen);
+ if(!result)
+ result = sasl_create_cram_md5_message(data, chlg, conn->user,
+ conn->passwd, &resp, &len);
+ free(chlg);
+ break;
+ case SASL_DIGESTMD5:
+ sasl->params->getmessage(data->state.buffer, &serverdata);
+ result = Curl_sasl_create_digest_md5_message(data, serverdata,
+ conn->user, conn->passwd,
+ sasl->params->service,
+ &resp, &len);
+ newstate = SASL_DIGESTMD5_RESP;
+ break;
+ case SASL_DIGESTMD5_RESP:
+ if(!(resp = strdup("")))
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+#endif
+
+#ifdef USE_NTLM
+ case SASL_NTLM:
+ /* Create the type-1 message */
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm, &resp, &len);
+ newstate = SASL_NTLM_TYPE2MSG;
+ break;
+ case SASL_NTLM_TYPE2MSG:
+ /* Decode the type-2 message */
+ sasl->params->getmessage(data->state.buffer, &serverdata);
+ result = Curl_sasl_decode_ntlm_type2_message(data, serverdata,
+ &conn->ntlm);
+ if(!result)
+ result = Curl_sasl_create_ntlm_type3_message(data, conn->user,
+ conn->passwd, &conn->ntlm,
+ &resp, &len);
+ break;
+#endif
+
+#if defined(USE_KERBEROS5)
+ case SASL_GSSAPI:
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd,
+ sasl->params->service,
+ sasl->mutual_auth, NULL,
+ &conn->krb5,
+ &resp, &len);
+ newstate = SASL_GSSAPI_TOKEN;
+ break;
+ case SASL_GSSAPI_TOKEN:
+ sasl->params->getmessage(data->state.buffer, &serverdata);
+ if(sasl->mutual_auth) {
+ /* Decode the user token challenge and create the optional response
+ message */
+ result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL,
+ sasl->mutual_auth,
+ serverdata, &conn->krb5,
+ &resp, &len);
+ newstate = SASL_GSSAPI_NO_DATA;
+ }
+ else
+ /* Decode the security challenge and create the response message */
+ result = Curl_sasl_create_gssapi_security_message(data, serverdata,
+ &conn->krb5,
+ &resp, &len);
+ break;
+ case SASL_GSSAPI_NO_DATA:
+ sasl->params->getmessage(data->state.buffer, &serverdata);
+ /* Decode the security challenge and create the response message */
+ result = Curl_sasl_create_gssapi_security_message(data, serverdata,
+ &conn->krb5,
+ &resp, &len);
+ break;
+#endif
+
+ case SASL_XOAUTH2:
+ /* Create the authorisation message */
+ result = sasl_create_xoauth2_message(data, conn->user,
+ conn->xoauth2_bearer, &resp, &len);
+ break;
+ case SASL_CANCEL:
+ /* Remove the offending mechanism from the supported list */
+ sasl->authmechs ^= sasl->authused;
+
+ /* Start an alternative SASL authentication */
+ result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress);
+ newstate = sasl->state; /* Use state from Curl_sasl_start() */
+ break;
+ default:
+ failf(data, "Unsupported SASL authentication mechanism");
+ result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
+ break;
+ }
+
+ switch(result) {
+ case CURLE_BAD_CONTENT_ENCODING:
+ /* Cancel dialog */
+ result = sasl->params->sendcont(conn, "*");
+ newstate = SASL_CANCEL;
+ break;
+ case CURLE_OK:
+ if(resp)
+ result = sasl->params->sendcont(conn, resp);
+ break;
+ default:
+ newstate = SASL_STOP; /* Stop on error */
+ *progress = SASL_DONE;
+ break;
+ }
+
+ free(resp);
+
+ state(sasl, conn, newstate);
+
+ return result;
+}
diff --git a/libcurl/src/lib/curl_sasl.h b/libcurl/src/lib/curl_sasl.h
new file mode 100644
index 0000000..ce0abbc
--- /dev/null
+++ b/libcurl/src/lib/curl_sasl.h
@@ -0,0 +1,245 @@
+#ifndef HEADER_CURL_SASL_H
+#define HEADER_CURL_SASL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+struct SessionHandle;
+struct connectdata;
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+struct digestdata;
+#endif
+
+#if defined(USE_NTLM)
+struct ntlmdata;
+#endif
+
+#if defined(USE_KERBEROS5)
+struct kerberos5data;
+#endif
+
+/* Authentication mechanism flags */
+#define SASL_MECH_LOGIN (1 << 0)
+#define SASL_MECH_PLAIN (1 << 1)
+#define SASL_MECH_CRAM_MD5 (1 << 2)
+#define SASL_MECH_DIGEST_MD5 (1 << 3)
+#define SASL_MECH_GSSAPI (1 << 4)
+#define SASL_MECH_EXTERNAL (1 << 5)
+#define SASL_MECH_NTLM (1 << 6)
+#define SASL_MECH_XOAUTH2 (1 << 7)
+
+/* Authentication mechanism values */
+#define SASL_AUTH_NONE 0
+#define SASL_AUTH_ANY ~0U
+#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & \
+ ~(SASL_MECH_EXTERNAL | SASL_MECH_XOAUTH2))
+
+/* Authentication mechanism strings */
+#define SASL_MECH_STRING_LOGIN "LOGIN"
+#define SASL_MECH_STRING_PLAIN "PLAIN"
+#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
+#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
+#define SASL_MECH_STRING_GSSAPI "GSSAPI"
+#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
+#define SASL_MECH_STRING_NTLM "NTLM"
+#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
+
+enum {
+ CURLDIGESTALGO_MD5,
+ CURLDIGESTALGO_MD5SESS
+};
+
+/* SASL machine states */
+typedef enum {
+ SASL_STOP,
+ SASL_PLAIN,
+ SASL_LOGIN,
+ SASL_LOGIN_PASSWD,
+ SASL_EXTERNAL,
+ SASL_CRAMMD5,
+ SASL_DIGESTMD5,
+ SASL_DIGESTMD5_RESP,
+ SASL_NTLM,
+ SASL_NTLM_TYPE2MSG,
+ SASL_GSSAPI,
+ SASL_GSSAPI_TOKEN,
+ SASL_GSSAPI_NO_DATA,
+ SASL_XOAUTH2,
+ SASL_CANCEL,
+ SASL_FINAL
+} saslstate;
+
+/* Progress indicator */
+typedef enum {
+ SASL_IDLE,
+ SASL_INPROGRESS,
+ SASL_DONE
+} saslprogress;
+
+/* Protocol dependent SASL parameters */
+struct SASLproto {
+ const char *service; /* The service name */
+ int contcode; /* Code to receive when continuation is expected */
+ int finalcode; /* Code to receive upon authentication success */
+ size_t maxirlen; /* Maximum initial response length */
+ CURLcode (*sendauth)(struct connectdata *conn,
+ const char *mech, const char *ir);
+ /* Send authentication command */
+ CURLcode (*sendcont)(struct connectdata *conn, const char *contauth);
+ /* Send authentication continuation */
+ void (*getmessage)(char *buffer, char **outptr);
+ /* Get SASL response message */
+};
+
+/* Per-connection parameters */
+struct SASL {
+ const struct SASLproto *params; /* Protocol dependent parameters */
+ saslstate state; /* Current machine state */
+ unsigned int authmechs; /* Accepted authentication mechanisms */
+ unsigned int prefmech; /* Preferred authentication mechanism */
+ unsigned int authused; /* Auth mechanism used for the connection */
+ bool resetprefs; /* For URL auth option parsing. */
+ bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
+ bool force_ir; /* Protocol always supports initial response */
+};
+
+/* This is used to test whether the line starts with the given mechanism */
+#define sasl_mech_equal(line, wordlen, mech) \
+ (wordlen == (sizeof(mech) - 1) / sizeof(char) && \
+ !memcmp(line, mech, wordlen))
+
+/* This is used to build a SPN string */
+#if !defined(USE_WINDOWS_SSPI)
+CURL_STATIC char *Curl_sasl_build_spn(const char *service, const char *instance);
+#else
+CURL_STATIC TCHAR *Curl_sasl_build_spn(const char *service, const char *instance);
+#endif
+
+#if defined(HAVE_GSSAPI)
+CURL_STATIC char *Curl_sasl_build_gssapi_spn(const char *service, const char *host);
+#endif
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+/* This is used to generate a base64 encoded DIGEST-MD5 response message */
+CURL_STATIC CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
+ const char *chlg64,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ char **outptr, size_t *outlen);
+
+/* This is used to decode a HTTP DIGEST challenge message */
+CURL_STATIC CURLcode Curl_sasl_decode_digest_http_message(const char *chlg,
+ struct digestdata *digest);
+
+/* This is used to generate a HTTP DIGEST response message */
+CURL_STATIC CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const unsigned char *request,
+ const unsigned char *uri,
+ struct digestdata *digest,
+ char **outptr, size_t *outlen);
+
+/* This is used to clean up the digest specific data */
+CURL_STATIC void Curl_sasl_digest_cleanup(struct digestdata *digest);
+#endif
+
+#ifdef USE_NTLM
+/* This is used to generate a base64 encoded NTLM type-1 message */
+CURL_STATIC CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen);
+
+/* This is used to decode a base64 encoded NTLM type-2 message */
+CURL_STATIC CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
+ const char *type2msg,
+ struct ntlmdata *ntlm);
+
+/* This is used to generate a base64 encoded NTLM type-3 message */
+CURL_STATIC CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen);
+
+/* This is used to clean up the ntlm specific data */
+void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm);
+
+#endif /* USE_NTLM */
+
+#if defined(USE_KERBEROS5)
+/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token
+ message */
+CURL_STATIC CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ const bool mutual,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr, size_t *outlen);
+
+/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security
+ token message */
+CURL_STATIC CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
+ const char *input,
+ struct kerberos5data *krb5,
+ char **outptr,
+ size_t *outlen);
+
+/* This is used to clean up the gssapi specific data */
+CURL_STATIC void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5);
+#endif /* USE_KERBEROS5 */
+
+/* This is used to cleanup any libraries or curl modules used by the sasl
+ functions */
+CURL_STATIC void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);
+
+/* Convert a mechanism name to a token */
+CURL_STATIC unsigned int Curl_sasl_decode_mech(const char *ptr,
+ size_t maxlen, size_t *len);
+
+/* Parse the URL login options */
+CURL_STATIC CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
+ const char *value, size_t len);
+
+/* Initializes an SASL structure */
+CURL_STATIC void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params);
+
+/* Check if we have enough auth data and capabilities to authenticate */
+CURL_STATIC bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn);
+
+/* Calculate the required login details for SASL authentication */
+CURL_STATIC CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
+ bool force_ir, saslprogress *progress);
+
+/* Continue an SASL authentication */
+CURL_STATIC CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
+ int code, saslprogress *progress);
+
+#endif /* HEADER_CURL_SASL_H */
diff --git a/libcurl/src/lib/curl_sasl_gssapi.c b/libcurl/src/lib/curl_sasl_gssapi.c
new file mode 100644
index 0000000..75bf6a7
--- /dev/null
+++ b/libcurl/src/lib/curl_sasl_gssapi.c
@@ -0,0 +1,392 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2014 - 2015, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(HAVE_GSSAPI) && defined(USE_KERBEROS5)
+
+#include <curl/curl.h>
+
+#include "curl_sasl.h"
+#include "urldata.h"
+#include "curl_base64.h"
+#include "curl_gssapi.h"
+#include "sendf.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+* Curl_sasl_build_gssapi_spn()
+*
+* This is used to build a SPN string in the format service@host.
+*
+* Parameters:
+*
+* serivce [in] - The service type such as www, smtp, pop or imap.
+* host [in] - The host name or realm.
+*
+* Returns a pointer to the newly allocated SPN.
+*/
+char *Curl_sasl_build_gssapi_spn(const char *service, const char *host)
+{
+ /* Generate and return our SPN */
+ return aprintf("%s@%s", service, host);
+}
+
+/*
+ * Curl_sasl_create_gssapi_user_message()
+ *
+ * This is used to generate an already encoded GSSAPI (Kerberos V5) user token
+ * message ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * mutual_auth [in] - Flag specifing whether or not mutual authentication
+ * is enabled.
+ * chlg64 [in] - Pointer to the optional base64 encoded challenge
+ * message.
+ * krb5 [in/out] - The gssapi data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ const bool mutual_auth,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlglen = 0;
+ unsigned char *chlg = NULL;
+ OM_uint32 gss_status;
+ OM_uint32 gss_major_status;
+ OM_uint32 gss_minor_status;
+ gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+
+ (void) userp;
+ (void) passwdp;
+
+ if(krb5->context == GSS_C_NO_CONTEXT) {
+ /* Generate our SPN */
+ char *spn = Curl_sasl_build_gssapi_spn(service,
+ data->easy_conn->host.name);
+ if(!spn)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Populate the SPN structure */
+ spn_token.value = spn;
+ spn_token.length = strlen(spn);
+
+ /* Import the SPN */
+ gss_major_status = gss_import_name(&gss_minor_status, &spn_token,
+ GSS_C_NT_HOSTBASED_SERVICE, &krb5->spn);
+ if(GSS_ERROR(gss_major_status)) {
+ Curl_gss_log_error(data, gss_minor_status, "gss_import_name() failed: ");
+
+ free(spn);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ free(spn);
+ }
+ else {
+ /* Decode the base-64 encoded challenge message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg) {
+ infof(data, "GSSAPI handshake failure (empty challenge message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Setup the challenge "input" security buffer */
+ input_token.value = chlg;
+ input_token.length = chlglen;
+ }
+
+ gss_major_status = Curl_gss_init_sec_context(data,
+ &gss_minor_status,
+ &krb5->context,
+ krb5->spn,
+ &Curl_krb5_mech_oid,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &input_token,
+ &output_token,
+ mutual_auth,
+ NULL);
+
+ free(input_token.value);
+
+ if(GSS_ERROR(gss_major_status)) {
+ if(output_token.value)
+ gss_release_buffer(&gss_status, &output_token);
+
+ Curl_gss_log_error(data, gss_minor_status,
+ "gss_init_sec_context() failed: ");
+
+ return CURLE_RECV_ERROR;
+ }
+
+ if(output_token.value && output_token.length) {
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *) output_token.value,
+ output_token.length, outptr, outlen);
+
+ gss_release_buffer(&gss_status, &output_token);
+ }
+
+ return result;
+}
+
+/*
+ * Curl_sasl_create_gssapi_security_message()
+ *
+ * This is used to generate an already encoded GSSAPI (Kerberos V5) security
+ * token message ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg64 [in] - Pointer to the optional base64 encoded challenge message.
+ * krb5 [in/out] - The gssapi data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr,
+ size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlglen = 0;
+ size_t messagelen = 0;
+ unsigned char *chlg = NULL;
+ unsigned char *message = NULL;
+ OM_uint32 gss_status;
+ OM_uint32 gss_major_status;
+ OM_uint32 gss_minor_status;
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+ unsigned int indata = 0;
+ unsigned int outdata = 0;
+ gss_qop_t qop = GSS_C_QOP_DEFAULT;
+ unsigned int sec_layer = 0;
+ unsigned int max_size = 0;
+ gss_name_t username = GSS_C_NO_NAME;
+ gss_buffer_desc username_token;
+
+ /* Decode the base-64 encoded input message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg) {
+ infof(data, "GSSAPI handshake failure (empty security message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Get the fully qualified username back from the context */
+ gss_major_status = gss_inquire_context(&gss_minor_status, krb5->context,
+ &username, NULL, NULL, NULL, NULL,
+ NULL, NULL);
+ if(GSS_ERROR(gss_major_status)) {
+ Curl_gss_log_error(data, gss_minor_status,
+ "gss_inquire_context() failed: ");
+
+ free(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Convert the username from internal format to a displayable token */
+ gss_major_status = gss_display_name(&gss_minor_status, username,
+ &username_token, NULL);
+ if(GSS_ERROR(gss_major_status)) {
+ Curl_gss_log_error(data, gss_minor_status, "gss_display_name() failed: ");
+
+ free(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Setup the challenge "input" security buffer */
+ input_token.value = chlg;
+ input_token.length = chlglen;
+
+ /* Decrypt the inbound challenge and obtain the qop */
+ gss_major_status = gss_unwrap(&gss_minor_status, krb5->context, &input_token,
+ &output_token, NULL, &qop);
+ if(GSS_ERROR(gss_major_status)) {
+ Curl_gss_log_error(data, gss_minor_status, "gss_unwrap() failed: ");
+
+ gss_release_buffer(&gss_status, &username_token);
+ free(chlg);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Not 4 octets long so fail as per RFC4752 Section 3.1 */
+ if(output_token.length != 4) {
+ infof(data, "GSSAPI handshake failure (invalid security data)\n");
+
+ gss_release_buffer(&gss_status, &username_token);
+ free(chlg);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Copy the data out and free the challenge as it is not required anymore */
+ memcpy(&indata, output_token.value, 4);
+ gss_release_buffer(&gss_status, &output_token);
+ free(chlg);
+
+ /* Extract the security layer */
+ sec_layer = indata & 0x000000FF;
+ if(!(sec_layer & GSSAUTH_P_NONE)) {
+ infof(data, "GSSAPI handshake failure (invalid security layer)\n");
+
+ gss_release_buffer(&gss_status, &username_token);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Extract the maximum message size the server can receive */
+ max_size = ntohl(indata & 0xFFFFFF00);
+ if(max_size > 0) {
+ /* The server has told us it supports a maximum receive buffer, however, as
+ we don't require one unless we are encrypting data, we tell the server
+ our receive buffer is zero. */
+ max_size = 0;
+ }
+
+ /* Allocate our message */
+ messagelen = sizeof(outdata) + username_token.length + 1;
+ message = malloc(messagelen);
+ if(!message) {
+ gss_release_buffer(&gss_status, &username_token);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Populate the message with the security layer, client supported receive
+ message size and authorization identity including the 0x00 based
+ terminator. Note: Dispite RFC4752 Section 3.1 stating "The authorization
+ identity is not terminated with the zero-valued (%x00) octet." it seems
+ necessary to include it. */
+ outdata = htonl(max_size) | sec_layer;
+ memcpy(message, &outdata, sizeof(outdata));
+ memcpy(message + sizeof(outdata), username_token.value,
+ username_token.length);
+ message[messagelen - 1] = '\0';
+
+ /* Free the username token as it is not required anymore */
+ gss_release_buffer(&gss_status, &username_token);
+
+ /* Setup the "authentication data" security buffer */
+ input_token.value = message;
+ input_token.length = messagelen;
+
+ /* Encrypt the data */
+ gss_major_status = gss_wrap(&gss_minor_status, krb5->context, 0,
+ GSS_C_QOP_DEFAULT, &input_token, NULL,
+ &output_token);
+ if(GSS_ERROR(gss_major_status)) {
+ Curl_gss_log_error(data, gss_minor_status, "gss_wrap() failed: ");
+
+ free(message);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *) output_token.value,
+ output_token.length, outptr, outlen);
+
+ /* Free the output buffer */
+ gss_release_buffer(&gss_status, &output_token);
+
+ /* Free the message buffer */
+ free(message);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_gssapi_cleanup()
+ *
+ * This is used to clean up the gssapi specific data.
+ *
+ * Parameters:
+ *
+ * krb5 [in/out] - The kerberos 5 data struct being cleaned up.
+ *
+ */
+CURL_STATIC void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5)
+{
+ OM_uint32 minor_status;
+
+ /* Free our security context */
+ if(krb5->context != GSS_C_NO_CONTEXT) {
+ gss_delete_sec_context(&minor_status, &krb5->context, GSS_C_NO_BUFFER);
+ krb5->context = GSS_C_NO_CONTEXT;
+ }
+
+ /* Free the SPN */
+ if(krb5->spn != GSS_C_NO_NAME) {
+ gss_release_name(&minor_status, &krb5->spn);
+ krb5->spn = GSS_C_NO_NAME;
+ }
+}
+
+#endif /* HAVE_GSSAPI && USE_KERBEROS5 */
diff --git a/libcurl/src/lib/curl_sasl_sspi.c b/libcurl/src/lib/curl_sasl_sspi.c
new file mode 100644
index 0000000..71007ea
--- /dev/null
+++ b/libcurl/src/lib/curl_sasl_sspi.c
@@ -0,0 +1,1207 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2014 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2014, Steve Holme, <steve_holme@hotmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2617 Basic and Digest Access Authentication
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_WINDOWS_SSPI)
+
+#include <curl/curl.h>
+
+#include "curl_sasl.h"
+#include "urldata.h"
+#include "curl_base64.h"
+#include "warnless.h"
+#include "curl_multibyte.h"
+#include "sendf.h"
+#include "strdup.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * Curl_sasl_build_spn()
+ *
+ * This is used to build a SPN string in the format service/host.
+ *
+ * Parameters:
+ *
+ * serivce [in] - The service type such as www, smtp, pop or imap.
+ * host [in] - The host name or realm.
+ *
+ * Returns a pointer to the newly allocated SPN.
+ */
+CURL_STATIC TCHAR *Curl_sasl_build_spn(const char *service, const char *host)
+{
+ char *utf8_spn = NULL;
+ TCHAR *tchar_spn = NULL;
+
+ /* Note: We could use DsMakeSPN() or DsClientMakeSpnForTargetServer() rather
+ than doing this ourselves but the first is only available in Windows XP
+ and Windows Server 2003 and the latter is only available in Windows 2000
+ but not Windows95/98/ME or Windows NT4.0 unless the Active Directory
+ Client Extensions are installed. As such it is far simpler for us to
+ formulate the SPN instead. */
+
+ /* Allocate our UTF8 based SPN */
+ utf8_spn = aprintf("%s/%s", service, host);
+ if(!utf8_spn) {
+ return NULL;
+ }
+
+ /* Allocate our TCHAR based SPN */
+ tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn);
+ if(!tchar_spn) {
+ free(utf8_spn);
+
+ return NULL;
+ }
+
+ /* Release the UTF8 variant when operating with Unicode */
+ Curl_unicodefree(utf8_spn);
+
+ /* Return our newly allocated SPN */
+ return tchar_spn;
+}
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+/*
+ * Curl_sasl_create_digest_md5_message()
+ *
+ * This is used to generate an already encoded DIGEST-MD5 response message
+ * ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg64 [in] - The base64 encoded challenge message.
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
+ const char *chlg64,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ TCHAR *spn = NULL;
+ size_t chlglen = 0;
+ size_t token_max = 0;
+ unsigned char *input_token = NULL;
+ unsigned char *output_token = NULL;
+ CredHandle credentials;
+ CtxtHandle context;
+ PSecPkgInfo SecurityPackage;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ SecBuffer chlg_buf;
+ SecBuffer resp_buf;
+ SecBufferDesc chlg_desc;
+ SecBufferDesc resp_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+
+ /* Decode the base-64 encoded challenge message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &input_token, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!input_token) {
+ infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Query the security package for DigestSSP */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
+ &SecurityPackage);
+ if(status != SEC_E_OK) {
+ free(input_token);
+
+ return CURLE_NOT_BUILT_IN;
+ }
+
+ token_max = SecurityPackage->cbMaxToken;
+
+ /* Release the package buffer as it is not required anymore */
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+
+ /* Allocate our response buffer */
+ output_token = malloc(token_max);
+ if(!output_token) {
+ free(input_token);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Generate our SPN */
+ spn = Curl_sasl_build_spn(service, data->easy_conn->host.name);
+ if(!spn) {
+ free(output_token);
+ free(input_token);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(userp && *userp) {
+ /* Populate our identity structure */
+ result = Curl_create_sspi_identity(userp, passwdp, &identity);
+ if(result) {
+ free(spn);
+ free(output_token);
+ free(input_token);
+
+ return result;
+ }
+
+ /* Allow proper cleanup of the identity structure */
+ p_identity = &identity;
+ }
+ else
+ /* Use the current Windows user */
+ p_identity = NULL;
+
+ /* Acquire our credentials handle */
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT(SP_NAME_DIGEST),
+ SECPKG_CRED_OUTBOUND, NULL,
+ p_identity, NULL, NULL,
+ &credentials, &expiry);
+
+ if(status != SEC_E_OK) {
+ Curl_sspi_free_identity(p_identity);
+ free(spn);
+ free(output_token);
+ free(input_token);
+
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Setup the challenge "input" security buffer */
+ chlg_desc.ulVersion = SECBUFFER_VERSION;
+ chlg_desc.cBuffers = 1;
+ chlg_desc.pBuffers = &chlg_buf;
+ chlg_buf.BufferType = SECBUFFER_TOKEN;
+ chlg_buf.pvBuffer = input_token;
+ chlg_buf.cbBuffer = curlx_uztoul(chlglen);
+
+ /* Setup the response "output" security buffer */
+ resp_desc.ulVersion = SECBUFFER_VERSION;
+ resp_desc.cBuffers = 1;
+ resp_desc.pBuffers = &resp_buf;
+ resp_buf.BufferType = SECBUFFER_TOKEN;
+ resp_buf.pvBuffer = output_token;
+ resp_buf.cbBuffer = curlx_uztoul(token_max);
+
+ /* Generate our response message */
+ status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, spn,
+ 0, 0, 0, &chlg_desc, 0,
+ &context, &resp_desc, &attrs,
+ &expiry);
+
+ if(status == SEC_I_COMPLETE_NEEDED ||
+ status == SEC_I_COMPLETE_AND_CONTINUE)
+ s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
+ else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ s_pSecFn->FreeCredentialsHandle(&credentials);
+ Curl_sspi_free_identity(p_identity);
+ free(spn);
+ free(output_token);
+ free(input_token);
+
+ return CURLE_RECV_ERROR;
+ }
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer,
+ outptr, outlen);
+
+ /* Free our handles */
+ s_pSecFn->DeleteSecurityContext(&context);
+ s_pSecFn->FreeCredentialsHandle(&credentials);
+
+ /* Free the identity structure */
+ Curl_sspi_free_identity(p_identity);
+
+ /* Free the SPN */
+ free(spn);
+
+ /* Free the response buffer */
+ free(output_token);
+
+ /* Free the decoded challenge message */
+ free(input_token);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_decode_digest_http_message()
+ *
+ * This is used to decode a HTTP DIGEST challenge message into the seperate
+ * attributes.
+ *
+ * Parameters:
+ *
+ * chlg [in] - The challenge message.
+ * digest [in/out] - The digest data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_decode_digest_http_message(const char *chlg,
+ struct digestdata *digest)
+{
+ size_t chlglen = strlen(chlg);
+
+ /* We had an input token before and we got another one now. This means we
+ provided bad credentials in the previous request. */
+ if(digest->input_token)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Simply store the challenge for use later */
+ digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen);
+ if(!digest->input_token)
+ return CURLE_OUT_OF_MEMORY;
+
+ digest->input_token_len = chlglen;
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sasl_create_digest_http_message()
+ *
+ * This is used to generate a HTTP DIGEST response message ready for sending
+ * to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * request [in] - The HTTP request.
+ * uripath [in] - The path of the HTTP uri.
+ * digest [in/out] - The digest data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const unsigned char *request,
+ const unsigned char *uripath,
+ struct digestdata *digest,
+ char **outptr, size_t *outlen)
+{
+ size_t token_max;
+ CredHandle credentials;
+ CtxtHandle context;
+ char *resp;
+ BYTE *output_token;
+ PSecPkgInfo SecurityPackage;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ SecBuffer chlg_buf[3];
+ SecBuffer resp_buf;
+ SecBufferDesc chlg_desc;
+ SecBufferDesc resp_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+
+ (void) data;
+
+ /* Query the security package for DigestSSP */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
+ &SecurityPackage);
+ if(status != SEC_E_OK)
+ return CURLE_NOT_BUILT_IN;
+
+ token_max = SecurityPackage->cbMaxToken;
+
+ /* Release the package buffer as it is not required anymore */
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+
+ /* Allocate the output buffer according to the max token size as indicated
+ by the security package */
+ output_token = malloc(token_max);
+ if(!output_token)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(userp && *userp) {
+ /* Populate our identity structure */
+ if(Curl_create_sspi_identity(userp, passwdp, &identity))
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Allow proper cleanup of the identity structure */
+ p_identity = &identity;
+ }
+ else
+ /* Use the current Windows user */
+ p_identity = NULL;
+
+ /* Acquire our credentials handle */
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT(SP_NAME_DIGEST),
+ SECPKG_CRED_OUTBOUND, NULL,
+ p_identity, NULL, NULL,
+ &credentials, &expiry);
+ if(status != SEC_E_OK) {
+ free(output_token);
+
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Setup the challenge "input" security buffer if present */
+ chlg_desc.ulVersion = SECBUFFER_VERSION;
+ chlg_desc.cBuffers = 3;
+ chlg_desc.pBuffers = chlg_buf;
+ chlg_buf[0].BufferType = SECBUFFER_TOKEN;
+ chlg_buf[0].pvBuffer = digest->input_token;
+ chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len);
+ chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS;
+ chlg_buf[1].pvBuffer = (void *)request;
+ chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request));
+ chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS;
+ chlg_buf[2].pvBuffer = NULL;
+ chlg_buf[2].cbBuffer = 0;
+
+ /* Setup the response "output" security buffer */
+ resp_desc.ulVersion = SECBUFFER_VERSION;
+ resp_desc.cBuffers = 1;
+ resp_desc.pBuffers = &resp_buf;
+ resp_buf.BufferType = SECBUFFER_TOKEN;
+ resp_buf.pvBuffer = output_token;
+ resp_buf.cbBuffer = curlx_uztoul(token_max);
+
+ /* Generate our reponse message */
+ status = s_pSecFn->InitializeSecurityContext(&credentials, NULL,
+ (TCHAR *) uripath,
+ ISC_REQ_USE_HTTP_STYLE, 0, 0,
+ &chlg_desc, 0, &context,
+ &resp_desc, &attrs, &expiry);
+
+ if(status == SEC_I_COMPLETE_NEEDED ||
+ status == SEC_I_COMPLETE_AND_CONTINUE)
+ s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
+ else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ s_pSecFn->FreeCredentialsHandle(&credentials);
+
+ free(output_token);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ resp = malloc(resp_buf.cbBuffer + 1);
+ if(!resp) {
+ s_pSecFn->DeleteSecurityContext(&context);
+ s_pSecFn->FreeCredentialsHandle(&credentials);
+
+ free(output_token);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Copy the generated reponse */
+ memcpy(resp, resp_buf.pvBuffer, resp_buf.cbBuffer);
+ resp[resp_buf.cbBuffer] = 0x00;
+
+ /* Return the response */
+ *outptr = resp;
+ *outlen = resp_buf.cbBuffer;
+
+ /* Free our handles */
+ s_pSecFn->DeleteSecurityContext(&context);
+ s_pSecFn->FreeCredentialsHandle(&credentials);
+
+ /* Free the identity structure */
+ Curl_sspi_free_identity(p_identity);
+
+ /* Free the response buffer */
+ free(output_token);
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sasl_digest_cleanup()
+ *
+ * This is used to clean up the digest specific data.
+ *
+ * Parameters:
+ *
+ * digest [in/out] - The digest data struct being cleaned up.
+ *
+ */
+void Curl_sasl_digest_cleanup(struct digestdata *digest)
+{
+ /* Free the input token */
+ Curl_safefree(digest->input_token);
+
+ /* Reset any variables */
+ digest->input_token_len = 0;
+}
+#endif /* !CURL_DISABLE_CRYPTO_AUTH */
+
+#if defined USE_NTLM
+/*
+* Curl_sasl_create_ntlm_type1_message()
+*
+* This is used to generate an already encoded NTLM type-1 message ready for
+* sending to the recipient.
+*
+* Parameters:
+*
+* userp [in] - The user name in the format User or Domain\User.
+* passdwp [in] - The user's password.
+* ntlm [in/out] - The ntlm data struct being used and modified.
+* outptr [in/out] - The address where a pointer to newly allocated memory
+* holding the result will be stored upon completion.
+* outlen [out] - The length of the output message.
+*
+* Returns CURLE_OK on success.
+*/
+CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen)
+{
+ PSecPkgInfo SecurityPackage;
+ SecBuffer type_1_buf;
+ SecBufferDesc type_1_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+
+ /* Clean up any former leftovers and initialise to defaults */
+ Curl_sasl_ntlm_cleanup(ntlm);
+
+ /* Query the security package for NTLM */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
+ &SecurityPackage);
+ if(status != SEC_E_OK)
+ return CURLE_NOT_BUILT_IN;
+
+ ntlm->token_max = SecurityPackage->cbMaxToken;
+
+ /* Release the package buffer as it is not required anymore */
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+
+ /* Allocate our output buffer */
+ ntlm->output_token = malloc(ntlm->token_max);
+ if(!ntlm->output_token)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(userp && *userp) {
+ CURLcode result;
+
+ /* Populate our identity structure */
+ result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity);
+ if(result)
+ return result;
+
+ /* Allow proper cleanup of the identity structure */
+ ntlm->p_identity = &ntlm->identity;
+ }
+ else
+ /* Use the current Windows user */
+ ntlm->p_identity = NULL;
+
+ /* Allocate our credentials handle */
+ ntlm->credentials = malloc(sizeof(CredHandle));
+ if(!ntlm->credentials)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(ntlm->credentials, 0, sizeof(CredHandle));
+
+ /* Acquire our credentials handle */
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT(SP_NAME_NTLM),
+ SECPKG_CRED_OUTBOUND, NULL,
+ ntlm->p_identity, NULL, NULL,
+ ntlm->credentials, &expiry);
+ if(status != SEC_E_OK)
+ return CURLE_LOGIN_DENIED;
+
+ /* Allocate our new context handle */
+ ntlm->context = malloc(sizeof(CtxtHandle));
+ if(!ntlm->context)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(ntlm->context, 0, sizeof(CtxtHandle));
+
+ /* Setup the type-1 "output" security buffer */
+ type_1_desc.ulVersion = SECBUFFER_VERSION;
+ type_1_desc.cBuffers = 1;
+ type_1_desc.pBuffers = &type_1_buf;
+ type_1_buf.BufferType = SECBUFFER_TOKEN;
+ type_1_buf.pvBuffer = ntlm->output_token;
+ type_1_buf.cbBuffer = curlx_uztoul(ntlm->token_max);
+
+ /* Generate our type-1 message */
+ status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL,
+ (TCHAR *) TEXT(""),
+ 0, 0, SECURITY_NETWORK_DREP,
+ NULL, 0,
+ ntlm->context, &type_1_desc,
+ &attrs, &expiry);
+ if(status == SEC_I_COMPLETE_NEEDED ||
+ status == SEC_I_COMPLETE_AND_CONTINUE)
+ s_pSecFn->CompleteAuthToken(ntlm->context, &type_1_desc);
+ else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
+ return CURLE_RECV_ERROR;
+
+ /* Base64 encode the response */
+ return Curl_base64_encode(NULL, (char *) ntlm->output_token,
+ type_1_buf.cbBuffer, outptr, outlen);
+}
+
+/*
+* Curl_sasl_decode_ntlm_type2_message()
+*
+* This is used to decode an already encoded NTLM type-2 message.
+*
+* Parameters:
+*
+* data [in] - The session handle.
+* type2msg [in] - The base64 encoded type-2 message.
+* ntlm [in/out] - The ntlm data struct being used and modified.
+*
+* Returns CURLE_OK on success.
+*/
+CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
+ const char *type2msg,
+ struct ntlmdata *ntlm)
+{
+ CURLcode result = CURLE_OK;
+ unsigned char *type2 = NULL;
+ size_t type2_len = 0;
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) data;
+#endif
+
+ /* Decode the base-64 encoded type-2 message */
+ if(strlen(type2msg) && *type2msg != '=') {
+ result = Curl_base64_decode(type2msg, &type2, &type2_len);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid type-2 message */
+ if(!type2) {
+ infof(data, "NTLM handshake failure (empty type-2 message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Simply store the challenge for use later */
+ ntlm->input_token = type2;
+ ntlm->input_token_len = type2_len;
+
+ return result;
+}
+
+/*
+* Curl_sasl_create_ntlm_type3_message()
+*
+* This is used to generate an already encoded NTLM type-3 message ready for
+* sending to the recipient.
+*
+* Parameters:
+*
+* data [in] - The session handle.
+* userp [in] - The user name in the format User or Domain\User.
+* passdwp [in] - The user's password.
+* ntlm [in/out] - The ntlm data struct being used and modified.
+* outptr [in/out] - The address where a pointer to newly allocated memory
+* holding the result will be stored upon completion.
+* outlen [out] - The length of the output message.
+*
+* Returns CURLE_OK on success.
+*/
+CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ SecBuffer type_2_buf;
+ SecBuffer type_3_buf;
+ SecBufferDesc type_2_desc;
+ SecBufferDesc type_3_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+
+ (void) passwdp;
+ (void) userp;
+
+ /* Setup the type-2 "input" security buffer */
+ type_2_desc.ulVersion = SECBUFFER_VERSION;
+ type_2_desc.cBuffers = 1;
+ type_2_desc.pBuffers = &type_2_buf;
+ type_2_buf.BufferType = SECBUFFER_TOKEN;
+ type_2_buf.pvBuffer = ntlm->input_token;
+ type_2_buf.cbBuffer = curlx_uztoul(ntlm->input_token_len);
+
+ /* Setup the type-3 "output" security buffer */
+ type_3_desc.ulVersion = SECBUFFER_VERSION;
+ type_3_desc.cBuffers = 1;
+ type_3_desc.pBuffers = &type_3_buf;
+ type_3_buf.BufferType = SECBUFFER_TOKEN;
+ type_3_buf.pvBuffer = ntlm->output_token;
+ type_3_buf.cbBuffer = curlx_uztoul(ntlm->token_max);
+
+ /* Generate our type-3 message */
+ status = s_pSecFn->InitializeSecurityContext(ntlm->credentials,
+ ntlm->context,
+ (TCHAR *) TEXT(""),
+ 0, 0, SECURITY_NETWORK_DREP,
+ &type_2_desc,
+ 0, ntlm->context,
+ &type_3_desc,
+ &attrs, &expiry);
+ if(status != SEC_E_OK) {
+ infof(data, "NTLM handshake failure (type-3 message): Status=%x\n",
+ status);
+
+ return CURLE_RECV_ERROR;
+ }
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *) ntlm->output_token,
+ type_3_buf.cbBuffer, outptr, outlen);
+
+ Curl_sasl_ntlm_cleanup(ntlm);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_ntlm_cleanup()
+ *
+ * This is used to clean up the ntlm specific data.
+ *
+ * Parameters:
+ *
+ * ntlm [in/out] - The ntlm data struct being cleaned up.
+ *
+ */
+void Curl_sasl_ntlm_cleanup(struct ntlmdata *ntlm)
+{
+ /* Free our security context */
+ if(ntlm->context) {
+ s_pSecFn->DeleteSecurityContext(ntlm->context);
+ free(ntlm->context);
+ ntlm->context = NULL;
+ }
+
+ /* Free our credentials handle */
+ if(ntlm->credentials) {
+ s_pSecFn->FreeCredentialsHandle(ntlm->credentials);
+ free(ntlm->credentials);
+ ntlm->credentials = NULL;
+ }
+
+ /* Free our identity */
+ Curl_sspi_free_identity(ntlm->p_identity);
+ ntlm->p_identity = NULL;
+
+ /* Free the input and output tokens */
+ Curl_safefree(ntlm->input_token);
+ Curl_safefree(ntlm->output_token);
+
+ /* Reset any variables */
+ ntlm->token_max = 0;
+}
+#endif /* USE_NTLM */
+
+#if defined(USE_KERBEROS5)
+/*
+ * Curl_sasl_create_gssapi_user_message()
+ *
+ * This is used to generate an already encoded GSSAPI (Kerberos V5) user token
+ * message ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * mutual_auth [in] - Flag specifing whether or not mutual authentication
+ * is enabled.
+ * chlg64 [in] - The optional base64 encoded challenge message.
+ * krb5 [in/out] - The gssapi data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ const bool mutual_auth,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlglen = 0;
+ unsigned char *chlg = NULL;
+ CtxtHandle context;
+ PSecPkgInfo SecurityPackage;
+ SecBuffer chlg_buf;
+ SecBuffer resp_buf;
+ SecBufferDesc chlg_desc;
+ SecBufferDesc resp_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+
+ if(!krb5->credentials) {
+ /* Query the security package for Kerberos */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
+ TEXT(SP_NAME_KERBEROS),
+ &SecurityPackage);
+ if(status != SEC_E_OK) {
+ return CURLE_NOT_BUILT_IN;
+ }
+
+ krb5->token_max = SecurityPackage->cbMaxToken;
+
+ /* Release the package buffer as it is not required anymore */
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+
+ /* Allocate our response buffer */
+ krb5->output_token = malloc(krb5->token_max);
+ if(!krb5->output_token)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Generate our SPN */
+ krb5->spn = Curl_sasl_build_spn(service, data->easy_conn->host.name);
+ if(!krb5->spn)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(userp && *userp) {
+ /* Populate our identity structure */
+ result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
+ if(result)
+ return result;
+
+ /* Allow proper cleanup of the identity structure */
+ krb5->p_identity = &krb5->identity;
+ }
+ else
+ /* Use the current Windows user */
+ krb5->p_identity = NULL;
+
+ /* Allocate our credentials handle */
+ krb5->credentials = malloc(sizeof(CredHandle));
+ if(!krb5->credentials)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(krb5->credentials, 0, sizeof(CredHandle));
+
+ /* Acquire our credentials handle */
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *)
+ TEXT(SP_NAME_KERBEROS),
+ SECPKG_CRED_OUTBOUND, NULL,
+ krb5->p_identity, NULL, NULL,
+ krb5->credentials, &expiry);
+ if(status != SEC_E_OK)
+ return CURLE_LOGIN_DENIED;
+
+ /* Allocate our new context handle */
+ krb5->context = malloc(sizeof(CtxtHandle));
+ if(!krb5->context)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(krb5->context, 0, sizeof(CtxtHandle));
+ }
+ else {
+ /* Decode the base-64 encoded challenge message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg) {
+ infof(data, "GSSAPI handshake failure (empty challenge message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Setup the challenge "input" security buffer */
+ chlg_desc.ulVersion = SECBUFFER_VERSION;
+ chlg_desc.cBuffers = 1;
+ chlg_desc.pBuffers = &chlg_buf;
+ chlg_buf.BufferType = SECBUFFER_TOKEN;
+ chlg_buf.pvBuffer = chlg;
+ chlg_buf.cbBuffer = curlx_uztoul(chlglen);
+ }
+
+ /* Setup the response "output" security buffer */
+ resp_desc.ulVersion = SECBUFFER_VERSION;
+ resp_desc.cBuffers = 1;
+ resp_desc.pBuffers = &resp_buf;
+ resp_buf.BufferType = SECBUFFER_TOKEN;
+ resp_buf.pvBuffer = krb5->output_token;
+ resp_buf.cbBuffer = curlx_uztoul(krb5->token_max);
+
+ /* Generate our challenge-response message */
+ status = s_pSecFn->InitializeSecurityContext(krb5->credentials,
+ chlg ? krb5->context : NULL,
+ krb5->spn,
+ (mutual_auth ?
+ ISC_REQ_MUTUAL_AUTH : 0),
+ 0, SECURITY_NATIVE_DREP,
+ chlg ? &chlg_desc : NULL, 0,
+ &context,
+ &resp_desc, &attrs,
+ &expiry);
+
+ if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ free(chlg);
+
+ return CURLE_RECV_ERROR;
+ }
+
+ if(memcmp(&context, krb5->context, sizeof(context))) {
+ s_pSecFn->DeleteSecurityContext(krb5->context);
+
+ memcpy(krb5->context, &context, sizeof(context));
+ }
+
+ if(resp_buf.cbBuffer) {
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *)resp_buf.pvBuffer,
+ resp_buf.cbBuffer, outptr, outlen);
+ }
+
+ /* Free the decoded challenge */
+ free(chlg);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_create_gssapi_security_message()
+ *
+ * This is used to generate an already encoded GSSAPI (Kerberos V5) security
+ * token message ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg64 [in] - The optional base64 encoded challenge message.
+ * krb5 [in/out] - The gssapi data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr,
+ size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t offset = 0;
+ size_t chlglen = 0;
+ size_t messagelen = 0;
+ size_t appdatalen = 0;
+ unsigned char *chlg = NULL;
+ unsigned char *trailer = NULL;
+ unsigned char *message = NULL;
+ unsigned char *padding = NULL;
+ unsigned char *appdata = NULL;
+ SecBuffer input_buf[2];
+ SecBuffer wrap_buf[3];
+ SecBufferDesc input_desc;
+ SecBufferDesc wrap_desc;
+ unsigned long indata = 0;
+ unsigned long outdata = 0;
+ unsigned long qop = 0;
+ unsigned long sec_layer = 0;
+ unsigned long max_size = 0;
+ SecPkgContext_Sizes sizes;
+ SecPkgCredentials_Names names;
+ SECURITY_STATUS status;
+ char *user_name;
+
+ /* Decode the base-64 encoded input message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg) {
+ infof(data, "GSSAPI handshake failure (empty security message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Get our response size information */
+ status = s_pSecFn->QueryContextAttributes(krb5->context,
+ SECPKG_ATTR_SIZES,
+ &sizes);
+ if(status != SEC_E_OK) {
+ free(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Get the fully qualified username back from the context */
+ status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials,
+ SECPKG_CRED_ATTR_NAMES,
+ &names);
+ if(status != SEC_E_OK) {
+ free(chlg);
+
+ return CURLE_RECV_ERROR;
+ }
+
+ /* Setup the "input" security buffer */
+ input_desc.ulVersion = SECBUFFER_VERSION;
+ input_desc.cBuffers = 2;
+ input_desc.pBuffers = input_buf;
+ input_buf[0].BufferType = SECBUFFER_STREAM;
+ input_buf[0].pvBuffer = chlg;
+ input_buf[0].cbBuffer = curlx_uztoul(chlglen);
+ input_buf[1].BufferType = SECBUFFER_DATA;
+ input_buf[1].pvBuffer = NULL;
+ input_buf[1].cbBuffer = 0;
+
+ /* Decrypt the inbound challenge and obtain the qop */
+ status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
+ if(status != SEC_E_OK) {
+ infof(data, "GSSAPI handshake failure (empty security message)\n");
+
+ free(chlg);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Not 4 octets long so fail as per RFC4752 Section 3.1 */
+ if(input_buf[1].cbBuffer != 4) {
+ infof(data, "GSSAPI handshake failure (invalid security data)\n");
+
+ free(chlg);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Copy the data out and free the challenge as it is not required anymore */
+ memcpy(&indata, input_buf[1].pvBuffer, 4);
+ s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
+ free(chlg);
+
+ /* Extract the security layer */
+ sec_layer = indata & 0x000000FF;
+ if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
+ infof(data, "GSSAPI handshake failure (invalid security layer)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Extract the maximum message size the server can receive */
+ max_size = ntohl(indata & 0xFFFFFF00);
+ if(max_size > 0) {
+ /* The server has told us it supports a maximum receive buffer, however, as
+ we don't require one unless we are encrypting data, we tell the server
+ our receive buffer is zero. */
+ max_size = 0;
+ }
+
+ /* Allocate the trailer */
+ trailer = malloc(sizes.cbSecurityTrailer);
+ if(!trailer)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Convert the user name to UTF8 when operating with Unicode */
+ user_name = Curl_convert_tchar_to_UTF8(names.sUserName);
+ if(!user_name) {
+ free(trailer);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Allocate our message */
+ messagelen = sizeof(outdata) + strlen(user_name) + 1;
+ message = malloc(messagelen);
+ if(!message) {
+ free(trailer);
+ Curl_unicodefree(user_name);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Populate the message with the security layer, client supported receive
+ message size and authorization identity including the 0x00 based
+ terminator. Note: Dispite RFC4752 Section 3.1 stating "The authorization
+ identity is not terminated with the zero-valued (%x00) octet." it seems
+ necessary to include it. */
+ outdata = htonl(max_size) | sec_layer;
+ memcpy(message, &outdata, sizeof(outdata));
+ strcpy((char *) message + sizeof(outdata), user_name);
+ Curl_unicodefree(user_name);
+
+ /* Allocate the padding */
+ padding = malloc(sizes.cbBlockSize);
+ if(!padding) {
+ free(message);
+ free(trailer);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Setup the "authentication data" security buffer */
+ wrap_desc.ulVersion = SECBUFFER_VERSION;
+ wrap_desc.cBuffers = 3;
+ wrap_desc.pBuffers = wrap_buf;
+ wrap_buf[0].BufferType = SECBUFFER_TOKEN;
+ wrap_buf[0].pvBuffer = trailer;
+ wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer;
+ wrap_buf[1].BufferType = SECBUFFER_DATA;
+ wrap_buf[1].pvBuffer = message;
+ wrap_buf[1].cbBuffer = curlx_uztoul(messagelen);
+ wrap_buf[2].BufferType = SECBUFFER_PADDING;
+ wrap_buf[2].pvBuffer = padding;
+ wrap_buf[2].cbBuffer = sizes.cbBlockSize;
+
+ /* Encrypt the data */
+ status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT,
+ &wrap_desc, 0);
+ if(status != SEC_E_OK) {
+ free(padding);
+ free(message);
+ free(trailer);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Allocate the encryption (wrap) buffer */
+ appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer +
+ wrap_buf[2].cbBuffer;
+ appdata = malloc(appdatalen);
+ if(!appdata) {
+ free(padding);
+ free(message);
+ free(trailer);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Populate the encryption buffer */
+ memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer);
+ offset += wrap_buf[0].cbBuffer;
+ memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer);
+ offset += wrap_buf[1].cbBuffer;
+ memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer);
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *)appdata, appdatalen, outptr,
+ outlen);
+
+ /* Free all of our local buffers */
+ free(appdata);
+ free(padding);
+ free(message);
+ free(trailer);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_gssapi_cleanup()
+ *
+ * This is used to clean up the gssapi specific data.
+ *
+ * Parameters:
+ *
+ * krb5 [in/out] - The kerberos 5 data struct being cleaned up.
+ *
+ */
+CURL_STATIC void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5)
+{
+ /* Free our security context */
+ if(krb5->context) {
+ s_pSecFn->DeleteSecurityContext(krb5->context);
+ free(krb5->context);
+ krb5->context = NULL;
+ }
+
+ /* Free our credentials handle */
+ if(krb5->credentials) {
+ s_pSecFn->FreeCredentialsHandle(krb5->credentials);
+ free(krb5->credentials);
+ krb5->credentials = NULL;
+ }
+
+ /* Free our identity */
+ Curl_sspi_free_identity(krb5->p_identity);
+ krb5->p_identity = NULL;
+
+ /* Free the SPN and output token */
+ Curl_safefree(krb5->spn);
+ Curl_safefree(krb5->output_token);
+
+ /* Reset any variables */
+ krb5->token_max = 0;
+}
+#endif /* USE_KERBEROS5 */
+
+#endif /* USE_WINDOWS_SSPI */
diff --git a/libcurl/src/lib/curl_sec.h b/libcurl/src/lib/curl_sec.h
new file mode 100644
index 0000000..9cb6d0a
--- /dev/null
+++ b/libcurl/src/lib/curl_sec.h
@@ -0,0 +1,51 @@
+#ifndef HEADER_CURL_SECURITY_H
+#define HEADER_CURL_SECURITY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct Curl_sec_client_mech {
+ const char *name;
+ size_t size;
+ int (*init)(void *);
+ int (*auth)(void *, struct connectdata *);
+ void (*end)(void *);
+ int (*check_prot)(void *, int);
+ int (*overhead)(void *, int, int);
+ int (*encode)(void *, const void*, int, int, void**);
+ int (*decode)(void *, void*, int, int, struct connectdata *);
+};
+
+#define AUTH_OK 0
+#define AUTH_CONTINUE 1
+#define AUTH_ERROR 2
+
+#ifdef HAVE_GSSAPI
+CURL_STATIC int Curl_sec_read_msg (struct connectdata *conn, char *,
+ enum protection_level);
+CURL_STATIC void Curl_sec_end (struct connectdata *);
+CURL_STATIC CURLcode Curl_sec_login (struct connectdata *);
+CURL_STATIC int Curl_sec_request_prot (struct connectdata *conn, const char *level);
+
+extern struct Curl_sec_client_mech Curl_krb5_client_mech;
+#endif
+
+#endif /* HEADER_CURL_SECURITY_H */
diff --git a/libcurl/src/lib/curl_setup.h b/libcurl/src/lib/curl_setup.h
new file mode 100644
index 0000000..7709e0e
--- /dev/null
+++ b/libcurl/src/lib/curl_setup.h
@@ -0,0 +1,713 @@
+#ifndef HEADER_CURL_SETUP_H
+#define HEADER_CURL_SETUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \
+ !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+/*
+ * Include configuration script results or hand-crafted
+ * configuration file for platforms which lack config tool.
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "curl_config.h"
+
+#else /* HAVE_CONFIG_H */
+
+#ifdef _WIN32_WCE
+# include "config-win32ce.h"
+#elif defined(CURL_WINRT)
+# include "config-winrt.h"
+#elif defined(WIN32)
+# include "config-win32.h"
+#elif defined(macintosh) && defined(__MRC__)
+# include "config-mac.h"
+#elif defined(__APPLE__)
+# include "TargetConditionals.h"
+# if TARGET_IPHONE_SIMULATOR
+# include "config-ios-sim.h"
+# elif TARGET_OS_IPHONE
+# include "config-ios.h"
+# elif TARGET_OS_MAC
+# include "config-osx.h"
+# endif
+#elif defined(__ANDROID__) && (defined(__arm__) || defined(_M_ARM))
+# include "config-android-arm.h"
+#elif defined(__ANDROID__) && (defined(__i386__) || defined(_M_IX86))
+# include "config-android-x86.h"
+#elif defined(__EMSCRIPTEN__)
+# include "config-emscripten.h"
+#elif defined(__riscos__)
+# include "config-riscos.h"
+#elif defined(__AMIGA__)
+# include "config-amigaos.h"
+#elif defined(__SYMBIAN32__)
+# include "config-symbian.h"
+#elif defined(__OS400__)
+# include "config-os400.h"
+#elif defined(TPF)
+# include "config-tpf.h"
+#elif defined(__VXWORKS__)
+# include "config-vxworks.h"
+#else
+#error Add missing configuration.
+#endif
+
+#endif /* HAVE_CONFIG_H */
+
+/* ================================================================ */
+/* Definition of preprocessor macros/symbols which modify compiler */
+/* behavior or generated code characteristics must be done here, */
+/* as appropriate, before any system header file is included. It is */
+/* also possible to have them defined in the config file included */
+/* before this point. As a result of all this we frown inclusion of */
+/* system header files in our config files, avoid this at any cost. */
+/* ================================================================ */
+
+/*
+ * AIX 4.3 and newer needs _THREAD_SAFE defined to build
+ * proper reentrant code. Others may also need it.
+ */
+
+#ifdef NEED_THREAD_SAFE
+# ifndef _THREAD_SAFE
+# define _THREAD_SAFE
+# endif
+#endif
+
+/*
+ * Tru64 needs _REENTRANT set for a few function prototypes and
+ * things to appear in the system header files. Unixware needs it
+ * to build proper reentrant code. Others may also need it.
+ */
+
+#ifdef NEED_REENTRANT
+# ifndef _REENTRANT
+# define _REENTRANT
+# endif
+#endif
+
+/* Solaris needs this to get a POSIX-conformant getpwuid_r */
+#if defined(sun) || defined(__sun)
+# ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+# endif
+#endif
+
+/* ================================================================ */
+/* If you need to include a system header file for your platform, */
+/* please, do it beyond the point further indicated in this file. */
+/* ================================================================ */
+
+/*
+ * libcurl's external interface definitions are also used internally,
+ * and might also include required system header files to define them.
+ */
+
+#include <curl/curlbuild.h>
+
+/*
+ * Compile time sanity checks must also be done when building the library.
+ */
+
+#include <curl/curlrules.h>
+
+/*
+ * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro
+ */
+
+#ifdef SIZEOF_CURL_OFF_T
+# error "SIZEOF_CURL_OFF_T shall not be defined!"
+ Error Compilation_aborted_SIZEOF_CURL_OFF_T_shall_not_be_defined
+#endif
+
+/*
+ * Disable other protocols when http is the only one desired.
+ */
+
+#ifdef HTTP_ONLY
+# ifndef CURL_DISABLE_TFTP
+# define CURL_DISABLE_TFTP
+# endif
+# ifndef CURL_DISABLE_FTP
+# define CURL_DISABLE_FTP
+# endif
+# ifndef CURL_DISABLE_LDAP
+# define CURL_DISABLE_LDAP
+# endif
+# ifndef CURL_DISABLE_TELNET
+# define CURL_DISABLE_TELNET
+# endif
+# ifndef CURL_DISABLE_DICT
+# define CURL_DISABLE_DICT
+# endif
+# ifndef CURL_DISABLE_FILE
+# define CURL_DISABLE_FILE
+# endif
+# ifndef CURL_DISABLE_RTSP
+# define CURL_DISABLE_RTSP
+# endif
+# ifndef CURL_DISABLE_POP3
+# define CURL_DISABLE_POP3
+# endif
+# ifndef CURL_DISABLE_IMAP
+# define CURL_DISABLE_IMAP
+# endif
+# ifndef CURL_DISABLE_SMTP
+# define CURL_DISABLE_SMTP
+# endif
+# ifndef CURL_DISABLE_RTSP
+# define CURL_DISABLE_RTSP
+# endif
+# ifndef CURL_DISABLE_RTMP
+# define CURL_DISABLE_RTMP
+# endif
+# ifndef CURL_DISABLE_GOPHER
+# define CURL_DISABLE_GOPHER
+# endif
+# ifndef CURL_DISABLE_SMB
+# define CURL_DISABLE_SMB
+# endif
+#endif
+
+/*
+ * When http is disabled rtsp is not supported.
+ */
+
+#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP)
+# define CURL_DISABLE_RTSP
+#endif
+
+/* ================================================================ */
+/* No system header file shall be included in this file before this */
+/* point. The only allowed ones are those included from curlbuild.h */
+/* ================================================================ */
+
+/*
+ * OS/400 setup file includes some system headers.
+ */
+
+#ifdef __OS400__
+# include "setup-os400.h"
+#endif
+
+/*
+ * VMS setup file includes some system headers.
+ */
+
+#ifdef __VMS
+# include "setup-vms.h"
+#endif
+
+/*
+ * Include header files for windows builds before redefining anything.
+ * Use this preprocessor block only to include or exclude windows.h,
+ * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs
+ * to any other further and independent block. Under Cygwin things work
+ * just as under linux (e.g. <sys/socket.h>) and the winsock headers should
+ * never be included when __CYGWIN__ is defined. configure script takes
+ * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H,
+ * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
+ */
+
+#ifdef HAVE_WINDOWS_H
+# if defined(UNICODE) && !defined(_UNICODE)
+# define _UNICODE
+# endif
+# if defined(_UNICODE) && !defined(UNICODE)
+# define UNICODE
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+# ifdef HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+# endif
+# else
+# ifdef HAVE_WINSOCK_H
+# include <winsock.h>
+# endif
+# endif
+# include <tchar.h>
+# ifdef UNICODE
+ typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
+# endif
+#endif
+
+/*
+ * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
+ * define USE_WINSOCK to 1 if we have and use WINSOCK API, else
+ * undefine USE_WINSOCK.
+ */
+
+#undef USE_WINSOCK
+
+#ifdef HAVE_WINSOCK2_H
+# define USE_WINSOCK 2
+#else
+# ifdef HAVE_WINSOCK_H
+# define USE_WINSOCK 1
+# endif
+#endif
+
+#ifdef USE_LWIPSOCK
+# include <lwip/init.h>
+# include <lwip/sockets.h>
+# include <lwip/netdb.h>
+#endif
+
+#ifdef HAVE_EXTRA_STRICMP_H
+# include <extra/stricmp.h>
+#endif
+
+#ifdef HAVE_EXTRA_STRDUP_H
+# include <extra/strdup.h>
+#endif
+
+#ifdef TPF
+# include <strings.h> /* for bzero, strcasecmp, and strncasecmp */
+# include <string.h> /* for strcpy and strlen */
+# include <stdlib.h> /* for rand and srand */
+# include <sys/socket.h> /* for select and ioctl*/
+# include <netdb.h> /* for in_addr_t definition */
+# include <tpf/sysapi.h> /* for tpf_process_signals */
+ /* change which select is used for libcurl */
+# define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e)
+#endif
+
+#ifdef __VXWORKS__
+# include <sockLib.h> /* for generic BSD socket functions */
+# include <ioLib.h> /* for basic I/O interface functions */
+#endif
+
+#ifdef __AMIGA__
+# ifndef __ixemul__
+# include <exec/types.h>
+# include <exec/execbase.h>
+# include <proto/exec.h>
+# include <proto/dos.h>
+# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
+# endif
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#ifdef __TANDEM /* for nsr-tandem-nsk systems */
+#include <floss.h>
+#endif
+
+#ifndef STDC_HEADERS /* no standard C headers! */
+#include <curl/stdcheaders.h>
+#endif
+
+#ifdef __POCC__
+# include <sys/types.h>
+# include <unistd.h>
+# define sys_nerr EILSEQ
+#endif
+
+/*
+ * Salford-C kludge section (mostly borrowed from wxWidgets).
+ */
+#ifdef __SALFORDC__
+ #pragma suppress 353 /* Possible nested comments */
+ #pragma suppress 593 /* Define not used */
+ #pragma suppress 61 /* enum has no name */
+ #pragma suppress 106 /* unnamed, unused parameter */
+ #include <clib.h>
+#endif
+
+/*
+ * Large file (>2Gb) support using WIN32 functions.
+ */
+
+#ifdef USE_WIN32_LARGE_FILES
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# undef lseek
+# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence)
+# undef fstat
+# define fstat(fdes,stp) _fstati64(fdes, stp)
+# undef stat
+# define stat(fname,stp) _stati64(fname, stp)
+# define struct_stat struct _stati64
+# define LSEEK_ERROR (__int64)-1
+#endif
+
+/*
+ * Small file (<2Gb) support using WIN32 functions.
+ */
+
+#ifdef USE_WIN32_SMALL_FILES
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# ifndef _WIN32_WCE
+# undef lseek
+# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence)
+# define fstat(fdes,stp) _fstat(fdes, stp)
+# define stat(fname,stp) _stat(fname, stp)
+# define struct_stat struct _stat
+# endif
+# define LSEEK_ERROR (long)-1
+#endif
+
+#ifndef struct_stat
+# define struct_stat struct stat
+#endif
+
+#ifndef LSEEK_ERROR
+# define LSEEK_ERROR (off_t)-1
+#endif
+
+/*
+ * Default sizeof(off_t) in case it hasn't been defined in config file.
+ */
+
+#ifndef SIZEOF_OFF_T
+# if defined(__VMS) && !defined(__VAX)
+# if defined(_LARGEFILE)
+# define SIZEOF_OFF_T 8
+# endif
+# elif defined(__OS400__) && defined(__ILEC400__)
+# if defined(_LARGE_FILES)
+# define SIZEOF_OFF_T 8
+# endif
+# elif defined(__MVS__) && defined(__IBMC__)
+# if defined(_LP64) || defined(_LARGE_FILES)
+# define SIZEOF_OFF_T 8
+# endif
+# elif defined(__370__) && defined(__IBMC__)
+# if defined(_LP64) || defined(_LARGE_FILES)
+# define SIZEOF_OFF_T 8
+# endif
+# endif
+# ifndef SIZEOF_OFF_T
+# define SIZEOF_OFF_T 4
+# endif
+#endif
+
+/*
+ * Arg 2 type for gethostname in case it hasn't been defined in config file.
+ */
+
+#ifndef GETHOSTNAME_TYPE_ARG2
+# ifdef USE_WINSOCK
+# define GETHOSTNAME_TYPE_ARG2 int
+# else
+# define GETHOSTNAME_TYPE_ARG2 size_t
+# endif
+#endif
+
+/* Below we define some functions. They should
+
+ 4. set the SIGALRM signal timeout
+ 5. set dir/file naming defines
+ */
+
+#ifdef WIN32
+
+# define DIR_CHAR "\\"
+# define DOT_CHAR "_"
+
+#else /* WIN32 */
+
+# ifdef MSDOS /* Watt-32 */
+
+# include <sys/ioctl.h>
+# define select(n,r,w,x,t) select_s(n,r,w,x,t)
+# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
+# include <tcp.h>
+# ifdef word
+# undef word
+# endif
+# ifdef byte
+# undef byte
+# endif
+
+# endif /* MSDOS */
+
+# ifdef __minix
+ /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
+ extern char * strtok_r(char *s, const char *delim, char **last);
+ extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp);
+# endif
+
+# define DIR_CHAR "/"
+# ifndef DOT_CHAR
+# define DOT_CHAR "."
+# endif
+
+# ifdef MSDOS
+# undef DOT_CHAR
+# define DOT_CHAR "_"
+# endif
+
+# ifndef fileno /* sunos 4 have this as a macro! */
+ int fileno( FILE *stream);
+# endif
+
+#endif /* WIN32 */
+
+/*
+ * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
+ * defined in ws2tcpip.h as well as to provide IPv6 support.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# if !defined(HAVE_WS2TCPIP_H) || \
+ ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
+# undef HAVE_GETADDRINFO_THREADSAFE
+# undef HAVE_FREEADDRINFO
+# undef HAVE_GETADDRINFO
+# undef HAVE_GETNAMEINFO
+# undef ENABLE_IPV6
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* resolver specialty compile-time defines */
+/* CURLRES_* defines to use in the host*.c sources */
+/* ---------------------------------------------------------------- */
+
+/*
+ * lcc-win32 doesn't have _beginthreadex(), lacks threads support.
+ */
+
+#if defined(__LCC__) && defined(WIN32)
+# undef USE_THREADS_POSIX
+# undef USE_THREADS_WIN32
+#endif
+
+/*
+ * MSVC threads support requires a multi-threaded runtime library.
+ * _beginthreadex() is not available in single-threaded ones.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
+# undef USE_THREADS_POSIX
+# undef USE_THREADS_WIN32
+#endif
+
+/*
+ * Mutually exclusive CURLRES_* definitions.
+ */
+
+#ifdef USE_ARES
+# define CURLRES_ASYNCH
+# define CURLRES_ARES
+/* now undef the stock libc functions just to avoid them being used */
+# undef HAVE_GETADDRINFO
+# undef HAVE_GETHOSTBYNAME
+#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+# define CURLRES_ASYNCH
+# define CURLRES_THREADED
+#else
+# define CURLRES_SYNCH
+#endif
+
+#ifdef ENABLE_IPV6
+# define CURLRES_IPV6
+#else
+# define CURLRES_IPV4
+#endif
+
+/* ---------------------------------------------------------------- */
+
+/*
+ * When using WINSOCK, TELNET protocol requires WINSOCK2 API.
+ */
+
+#if defined(USE_WINSOCK) && (USE_WINSOCK != 2)
+# define CURL_DISABLE_TELNET 1
+#endif
+
+/*
+ * msvc 6.0 does not have struct sockaddr_storage and
+ * does not define IPPROTO_ESP in winsock2.h. But both
+ * are available if PSDK is properly installed.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
+# undef HAVE_STRUCT_SOCKADDR_STORAGE
+# endif
+#endif
+
+/*
+ * Intentionally fail to build when using msvc 6.0 without PSDK installed.
+ * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
+ * in lib/config-win32.h although absolutely discouraged and unsupported.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
+# if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
+# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
+ "Windows Server 2003 PSDK"
+# else
+# define CURL_DISABLE_LDAP 1
+# endif
+# endif
+#endif
+
+#ifdef NETWARE
+int netware_init(void);
+#ifndef __NOVELL_LIBC__
+#include <sys/bsdskt.h>
+#include <sys/timeval.h>
+#endif
+#endif
+
+#if defined(HAVE_LIBIDN) && defined(HAVE_TLD_H)
+/* The lib was present and the tld.h header (which is missing in libidn 0.3.X
+ but we only work with libidn 0.4.1 or later) */
+#define USE_LIBIDN
+#endif
+
+#ifndef SIZEOF_TIME_T
+/* assume default size of time_t to be 32 bit */
+#define SIZEOF_TIME_T 4
+#endif
+
+#define LIBIDN_REQUIRED_VERSION "0.4.1"
+
+#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
+ defined(USE_POLARSSL) || defined(USE_AXTLS) || \
+ defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
+ defined(USE_DARWINSSL) || defined(USE_GSKIT)
+#define USE_SSL /* SSL support has been enabled */
+#endif
+
+/* Single point where USE_SPNEGO definition might be defined */
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
+ (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
+#define USE_SPNEGO
+#endif
+
+/* Single point where USE_KERBEROS5 definition might be defined */
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
+ (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
+#define USE_KERBEROS5
+#endif
+
+/* Single point where USE_NTLM definition might be defined */
+#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
+ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
+ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
+
+#ifdef HAVE_BORINGSSL /* BoringSSL is not NTLM capable */
+#undef USE_NTLM
+#else
+#define USE_NTLM
+#endif
+#endif
+#endif
+
+/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */
+#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE)
+#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
+#endif
+
+/*
+ * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
+ * Parameters should of course normally not be unused, but for example when
+ * we have multiple implementations of the same interface it may happen.
+ */
+
+#if defined(__GNUC__) && ((__GNUC__ >= 3) || \
+ ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
+# define UNUSED_PARAM __attribute__((__unused__))
+# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+# define UNUSED_PARAM /*NOTHING*/
+# define WARN_UNUSED_RESULT
+#endif
+
+/*
+ * Include macros and defines that should only be processed once.
+ */
+
+#ifndef HEADER_CURL_SETUP_ONCE_H
+#include "curl_setup_once.h"
+#endif
+
+/*
+ * Definition of our NOP statement Object-like macro
+ */
+
+#ifndef Curl_nop_stmt
+# define Curl_nop_stmt do { } WHILE_FALSE
+#endif
+
+/*
+ * Ensure that Winsock and lwIP TCP/IP stacks are not mixed.
+ */
+
+#if defined(__LWIP_OPT_H__)
+# if defined(SOCKET) || \
+ defined(USE_WINSOCK) || \
+ defined(HAVE_WINSOCK_H) || \
+ defined(HAVE_WINSOCK2_H) || \
+ defined(HAVE_WS2TCPIP_H)
+# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
+# endif
+#endif
+
+/*
+ * Portable symbolic names for Winsock shutdown() mode flags.
+ */
+
+#ifdef USE_WINSOCK
+# define SHUT_RD 0x00
+# define SHUT_WR 0x01
+# define SHUT_RDWR 0x02
+#endif
+
+/* Define S_ISREG if not defined by system headers, f.e. MSVC */
+#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+/* Define S_ISDIR if not defined by system headers, f.e. MSVC */
+#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+#endif /* HEADER_CURL_SETUP_H */
diff --git a/libcurl/src/lib/curl_setup_once.h b/libcurl/src/lib/curl_setup_once.h
new file mode 100644
index 0000000..69d6d47
--- /dev/null
+++ b/libcurl/src/lib/curl_setup_once.h
@@ -0,0 +1,551 @@
+#ifndef HEADER_CURL_SETUP_ONCE_H
+#define HEADER_CURL_SETUP_ONCE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/*
+ * Inclusion of common header files.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef NEED_MALLOC_H
+#include <malloc.h>
+#endif
+
+#ifdef NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#endif
+
+#ifdef WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T)
+#include <stdbool.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef _APP32_64BIT_OFF_T
+# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
+# undef _APP32_64BIT_OFF_T
+# else
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef OLD_APP32_64BIT_OFF_T
+# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+
+/*
+ * Definition of timeval struct for platforms that don't have it.
+ */
+
+#ifndef HAVE_STRUCT_TIMEVAL
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+#endif
+
+
+/*
+ * If we have the MSG_NOSIGNAL define, make sure we use
+ * it as the fourth argument of function send()
+ */
+
+#ifdef HAVE_MSG_NOSIGNAL
+#define SEND_4TH_ARG MSG_NOSIGNAL
+#else
+#define SEND_4TH_ARG 0
+#endif
+
+
+#if defined(__minix)
+/* Minix doesn't support recv on TCP sockets */
+#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \
+ (RECV_TYPE_ARG2)(y), \
+ (RECV_TYPE_ARG3)(z))
+
+#elif defined(HAVE_RECV)
+/*
+ * The definitions for the return type and arguments types
+ * of functions recv() and send() belong and come from the
+ * configuration file. Do not define them in any other place.
+ *
+ * HAVE_RECV is defined if you have a function named recv()
+ * which is used to read incoming data from sockets. If your
+ * function has another name then don't define HAVE_RECV.
+ *
+ * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2,
+ * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also
+ * be defined.
+ *
+ * HAVE_SEND is defined if you have a function named send()
+ * which is used to write outgoing data on a connected socket.
+ * If yours has another name then don't define HAVE_SEND.
+ *
+ * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2,
+ * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and
+ * SEND_TYPE_RETV must also be defined.
+ */
+
+#if !defined(RECV_TYPE_ARG1) || \
+ !defined(RECV_TYPE_ARG2) || \
+ !defined(RECV_TYPE_ARG3) || \
+ !defined(RECV_TYPE_ARG4) || \
+ !defined(RECV_TYPE_RETV)
+ /* */
+ Error Missing_definition_of_return_and_arguments_types_of_recv
+ /* */
+#else
+#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
+ (RECV_TYPE_ARG2)(y), \
+ (RECV_TYPE_ARG3)(z), \
+ (RECV_TYPE_ARG4)(0))
+#endif
+#else /* HAVE_RECV */
+#ifndef sread
+ /* */
+ Error Missing_definition_of_macro_sread
+ /* */
+#endif
+#endif /* HAVE_RECV */
+
+
+#if defined(__minix)
+/* Minix doesn't support send on TCP sockets */
+#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \
+ (SEND_TYPE_ARG2)(y), \
+ (SEND_TYPE_ARG3)(z))
+
+#elif defined(HAVE_SEND)
+#if !defined(SEND_TYPE_ARG1) || \
+ !defined(SEND_QUAL_ARG2) || \
+ !defined(SEND_TYPE_ARG2) || \
+ !defined(SEND_TYPE_ARG3) || \
+ !defined(SEND_TYPE_ARG4) || \
+ !defined(SEND_TYPE_RETV)
+ /* */
+ Error Missing_definition_of_return_and_arguments_types_of_send
+ /* */
+#else
+#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
+ (SEND_TYPE_ARG2)(y), \
+ (SEND_TYPE_ARG3)(z), \
+ (SEND_TYPE_ARG4)(SEND_4TH_ARG))
+#endif
+#else /* HAVE_SEND */
+#ifndef swrite
+ /* */
+ Error Missing_definition_of_macro_swrite
+ /* */
+#endif
+#endif /* HAVE_SEND */
+
+
+#if 0
+#if defined(HAVE_RECVFROM)
+/*
+ * Currently recvfrom is only used on udp sockets.
+ */
+#if !defined(RECVFROM_TYPE_ARG1) || \
+ !defined(RECVFROM_TYPE_ARG2) || \
+ !defined(RECVFROM_TYPE_ARG3) || \
+ !defined(RECVFROM_TYPE_ARG4) || \
+ !defined(RECVFROM_TYPE_ARG5) || \
+ !defined(RECVFROM_TYPE_ARG6) || \
+ !defined(RECVFROM_TYPE_RETV)
+ /* */
+ Error Missing_definition_of_return_and_arguments_types_of_recvfrom
+ /* */
+#else
+#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \
+ (RECVFROM_TYPE_ARG2 *)(b), \
+ (RECVFROM_TYPE_ARG3) (bl), \
+ (RECVFROM_TYPE_ARG4) (0), \
+ (RECVFROM_TYPE_ARG5 *)(f), \
+ (RECVFROM_TYPE_ARG6 *)(fl))
+#endif
+#else /* HAVE_RECVFROM */
+#ifndef sreadfrom
+ /* */
+ Error Missing_definition_of_macro_sreadfrom
+ /* */
+#endif
+#endif /* HAVE_RECVFROM */
+
+
+#ifdef RECVFROM_TYPE_ARG6_IS_VOID
+# define RECVFROM_ARG6_T int
+#else
+# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6
+#endif
+#endif /* if 0 */
+
+
+/*
+ * Function-like macro definition used to close a socket.
+ */
+
+#if defined(HAVE_CLOSESOCKET)
+# define sclose(x) closesocket((x))
+#elif defined(HAVE_CLOSESOCKET_CAMEL)
+# define sclose(x) CloseSocket((x))
+#elif defined(HAVE_CLOSE_S)
+# define sclose(x) close_s((x))
+#elif defined(USE_LWIPSOCK)
+# define sclose(x) lwip_close((x))
+#else
+# define sclose(x) close((x))
+#endif
+
+/*
+ * Stack-independent version of fcntl() on sockets:
+ */
+#if defined(USE_LWIPSOCK)
+# define sfcntl lwip_fcntl
+#else
+# define sfcntl fcntl
+#endif
+
+/*
+ * Uppercase macro versions of ANSI/ISO is*() functions/macros which
+ * avoid negative number inputs with argument byte codes > 127.
+ */
+
+#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (islower((int) ((unsigned char)x)))
+#define ISASCII(x) (isascii((int) ((unsigned char)x)))
+
+#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
+ (((unsigned char)x) == '\t'))
+
+#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
+
+
+/*
+ * 'bool' stuff compatible with HP-UX headers.
+ */
+
+#if defined(__hpux) && !defined(HAVE_BOOL_T)
+ typedef int bool;
+# define false 0
+# define true 1
+# define HAVE_BOOL_T
+#endif
+
+
+/*
+ * 'bool' exists on platforms with <stdbool.h>, i.e. C99 platforms.
+ * On non-C99 platforms there's no bool, so define an enum for that.
+ * On C99 platforms 'false' and 'true' also exist. Enum uses a
+ * global namespace though, so use bool_false and bool_true.
+ */
+
+#ifndef HAVE_BOOL_T
+ typedef enum {
+ bool_false = 0,
+ bool_true = 1
+ } bool;
+
+/*
+ * Use a define to let 'true' and 'false' use those enums. There
+ * are currently no use of true and false in libcurl proper, but
+ * there are some in the examples. This will cater for any later
+ * code happening to use true and false.
+ */
+# define false bool_false
+# define true bool_true
+# define HAVE_BOOL_T
+#endif
+
+
+/*
+ * Redefine TRUE and FALSE too, to catch current use. With this
+ * change, 'bool found = 1' will give a warning on MIPSPro, but
+ * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro,
+ * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too.
+ */
+
+#ifndef TRUE
+#define TRUE true
+#endif
+#ifndef FALSE
+#define FALSE false
+#endif
+
+
+/*
+ * Macro WHILE_FALSE may be used to build single-iteration do-while loops,
+ * avoiding compiler warnings. Mostly intended for other macro definitions.
+ */
+
+#define WHILE_FALSE while(0)
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# undef WHILE_FALSE
+# if (_MSC_VER < 1500)
+# define WHILE_FALSE while(1, 0)
+# else
+# define WHILE_FALSE \
+__pragma(warning(push)) \
+__pragma(warning(disable:4127)) \
+while(0) \
+__pragma(warning(pop))
+# endif
+#endif
+
+
+/*
+ * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
+ */
+
+#ifndef HAVE_SIG_ATOMIC_T
+typedef int sig_atomic_t;
+#define HAVE_SIG_ATOMIC_T
+#endif
+
+
+/*
+ * Convenience SIG_ATOMIC_T definition
+ */
+
+#ifdef HAVE_SIG_ATOMIC_T_VOLATILE
+#define SIG_ATOMIC_T static sig_atomic_t
+#else
+#define SIG_ATOMIC_T static volatile sig_atomic_t
+#endif
+
+
+/*
+ * Default return type for signal handlers.
+ */
+
+#ifndef RETSIGTYPE
+#define RETSIGTYPE void
+#endif
+
+
+/*
+ * Macro used to include code only in debug builds.
+ */
+
+#ifdef DEBUGBUILD
+#define DEBUGF(x) x
+#else
+#define DEBUGF(x) do { } WHILE_FALSE
+#endif
+
+
+/*
+ * Macro used to include assertion code only in debug builds.
+ */
+
+#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
+#define DEBUGASSERT(x) assert(x)
+#else
+#define DEBUGASSERT(x) do { } WHILE_FALSE
+#endif
+
+
+/*
+ * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno
+ * (or equivalent) on this platform to hide platform details to code using it.
+ */
+
+#ifdef USE_WINSOCK
+#define SOCKERRNO ((int)WSAGetLastError())
+#define SET_SOCKERRNO(x) (WSASetLastError((int)(x)))
+#else
+#define SOCKERRNO (errno)
+#define SET_SOCKERRNO(x) (errno = (x))
+#endif
+
+
+/*
+ * Macro ERRNO / SET_ERRNO() returns / sets the NOT *socket-related* errno
+ * (or equivalent) on this platform to hide platform details to code using it.
+ */
+
+#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#define ERRNO ((int)GetLastError())
+#define SET_ERRNO(x) (SetLastError((DWORD)(x)))
+#else
+#define ERRNO (errno)
+#define SET_ERRNO(x) (errno = (x))
+#endif
+
+
+/*
+ * Portable error number symbolic names defined to Winsock error codes.
+ */
+
+#ifdef USE_WINSOCK
+#undef EBADF /* override definition in errno.h */
+#define EBADF WSAEBADF
+#undef EINTR /* override definition in errno.h */
+#define EINTR WSAEINTR
+#undef EINVAL /* override definition in errno.h */
+#define EINVAL WSAEINVAL
+#undef EWOULDBLOCK /* override definition in errno.h */
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef EINPROGRESS /* override definition in errno.h */
+#define EINPROGRESS WSAEINPROGRESS
+#undef EALREADY /* override definition in errno.h */
+#define EALREADY WSAEALREADY
+#undef ENOTSOCK /* override definition in errno.h */
+#define ENOTSOCK WSAENOTSOCK
+#undef EDESTADDRREQ /* override definition in errno.h */
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#undef EMSGSIZE /* override definition in errno.h */
+#define EMSGSIZE WSAEMSGSIZE
+#undef EPROTOTYPE /* override definition in errno.h */
+#define EPROTOTYPE WSAEPROTOTYPE
+#undef ENOPROTOOPT /* override definition in errno.h */
+#define ENOPROTOOPT WSAENOPROTOOPT
+#undef EPROTONOSUPPORT /* override definition in errno.h */
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#undef EOPNOTSUPP /* override definition in errno.h */
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#undef EAFNOSUPPORT /* override definition in errno.h */
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#undef EADDRINUSE /* override definition in errno.h */
+#define EADDRINUSE WSAEADDRINUSE
+#undef EADDRNOTAVAIL /* override definition in errno.h */
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#undef ENETDOWN /* override definition in errno.h */
+#define ENETDOWN WSAENETDOWN
+#undef ENETUNREACH /* override definition in errno.h */
+#define ENETUNREACH WSAENETUNREACH
+#undef ENETRESET /* override definition in errno.h */
+#define ENETRESET WSAENETRESET
+#undef ECONNABORTED /* override definition in errno.h */
+#define ECONNABORTED WSAECONNABORTED
+#undef ECONNRESET /* override definition in errno.h */
+#define ECONNRESET WSAECONNRESET
+#undef ENOBUFS /* override definition in errno.h */
+#define ENOBUFS WSAENOBUFS
+#undef EISCONN /* override definition in errno.h */
+#define EISCONN WSAEISCONN
+#undef ENOTCONN /* override definition in errno.h */
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#undef ETIMEDOUT /* override definition in errno.h */
+#define ETIMEDOUT WSAETIMEDOUT
+#undef ECONNREFUSED /* override definition in errno.h */
+#define ECONNREFUSED WSAECONNREFUSED
+#undef ELOOP /* override definition in errno.h */
+#define ELOOP WSAELOOP
+#ifndef ENAMETOOLONG /* possible previous definition in errno.h */
+#define ENAMETOOLONG WSAENAMETOOLONG
+#endif
+#define EHOSTDOWN WSAEHOSTDOWN
+#undef EHOSTUNREACH /* override definition in errno.h */
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#ifndef ENOTEMPTY /* possible previous definition in errno.h */
+#define ENOTEMPTY WSAENOTEMPTY
+#endif
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+#endif
+
+/*
+ * Macro argv_item_t hides platform details to code using it.
+ */
+
+#ifdef __VMS
+#define argv_item_t __char_ptr32
+#else
+#define argv_item_t char *
+#endif
+
+
+/*
+ * We use this ZERO_NULL to avoid picky compiler warnings,
+ * when assigning a NULL pointer to a function pointer var.
+ */
+
+#define ZERO_NULL 0
+
+
+#endif /* HEADER_CURL_SETUP_ONCE_H */
+
diff --git a/libcurl/src/lib/curl_sspi.c b/libcurl/src/lib/curl_sspi.c
new file mode 100644
index 0000000..6a58437
--- /dev/null
+++ b/libcurl/src/lib/curl_sspi.c
@@ -0,0 +1,252 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_WINDOWS_SSPI
+
+#include <curl/curl.h>
+#include "curl_sspi.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* We use our own typedef here since some headers might lack these */
+typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID);
+
+/* See definition of SECURITY_ENTRYPOINT in sspi.h */
+#ifdef UNICODE
+# ifdef _WIN32_WCE
+# define SECURITYENTRYPOINT L"InitSecurityInterfaceW"
+# else
+# define SECURITYENTRYPOINT "InitSecurityInterfaceW"
+# endif
+#else
+# define SECURITYENTRYPOINT "InitSecurityInterfaceA"
+#endif
+
+/* Handle of security.dll or secur32.dll, depending on Windows version */
+HMODULE s_hSecDll = NULL;
+
+/* Pointer to SSPI dispatch table */
+PSecurityFunctionTable s_pSecFn = NULL;
+
+/*
+ * Curl_sspi_global_init()
+ *
+ * This is used to load the Security Service Provider Interface (SSPI)
+ * dynamic link library portably across all Windows versions, without
+ * the need to directly link libcurl, nor the application using it, at
+ * build time.
+ *
+ * Once this function has been executed, Windows SSPI functions can be
+ * called through the Security Service Provider Interface dispatch table.
+ */
+CURL_STATIC CURLcode Curl_sspi_global_init(void)
+{
+ bool securityDll = FALSE;
+ INITSECURITYINTERFACE_FN pInitSecurityInterface;
+
+ /* If security interface is not yet initialized try to do this */
+ if(!s_hSecDll) {
+ /* Security Service Provider Interface (SSPI) functions are located in
+ * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
+ * have both these DLLs (security.dll forwards calls to secur32.dll) */
+ DWORD majorVersion = 4;
+ DWORD platformId = VER_PLATFORM_WIN32_NT;
+
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
+ (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
+ OSVERSIONINFO osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+
+ /* Find out Windows version */
+ if(!GetVersionEx(&osver))
+ return CURLE_FAILED_INIT;
+
+ /* Verify the major version number == 4 and platform id == WIN_NT */
+ if(osver.dwMajorVersion == majorVersion &&
+ osver.dwPlatformId == platformId)
+ securityDll = TRUE;
+#else
+ ULONGLONG majorVersionMask;
+ ULONGLONG platformIdMask;
+ OSVERSIONINFOEX osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ osver.dwMajorVersion = majorVersion;
+ osver.dwPlatformId = platformId;
+ majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
+ platformIdMask = VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL);
+
+ /* Verify the major version number == 4 and platform id == WIN_NT */
+ if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask) &&
+ VerifyVersionInfo(&osver, VER_PLATFORMID, platformIdMask))
+ securityDll = TRUE;
+#endif
+
+ /* Load SSPI dll into the address space of the calling process */
+ if(securityDll)
+ s_hSecDll = LoadLibrary(TEXT("security.dll"));
+ else
+ s_hSecDll = LoadLibrary(TEXT("secur32.dll"));
+ if(!s_hSecDll)
+ return CURLE_FAILED_INIT;
+
+ /* Get address of the InitSecurityInterfaceA function from the SSPI dll */
+ pInitSecurityInterface = (INITSECURITYINTERFACE_FN)
+ GetProcAddress(s_hSecDll, SECURITYENTRYPOINT);
+ if(!pInitSecurityInterface)
+ return CURLE_FAILED_INIT;
+
+ /* Get pointer to Security Service Provider Interface dispatch table */
+ s_pSecFn = pInitSecurityInterface();
+ if(!s_pSecFn)
+ return CURLE_FAILED_INIT;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sspi_global_cleanup()
+ *
+ * This deinitializes the Security Service Provider Interface from libcurl.
+ */
+
+CURL_STATIC void Curl_sspi_global_cleanup(void)
+{
+ if(s_hSecDll) {
+ FreeLibrary(s_hSecDll);
+ s_hSecDll = NULL;
+ s_pSecFn = NULL;
+ }
+}
+
+/*
+ * Curl_create_sspi_identity()
+ *
+ * This is used to populate a SSPI identity structure based on the supplied
+ * username and password.
+ *
+ * Parameters:
+ *
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * identity [in/out] - The identity structure.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
+ SEC_WINNT_AUTH_IDENTITY *identity)
+{
+ xcharp_u useranddomain;
+ xcharp_u user, dup_user;
+ xcharp_u domain, dup_domain;
+ xcharp_u passwd, dup_passwd;
+ size_t domlen = 0;
+
+ domain.const_tchar_ptr = TEXT("");
+
+ /* Initialize the identity */
+ memset(identity, 0, sizeof(*identity));
+
+ useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp);
+ if(!useranddomain.tchar_ptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\'));
+ if(!user.const_tchar_ptr)
+ user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/'));
+
+ if(user.tchar_ptr) {
+ domain.tchar_ptr = useranddomain.tchar_ptr;
+ domlen = user.tchar_ptr - useranddomain.tchar_ptr;
+ user.tchar_ptr++;
+ }
+ else {
+ user.tchar_ptr = useranddomain.tchar_ptr;
+ domain.const_tchar_ptr = TEXT("");
+ domlen = 0;
+ }
+
+ /* Setup the identity's user and length */
+ dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
+ if(!dup_user.tchar_ptr) {
+ Curl_unicodefree(useranddomain.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ identity->User = dup_user.tbyte_ptr;
+ identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr));
+ dup_user.tchar_ptr = NULL;
+
+ /* Setup the identity's domain and length */
+ dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
+ if(!dup_domain.tchar_ptr) {
+ Curl_unicodefree(useranddomain.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
+ *(dup_domain.tchar_ptr + domlen) = TEXT('\0');
+ identity->Domain = dup_domain.tbyte_ptr;
+ identity->DomainLength = curlx_uztoul(domlen);
+ dup_domain.tchar_ptr = NULL;
+
+ Curl_unicodefree(useranddomain.tchar_ptr);
+
+ /* Setup ntlm identity's password and length */
+ passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp);
+ if(!passwd.tchar_ptr)
+ return CURLE_OUT_OF_MEMORY;
+ dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
+ if(!dup_passwd.tchar_ptr) {
+ Curl_unicodefree(passwd.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ identity->Password = dup_passwd.tbyte_ptr;
+ identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
+ dup_passwd.tchar_ptr = NULL;
+
+ Curl_unicodefree(passwd.tchar_ptr);
+
+ /* Setup the identity's flags */
+ identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
+{
+ if(identity) {
+ Curl_safefree(identity->User);
+ Curl_safefree(identity->Password);
+ Curl_safefree(identity->Domain);
+ }
+}
+
+#endif /* USE_WINDOWS_SSPI */
diff --git a/libcurl/src/lib/curl_sspi.h b/libcurl/src/lib/curl_sspi.h
new file mode 100644
index 0000000..b4cd05f
--- /dev/null
+++ b/libcurl/src/lib/curl_sspi.h
@@ -0,0 +1,342 @@
+#ifndef HEADER_CURL_SSPI_H
+#define HEADER_CURL_SSPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_WINDOWS_SSPI
+
+#include <curl/curl.h>
+
+/*
+ * When including the following three headers, it is mandatory to define either
+ * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code.
+ */
+
+#undef SECURITY_WIN32
+#undef SECURITY_KERNEL
+#define SECURITY_WIN32 1
+#include <security.h>
+#include <sspi.h>
+#include <rpc.h>
+
+CURL_STATIC CURLcode Curl_sspi_global_init(void);
+CURL_STATIC void Curl_sspi_global_cleanup(void);
+
+/* This is used to generate an SSPI identity structure */
+CURL_STATIC CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
+ SEC_WINNT_AUTH_IDENTITY *identity);
+
+/* This is used to free an SSPI identity structure */
+CURL_STATIC void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity);
+
+/* Forward-declaration of global variables defined in curl_sspi.c */
+extern HMODULE s_hSecDll;
+extern PSecurityFunctionTable s_pSecFn;
+
+/* Provide some definitions missing in old headers */
+#define SP_NAME_DIGEST "WDigest"
+#define SP_NAME_NTLM "NTLM"
+#define SP_NAME_NEGOTIATE "Negotiate"
+#define SP_NAME_KERBEROS "Kerberos"
+
+#ifndef ISC_REQ_USE_HTTP_STYLE
+#define ISC_REQ_USE_HTTP_STYLE 0x01000000
+#endif
+
+#ifndef ISC_RET_REPLAY_DETECT
+#define ISC_RET_REPLAY_DETECT 0x00000004
+#endif
+
+#ifndef ISC_RET_SEQUENCE_DETECT
+#define ISC_RET_SEQUENCE_DETECT 0x00000008
+#endif
+
+#ifndef ISC_RET_CONFIDENTIALITY
+#define ISC_RET_CONFIDENTIALITY 0x00000010
+#endif
+
+#ifndef ISC_RET_ALLOCATED_MEMORY
+#define ISC_RET_ALLOCATED_MEMORY 0x00000100
+#endif
+
+#ifndef ISC_RET_STREAM
+#define ISC_RET_STREAM 0x00008000
+#endif
+
+#ifndef SEC_E_INSUFFICIENT_MEMORY
+# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L)
+#endif
+#ifndef SEC_E_INVALID_HANDLE
+# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L)
+#endif
+#ifndef SEC_E_UNSUPPORTED_FUNCTION
+# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L)
+#endif
+#ifndef SEC_E_TARGET_UNKNOWN
+# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L)
+#endif
+#ifndef SEC_E_INTERNAL_ERROR
+# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L)
+#endif
+#ifndef SEC_E_SECPKG_NOT_FOUND
+# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L)
+#endif
+#ifndef SEC_E_NOT_OWNER
+# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L)
+#endif
+#ifndef SEC_E_CANNOT_INSTALL
+# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L)
+#endif
+#ifndef SEC_E_INVALID_TOKEN
+# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L)
+#endif
+#ifndef SEC_E_CANNOT_PACK
+# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L)
+#endif
+#ifndef SEC_E_QOP_NOT_SUPPORTED
+# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL)
+#endif
+#ifndef SEC_E_NO_IMPERSONATION
+# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL)
+#endif
+#ifndef SEC_E_LOGON_DENIED
+# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL)
+#endif
+#ifndef SEC_E_UNKNOWN_CREDENTIALS
+# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL)
+#endif
+#ifndef SEC_E_NO_CREDENTIALS
+# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL)
+#endif
+#ifndef SEC_E_MESSAGE_ALTERED
+# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL)
+#endif
+#ifndef SEC_E_OUT_OF_SEQUENCE
+# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L)
+#endif
+#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY
+# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L)
+#endif
+#ifndef SEC_E_BAD_PKGID
+# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L)
+#endif
+#ifndef SEC_E_CONTEXT_EXPIRED
+# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L)
+#endif
+#ifndef SEC_E_INCOMPLETE_MESSAGE
+# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L)
+#endif
+#ifndef SEC_E_INCOMPLETE_CREDENTIALS
+# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L)
+#endif
+#ifndef SEC_E_BUFFER_TOO_SMALL
+# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L)
+#endif
+#ifndef SEC_E_WRONG_PRINCIPAL
+# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L)
+#endif
+#ifndef SEC_E_TIME_SKEW
+# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L)
+#endif
+#ifndef SEC_E_UNTRUSTED_ROOT
+# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L)
+#endif
+#ifndef SEC_E_ILLEGAL_MESSAGE
+# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L)
+#endif
+#ifndef SEC_E_CERT_UNKNOWN
+# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L)
+#endif
+#ifndef SEC_E_CERT_EXPIRED
+# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L)
+#endif
+#ifndef SEC_E_ENCRYPT_FAILURE
+# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L)
+#endif
+#ifndef SEC_E_DECRYPT_FAILURE
+# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L)
+#endif
+#ifndef SEC_E_ALGORITHM_MISMATCH
+# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L)
+#endif
+#ifndef SEC_E_SECURITY_QOS_FAILED
+# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L)
+#endif
+#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED
+# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L)
+#endif
+#ifndef SEC_E_NO_TGT_REPLY
+# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L)
+#endif
+#ifndef SEC_E_NO_IP_ADDRESSES
+# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L)
+#endif
+#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE
+# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L)
+#endif
+#ifndef SEC_E_CRYPTO_SYSTEM_INVALID
+# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L)
+#endif
+#ifndef SEC_E_MAX_REFERRALS_EXCEEDED
+# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L)
+#endif
+#ifndef SEC_E_MUST_BE_KDC
+# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L)
+#endif
+#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED
+# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL)
+#endif
+#ifndef SEC_E_TOO_MANY_PRINCIPALS
+# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL)
+#endif
+#ifndef SEC_E_NO_PA_DATA
+# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL)
+#endif
+#ifndef SEC_E_PKINIT_NAME_MISMATCH
+# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL)
+#endif
+#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED
+# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL)
+#endif
+#ifndef SEC_E_SHUTDOWN_IN_PROGRESS
+# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL)
+#endif
+#ifndef SEC_E_KDC_INVALID_REQUEST
+# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L)
+#endif
+#ifndef SEC_E_KDC_UNABLE_TO_REFER
+# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L)
+#endif
+#ifndef SEC_E_KDC_UNKNOWN_ETYPE
+# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L)
+#endif
+#ifndef SEC_E_UNSUPPORTED_PREAUTH
+# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L)
+#endif
+#ifndef SEC_E_DELEGATION_REQUIRED
+# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L)
+#endif
+#ifndef SEC_E_BAD_BINDINGS
+# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L)
+#endif
+#ifndef SEC_E_MULTIPLE_ACCOUNTS
+# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L)
+#endif
+#ifndef SEC_E_NO_KERB_KEY
+# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L)
+#endif
+#ifndef SEC_E_CERT_WRONG_USAGE
+# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L)
+#endif
+#ifndef SEC_E_DOWNGRADE_DETECTED
+# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L)
+#endif
+#ifndef SEC_E_SMARTCARD_CERT_REVOKED
+# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L)
+#endif
+#ifndef SEC_E_ISSUING_CA_UNTRUSTED
+# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L)
+#endif
+#ifndef SEC_E_REVOCATION_OFFLINE_C
+# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L)
+#endif
+#ifndef SEC_E_PKINIT_CLIENT_FAILURE
+# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L)
+#endif
+#ifndef SEC_E_SMARTCARD_CERT_EXPIRED
+# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L)
+#endif
+#ifndef SEC_E_NO_S4U_PROT_SUPPORT
+# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L)
+#endif
+#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE
+# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L)
+#endif
+#ifndef SEC_E_REVOCATION_OFFLINE_KDC
+# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L)
+#endif
+#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC
+# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L)
+#endif
+#ifndef SEC_E_KDC_CERT_EXPIRED
+# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL)
+#endif
+#ifndef SEC_E_KDC_CERT_REVOKED
+# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL)
+#endif
+#ifndef SEC_E_INVALID_PARAMETER
+# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL)
+#endif
+#ifndef SEC_E_DELEGATION_POLICY
+# define SEC_E_DELEGATION_POLICY ((HRESULT)0x8009035EL)
+#endif
+#ifndef SEC_E_POLICY_NLTM_ONLY
+# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL)
+#endif
+
+#ifndef SEC_I_CONTINUE_NEEDED
+# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L)
+#endif
+#ifndef SEC_I_COMPLETE_NEEDED
+# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L)
+#endif
+#ifndef SEC_I_COMPLETE_AND_CONTINUE
+# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L)
+#endif
+#ifndef SEC_I_LOCAL_LOGON
+# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L)
+#endif
+#ifndef SEC_I_CONTEXT_EXPIRED
+# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L)
+#endif
+#ifndef SEC_I_INCOMPLETE_CREDENTIALS
+# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L)
+#endif
+#ifndef SEC_I_RENEGOTIATE
+# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L)
+#endif
+#ifndef SEC_I_NO_LSA_CONTEXT
+# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L)
+#endif
+#ifndef SEC_I_SIGNATURE_NEEDED
+# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
+#endif
+
+#ifdef UNICODE
+# define SECFLAG_WINNT_AUTH_IDENTITY \
+ (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE
+#else
+# define SECFLAG_WINNT_AUTH_IDENTITY \
+ (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI
+#endif
+
+/*
+ * Definitions required from ntsecapi.h are directly provided below this point
+ * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h
+ */
+#define KERB_WRAP_NO_ENCRYPT 0x80000001
+
+#endif /* USE_WINDOWS_SSPI */
+
+#endif /* HEADER_CURL_SSPI_H */
diff --git a/libcurl/src/lib/curl_threads.c b/libcurl/src/lib/curl_threads.c
new file mode 100644
index 0000000..42556bd
--- /dev/null
+++ b/libcurl/src/lib/curl_threads.c
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_THREADS_POSIX)
+# ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+# endif
+#elif defined(USE_THREADS_WIN32)
+# ifdef HAVE_PROCESS_H
+# include <process.h>
+# endif
+#endif
+
+#include "curl_threads.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if defined(USE_THREADS_POSIX)
+
+struct curl_actual_call {
+ unsigned int (*func)(void *);
+ void *arg;
+};
+
+static void *curl_thread_create_thunk(void *arg)
+{
+ struct curl_actual_call * ac = arg;
+ unsigned int (*func)(void *) = ac->func;
+ void *real_arg = ac->arg;
+
+ free(ac);
+
+ (*func)(real_arg);
+
+ return 0;
+}
+
+CURL_STATIC curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
+{
+ curl_thread_t t = malloc(sizeof(pthread_t));
+ struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
+ if(!(ac && t))
+ goto err;
+
+ ac->func = func;
+ ac->arg = arg;
+
+ if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0)
+ goto err;
+
+ return t;
+
+err:
+ free(t);
+ free(ac);
+ return curl_thread_t_null;
+}
+
+CURL_STATIC void Curl_thread_destroy(curl_thread_t hnd)
+{
+ if(hnd != curl_thread_t_null) {
+ pthread_detach(*hnd);
+ free(hnd);
+ }
+}
+
+CURL_STATIC int Curl_thread_join(curl_thread_t *hnd)
+{
+ int ret = (pthread_join(**hnd, NULL) == 0);
+
+ free(*hnd);
+ *hnd = curl_thread_t_null;
+
+ return ret;
+}
+
+#elif defined(USE_THREADS_WIN32)
+
+CURL_STATIC curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+ void *arg)
+{
+#ifdef _WIN32_WCE
+ return CreateThread(NULL, 0, func, arg, 0, NULL);
+#else
+ curl_thread_t t;
+ t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
+ if((t == 0) || (t == (curl_thread_t)-1L))
+ return curl_thread_t_null;
+ return t;
+#endif
+}
+
+CURL_STATIC void Curl_thread_destroy(curl_thread_t hnd)
+{
+ CloseHandle(hnd);
+}
+
+CURL_STATIC int Curl_thread_join(curl_thread_t *hnd)
+{
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+ int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
+#else
+ int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0);
+#endif
+
+ Curl_thread_destroy(*hnd);
+
+ *hnd = curl_thread_t_null;
+
+ return ret;
+}
+
+#endif /* USE_THREADS_* */
diff --git a/libcurl/src/lib/curl_threads.h b/libcurl/src/lib/curl_threads.h
new file mode 100644
index 0000000..20bbcdb
--- /dev/null
+++ b/libcurl/src/lib/curl_threads.h
@@ -0,0 +1,62 @@
+#ifndef HEADER_CURL_THREADS_H
+#define HEADER_CURL_THREADS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(USE_THREADS_POSIX)
+# define CURL_STDCALL
+# define curl_mutex_t pthread_mutex_t
+# define curl_thread_t pthread_t *
+# define curl_thread_t_null (pthread_t *)0
+# define Curl_mutex_init(m) pthread_mutex_init(m, NULL)
+# define Curl_mutex_acquire(m) pthread_mutex_lock(m)
+# define Curl_mutex_release(m) pthread_mutex_unlock(m)
+# define Curl_mutex_destroy(m) pthread_mutex_destroy(m)
+#elif defined(USE_THREADS_WIN32)
+# define CURL_STDCALL __stdcall
+# define curl_mutex_t CRITICAL_SECTION
+# define curl_thread_t HANDLE
+# define curl_thread_t_null (HANDLE)0
+# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+# define Curl_mutex_init(m) InitializeCriticalSection(m)
+# else
+# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
+# endif
+# define Curl_mutex_acquire(m) EnterCriticalSection(m)
+# define Curl_mutex_release(m) LeaveCriticalSection(m)
+# define Curl_mutex_destroy(m) DeleteCriticalSection(m)
+#endif
+
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+
+CURL_STATIC curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+ void *arg);
+
+CURL_STATIC void Curl_thread_destroy(curl_thread_t hnd);
+
+CURL_STATIC int Curl_thread_join(curl_thread_t *hnd);
+
+#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
+
+#endif /* HEADER_CURL_THREADS_H */
diff --git a/libcurl/src/lib/curlx.h b/libcurl/src/lib/curlx.h
new file mode 100644
index 0000000..979e7d7
--- /dev/null
+++ b/libcurl/src/lib/curlx.h
@@ -0,0 +1,118 @@
+#ifndef HEADER_CURL_CURLX_H
+#define HEADER_CURL_CURLX_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Defines protos and includes all header files that provide the curlx_*
+ * functions. The curlx_* functions are not part of the libcurl API, but are
+ * stand-alone functions whose sources can be built and linked by apps if need
+ * be.
+ */
+
+#include <curl/mprintf.h>
+/* this is still a public header file that provides the curl_mprintf()
+ functions while they still are offered publicly. They will be made library-
+ private one day */
+
+#include "strequal.h"
+/* "strequal.h" provides the strequal protos */
+
+#include "strtoofft.h"
+/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a
+ curl_off_t number from a given string.
+*/
+
+#include "timeval.h"
+/*
+ "timeval.h" sets up a 'struct timeval' even for platforms that otherwise
+ don't have one and has protos for these functions:
+
+ curlx_tvnow()
+ curlx_tvdiff()
+ curlx_tvdiff_secs()
+*/
+
+#include "nonblock.h"
+/* "nonblock.h" provides curlx_nonblock() */
+
+#include "warnless.h"
+/* "warnless.h" provides functions:
+
+ curlx_ultous()
+ curlx_ultouc()
+ curlx_uztosi()
+*/
+
+/* Now setup curlx_ * names for the functions that are to become curlx_ and
+ be removed from a future libcurl official API:
+ curlx_getenv
+ curlx_mprintf (and its variations)
+ curlx_strequal
+ curlx_strnequal
+
+*/
+
+#define curlx_getenv curl_getenv
+#define curlx_strequal curl_strequal
+#define curlx_strnequal curl_strnequal
+#define curlx_raw_equal Curl_raw_equal
+#define curlx_mvsnprintf curl_mvsnprintf
+#define curlx_msnprintf curl_msnprintf
+#define curlx_maprintf curl_maprintf
+#define curlx_mvaprintf curl_mvaprintf
+#define curlx_msprintf curl_msprintf
+#define curlx_mprintf curl_mprintf
+#define curlx_mfprintf curl_mfprintf
+#define curlx_mvsprintf curl_mvsprintf
+#define curlx_mvprintf curl_mvprintf
+#define curlx_mvfprintf curl_mvfprintf
+
+#ifdef ENABLE_CURLX_PRINTF
+/* If this define is set, we define all "standard" printf() functions to use
+ the curlx_* version instead. It makes the source code transparent and
+ easier to understand/patch. Undefine them first. */
+# undef printf
+# undef fprintf
+# undef sprintf
+# undef snprintf
+# undef vprintf
+# undef vfprintf
+# undef vsprintf
+# undef vsnprintf
+# undef aprintf
+# undef vaprintf
+
+# define printf curlx_mprintf
+# define fprintf curlx_mfprintf
+# define sprintf curlx_msprintf
+# define snprintf curlx_msnprintf
+# define vprintf curlx_mvprintf
+# define vfprintf curlx_mvfprintf
+# define vsprintf curlx_mvsprintf
+# define vsnprintf curlx_mvsnprintf
+# define aprintf curlx_maprintf
+# define vaprintf curlx_mvaprintf
+#endif /* ENABLE_CURLX_PRINTF */
+
+#endif /* HEADER_CURL_CURLX_H */
+
diff --git a/libcurl/src/lib/dict.c b/libcurl/src/lib/dict.c
new file mode 100644
index 0000000..06d7699
--- /dev/null
+++ b/libcurl/src/lib/dict.c
@@ -0,0 +1,279 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_DICT
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+
+#include "progress.h"
+#include "strequal.h"
+#include "dict.h"
+#include "rawstr.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode dict_do(struct connectdata *conn, bool *done);
+
+/*
+ * DICT protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_dict = {
+ "DICT", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ dict_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_DICT, /* defport */
+ CURLPROTO_DICT, /* protocol */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+};
+
+static char *unescape_word(struct SessionHandle *data, const char *inputbuff)
+{
+ char *newp;
+ char *dictp;
+ char *ptr;
+ int len;
+ char ch;
+ int olen=0;
+
+ newp = curl_easy_unescape(data, inputbuff, 0, &len);
+ if(!newp)
+ return NULL;
+
+ dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
+ if(dictp) {
+ /* According to RFC2229 section 2.2, these letters need to be escaped with
+ \[letter] */
+ for(ptr = newp;
+ (ch = *ptr) != 0;
+ ptr++) {
+ if((ch <= 32) || (ch == 127) ||
+ (ch == '\'') || (ch == '\"') || (ch == '\\')) {
+ dictp[olen++] = '\\';
+ }
+ dictp[olen++] = ch;
+ }
+ dictp[olen]=0;
+ }
+ free(newp);
+ return dictp;
+}
+
+static CURLcode dict_do(struct connectdata *conn, bool *done)
+{
+ char *word;
+ char *eword;
+ char *ppath;
+ char *database = NULL;
+ char *strategy = NULL;
+ char *nthdef = NULL; /* This is not part of the protocol, but required
+ by RFC 2229 */
+ CURLcode result=CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+
+ char *path = data->state.path;
+ curl_off_t *bytecount = &data->req.bytecount;
+
+ *done = TRUE; /* unconditionally */
+
+ if(conn->bits.user_passwd) {
+ /* AUTH is missing */
+ }
+
+ if(Curl_raw_nequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
+ Curl_raw_nequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
+ Curl_raw_nequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
+
+ word = strchr(path, ':');
+ if(word) {
+ word++;
+ database = strchr(word, ':');
+ if(database) {
+ *database++ = (char)0;
+ strategy = strchr(database, ':');
+ if(strategy) {
+ *strategy++ = (char)0;
+ nthdef = strchr(strategy, ':');
+ if(nthdef) {
+ *nthdef = (char)0;
+ }
+ }
+ }
+ }
+
+ if((word == NULL) || (*word == (char)0)) {
+ infof(data, "lookup word is missing\n");
+ word=(char *)"default";
+ }
+ if((database == NULL) || (*database == (char)0)) {
+ database = (char *)"!";
+ }
+ if((strategy == NULL) || (*strategy == (char)0)) {
+ strategy = (char *)".";
+ }
+
+ eword = unescape_word(data, word);
+ if(!eword)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_sendf(sockfd, conn,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "MATCH "
+ "%s " /* database */
+ "%s " /* strategy */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+
+ database,
+ strategy,
+ eword
+ );
+
+ free(eword);
+
+ if(result) {
+ failf(data, "Failed sending DICT request");
+ return result;
+ }
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
+ -1, NULL); /* no upload */
+ }
+ else if(Curl_raw_nequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
+ Curl_raw_nequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
+ Curl_raw_nequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
+
+ word = strchr(path, ':');
+ if(word) {
+ word++;
+ database = strchr(word, ':');
+ if(database) {
+ *database++ = (char)0;
+ nthdef = strchr(database, ':');
+ if(nthdef) {
+ *nthdef = (char)0;
+ }
+ }
+ }
+
+ if((word == NULL) || (*word == (char)0)) {
+ infof(data, "lookup word is missing\n");
+ word=(char *)"default";
+ }
+ if((database == NULL) || (*database == (char)0)) {
+ database = (char *)"!";
+ }
+
+ eword = unescape_word(data, word);
+ if(!eword)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_sendf(sockfd, conn,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "DEFINE "
+ "%s " /* database */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+ database,
+ eword);
+
+ free(eword);
+
+ if(result) {
+ failf(data, "Failed sending DICT request");
+ return result;
+ }
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
+ -1, NULL); /* no upload */
+ }
+ else {
+
+ ppath = strchr(path, '/');
+ if(ppath) {
+ int i;
+
+ ppath++;
+ for(i = 0; ppath[i]; i++) {
+ if(ppath[i] == ':')
+ ppath[i] = ' ';
+ }
+ result = Curl_sendf(sockfd, conn,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "%s\r\n"
+ "QUIT\r\n", ppath);
+ if(result) {
+ failf(data, "Failed sending DICT request");
+ return result;
+ }
+
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
+ }
+ }
+
+ return CURLE_OK;
+}
+#endif /*CURL_DISABLE_DICT*/
diff --git a/libcurl/src/lib/dict.h b/libcurl/src/lib/dict.h
new file mode 100644
index 0000000..44fd9d4
--- /dev/null
+++ b/libcurl/src/lib/dict.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_DICT_H
+#define HEADER_CURL_DICT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_DICT
+extern const struct Curl_handler Curl_handler_dict;
+#endif
+
+#endif /* HEADER_CURL_DICT_H */
diff --git a/libcurl/src/lib/dotdot.c b/libcurl/src/lib/dotdot.c
new file mode 100644
index 0000000..418408e
--- /dev/null
+++ b/libcurl/src/lib/dotdot.c
@@ -0,0 +1,170 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "dotdot.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * "Remove Dot Segments"
+ * http://tools.ietf.org/html/rfc3986#section-5.2.4
+ */
+
+/*
+ * Curl_dedotdotify()
+ *
+ * This function gets a zero-terminated path with dot and dotdot sequences
+ * passed in and strips them off according to the rules in RFC 3986 section
+ * 5.2.4.
+ *
+ * The function handles a query part ('?' + stuff) appended but it expects
+ * that fragments ('#' + stuff) have already been cut off.
+ *
+ * RETURNS
+ *
+ * an allocated dedotdotified output string
+ */
+CURL_STATIC char *Curl_dedotdotify(const char *input)
+{
+ size_t inlen = strlen(input);
+ char *clone;
+ size_t clen = inlen; /* the length of the cloned input */
+ char *out = malloc(inlen+1);
+ char *outptr;
+ char *orgclone;
+ char *queryp;
+ if(!out)
+ return NULL; /* out of memory */
+
+ /* get a cloned copy of the input */
+ clone = strdup(input);
+ if(!clone) {
+ free(out);
+ return NULL;
+ }
+ orgclone = clone;
+ outptr = out;
+
+ /*
+ * To handle query-parts properly, we must find it and remove it during the
+ * dotdot-operation and then append it again at the end to the output
+ * string.
+ */
+ queryp = strchr(clone, '?');
+ if(queryp)
+ *queryp = 0;
+
+ do {
+
+ /* A. If the input buffer begins with a prefix of "../" or "./", then
+ remove that prefix from the input buffer; otherwise, */
+
+ if(!strncmp("./", clone, 2)) {
+ clone+=2;
+ clen-=2;
+ }
+ else if(!strncmp("../", clone, 3)) {
+ clone+=3;
+ clen-=3;
+ }
+
+ /* B. if the input buffer begins with a prefix of "/./" or "/.", where
+ "." is a complete path segment, then replace that prefix with "/" in
+ the input buffer; otherwise, */
+ else if(!strncmp("/./", clone, 3)) {
+ clone+=2;
+ clen-=2;
+ }
+ else if(!strcmp("/.", clone)) {
+ clone[1]='/';
+ clone++;
+ clen-=1;
+ }
+
+ /* C. if the input buffer begins with a prefix of "/../" or "/..", where
+ ".." is a complete path segment, then replace that prefix with "/" in
+ the input buffer and remove the last segment and its preceding "/" (if
+ any) from the output buffer; otherwise, */
+
+ else if(!strncmp("/../", clone, 4)) {
+ clone+=3;
+ clen-=3;
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr = 0; /* zero-terminate where it stops */
+ }
+ else if(!strcmp("/..", clone)) {
+ clone[2]='/';
+ clone+=2;
+ clen-=2;
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr = 0; /* zero-terminate where it stops */
+ }
+
+ /* D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise, */
+
+ else if(!strcmp(".", clone) || !strcmp("..", clone)) {
+ *clone=0;
+ }
+
+ else {
+ /* E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if any) and
+ any subsequent characters up to, but not including, the next "/"
+ character or the end of the input buffer. */
+
+ do {
+ *outptr++ = *clone++;
+ clen--;
+ } while(*clone && (*clone != '/'));
+ *outptr = 0;
+ }
+
+ } while(*clone);
+
+ if(queryp) {
+ size_t qlen;
+ /* There was a query part, append that to the output. The 'clone' string
+ may now have been altered so we copy from the original input string
+ from the correct index. */
+ size_t oindex = queryp - orgclone;
+ qlen = strlen(&input[oindex]);
+ memcpy(outptr, &input[oindex], qlen+1); /* include the ending zero byte */
+ }
+
+ free(orgclone);
+ return out;
+}
diff --git a/libcurl/src/lib/dotdot.h b/libcurl/src/lib/dotdot.h
new file mode 100644
index 0000000..e831732
--- /dev/null
+++ b/libcurl/src/lib/dotdot.h
@@ -0,0 +1,25 @@
+#ifndef HEADER_CURL_DOTDOT_H
+#define HEADER_CURL_DOTDOT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+CURL_STATIC char *Curl_dedotdotify(const char *input);
+#endif
diff --git a/libcurl/src/lib/easy.c b/libcurl/src/lib/easy.c
new file mode 100644
index 0000000..9492d3e
--- /dev/null
+++ b/libcurl/src/lib/easy.c
@@ -0,0 +1,1130 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/*
+ * See comment in curl_memory.h for the explanation of this sanity check.
+ */
+
+#ifdef CURLX_NO_MEMORY_CALLBACKS
+#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined"
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "strequal.h"
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "vtls/vtls.h"
+#include "url.h"
+#include "getinfo.h"
+#include "hostip.h"
+#include "share.h"
+#include "strdup.h"
+#include "progress.h"
+#include "easyif.h"
+#include "select.h"
+#include "sendf.h" /* for failf function prototype */
+#include "curl_ntlm.h"
+#include "connect.h" /* for Curl_getconnectinfo */
+#include "slist.h"
+#include "amigaos.h"
+#include "non-ascii.h"
+#include "warnless.h"
+#include "conncache.h"
+#include "multiif.h"
+#include "sigpipe.h"
+#include "ssh.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
+ of win32_init() */
+static void win32_cleanup(void)
+{
+#ifdef USE_WINSOCK
+ WSACleanup();
+#endif
+#ifdef USE_WINDOWS_SSPI
+ Curl_sspi_global_cleanup();
+#endif
+}
+
+/* win32_init() performs win32 socket initialization to properly setup the
+ stack to allow networking */
+static CURLcode win32_init(void)
+{
+#ifdef USE_WINSOCK
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int res;
+
+#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
+ Error IPV6_requires_winsock2
+#endif
+
+ wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
+
+ res = WSAStartup(wVersionRequested, &wsaData);
+
+ if(res != 0)
+ /* Tell the user that we couldn't find a useable */
+ /* winsock.dll. */
+ return CURLE_FAILED_INIT;
+
+ /* Confirm that the Windows Sockets DLL supports what we need.*/
+ /* Note that if the DLL supports versions greater */
+ /* than wVersionRequested, it will still return */
+ /* wVersionRequested in wVersion. wHighVersion contains the */
+ /* highest supported version. */
+
+ if(LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
+ HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
+ /* Tell the user that we couldn't find a useable */
+
+ /* winsock.dll. */
+ WSACleanup();
+ return CURLE_FAILED_INIT;
+ }
+ /* The Windows Sockets DLL is acceptable. Proceed. */
+#elif defined(USE_LWIPSOCK)
+ lwip_init();
+#endif
+
+#ifdef USE_WINDOWS_SSPI
+ {
+ CURLcode result = Curl_sspi_global_init();
+ if(result)
+ return result;
+ }
+#endif
+
+ return CURLE_OK;
+}
+
+#ifdef USE_LIBIDN
+/*
+ * Initialise use of IDNA library.
+ * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
+ * idna_to_ascii_lz().
+ */
+static void idna_init (void)
+{
+#ifdef WIN32
+ char buf[60];
+ UINT cp = GetACP();
+
+ if(!getenv("CHARSET") && cp > 0) {
+ snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
+ putenv(buf);
+ }
+#else
+ /* to do? */
+#endif
+}
+#endif /* USE_LIBIDN */
+
+/* true globals -- for curl_global_init() and curl_global_cleanup() */
+static unsigned int initialized;
+static long init_flags;
+
+///*
+// * strdup (and other memory functions) is redefined in complicated
+// * ways, but at this point it must be defined as the system-supplied strdup
+// * so the callback pointer is initialized correctly.
+// */
+//#if defined(_WIN32_WCE)
+//#define system_strdup _strdup
+//#elif !defined(HAVE_STRDUP)
+//#define system_strdup curlx_strdup
+//#else
+//#define system_strdup strdup
+//#endif
+//
+//#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+//# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
+//#endif
+//
+//#ifndef __SYMBIAN32__
+///*
+// * If a memory-using function (like curl_getenv) is used before
+// * curl_global_init() is called, we need to have these pointers set already.
+// */
+//curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
+//curl_free_callback Curl_cfree = (curl_free_callback)free;
+//curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
+//curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
+//curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
+//#if defined(WIN32) && defined(UNICODE)
+//curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
+//#endif
+//#else
+///*
+// * Symbian OS doesn't support initialization to code in writeable static data.
+// * Initialization will occur in the curl_global_init() call.
+// */
+//curl_malloc_callback Curl_cmalloc;
+//curl_free_callback Curl_cfree;
+//curl_realloc_callback Curl_crealloc;
+//curl_strdup_callback Curl_cstrdup;
+//curl_calloc_callback Curl_ccalloc;
+//#endif
+//
+//#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+//# pragma warning(default:4232) /* MSVC extension, dllimport identity */
+//#endif
+
+/**
+ * curl_global_init() globally initializes cURL given a bitwise set of the
+ * different features of what to initialize.
+ */
+CURLcode curl_global_init(long flags)
+{
+ if(initialized++)
+ return CURLE_OK;
+
+ /* Setup the default memory functions here (again) */
+ Curl_cmalloc = (curl_malloc_callback)malloc;
+ Curl_cfree = (curl_free_callback)free;
+ Curl_crealloc = (curl_realloc_callback)realloc;
+ Curl_cstrdup = (curl_strdup_callback)system_strdup;
+ Curl_ccalloc = (curl_calloc_callback)calloc;
+#if defined(WIN32) && defined(UNICODE)
+ Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
+#endif
+
+ if(flags & CURL_GLOBAL_SSL)
+ if(!Curl_ssl_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+
+ if(flags & CURL_GLOBAL_WIN32)
+ if(win32_init()) {
+ DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+
+#ifdef __AMIGA__
+ if(!Curl_amiga_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+#endif
+
+#ifdef NETWARE
+ if(netware_init()) {
+ DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
+ }
+#endif
+
+#ifdef USE_LIBIDN
+ idna_init();
+#endif
+
+ if(Curl_resolver_global_init()) {
+ DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+
+#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
+ if(libssh2_init(0)) {
+ DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+#endif
+
+ if(flags & CURL_GLOBAL_ACK_EINTR)
+ Curl_ack_eintr = 1;
+
+ init_flags = flags;
+
+ return CURLE_OK;
+}
+
+/*
+ * curl_global_init_mem() globally initializes cURL and also registers the
+ * user provided callback routines.
+ */
+CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
+ curl_free_callback f, curl_realloc_callback r,
+ curl_strdup_callback s, curl_calloc_callback c)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Invalid input, return immediately */
+ if(!m || !f || !r || !s || !c)
+ return CURLE_FAILED_INIT;
+
+ if(initialized) {
+ /* Already initialized, don't do it again, but bump the variable anyway to
+ work like curl_global_init() and require the same amount of cleanup
+ calls. */
+ initialized++;
+ return CURLE_OK;
+ }
+
+ /* Call the actual init function first */
+ result = curl_global_init(flags);
+ if(!result) {
+ Curl_cmalloc = m;
+ Curl_cfree = f;
+ Curl_cstrdup = s;
+ Curl_crealloc = r;
+ Curl_ccalloc = c;
+ }
+
+ return result;
+}
+
+/**
+ * curl_global_cleanup() globally cleanups cURL, uses the value of
+ * "init_flags" to determine what needs to be cleaned up and what doesn't.
+ */
+void curl_global_cleanup(void)
+{
+ if(!initialized)
+ return;
+
+ if(--initialized)
+ return;
+
+ Curl_global_host_cache_dtor();
+
+ if(init_flags & CURL_GLOBAL_SSL)
+ Curl_ssl_cleanup();
+
+ Curl_resolver_global_cleanup();
+
+ if(init_flags & CURL_GLOBAL_WIN32)
+ win32_cleanup();
+
+ Curl_amiga_cleanup();
+
+#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
+ (void)libssh2_exit();
+#endif
+
+ init_flags = 0;
+}
+
+/*
+ * curl_easy_init() is the external interface to alloc, setup and init an
+ * easy handle that is returned. If anything goes wrong, NULL is returned.
+ */
+CURL *curl_easy_init(void)
+{
+ CURLcode result;
+ struct SessionHandle *data;
+
+ /* Make sure we inited the global SSL stuff */
+ if(!initialized) {
+ result = curl_global_init(CURL_GLOBAL_DEFAULT);
+ if(result) {
+ /* something in the global init failed, return nothing */
+ DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
+ return NULL;
+ }
+ }
+
+ /* We use curl_open() with undefined URL so far */
+ result = Curl_open(&data);
+ if(result) {
+ DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
+ return NULL;
+ }
+
+ return data;
+}
+
+/*
+ * curl_easy_setopt() is the external interface for setting options on an
+ * easy handle.
+ */
+
+//#undef curl_easy_setopt
+CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
+{
+ va_list arg;
+ struct SessionHandle *data = curl;
+ CURLcode result;
+
+ if(!curl)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ va_start(arg, tag);
+
+ result = Curl_setopt(data, tag, arg);
+
+ va_end(arg);
+ return result;
+}
+
+#ifdef CURLDEBUG
+
+struct socketmonitor {
+ struct socketmonitor *next; /* the next node in the list or NULL */
+ struct pollfd socket; /* socket info of what to monitor */
+};
+
+struct events {
+ long ms; /* timeout, run the timeout function when reached */
+ bool msbump; /* set TRUE when timeout is set by callback */
+ int num_sockets; /* number of nodes in the monitor list */
+ struct socketmonitor *list; /* list of sockets to monitor */
+ int running_handles; /* store the returned number */
+};
+
+/* events_timer
+ *
+ * Callback that gets called with a new value when the timeout should be
+ * updated.
+ */
+
+static int events_timer(CURLM *multi, /* multi handle */
+ long timeout_ms, /* see above */
+ void *userp) /* private callback pointer */
+{
+ struct events *ev = userp;
+ (void)multi;
+ if(timeout_ms == -1)
+ /* timeout removed */
+ timeout_ms = 0;
+ else if(timeout_ms == 0)
+ /* timeout is already reached! */
+ timeout_ms = 1; /* trigger asap */
+
+ ev->ms = timeout_ms;
+ ev->msbump = TRUE;
+ return 0;
+}
+
+
+/* poll2cselect
+ *
+ * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
+ */
+static int poll2cselect(int pollmask)
+{
+ int omask=0;
+ if(pollmask & POLLIN)
+ omask |= CURL_CSELECT_IN;
+ if(pollmask & POLLOUT)
+ omask |= CURL_CSELECT_OUT;
+ if(pollmask & POLLERR)
+ omask |= CURL_CSELECT_ERR;
+ return omask;
+}
+
+
+/* socketcb2poll
+ *
+ * convert from libcurl' CURL_POLL_* bit definitions to poll()'s
+ */
+static short socketcb2poll(int pollmask)
+{
+ short omask=0;
+ if(pollmask & CURL_POLL_IN)
+ omask |= POLLIN;
+ if(pollmask & CURL_POLL_OUT)
+ omask |= POLLOUT;
+ return omask;
+}
+
+/* events_socket
+ *
+ * Callback that gets called with information about socket activity to
+ * monitor.
+ */
+static int events_socket(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int what, /* see above */
+ void *userp, /* private callback
+ pointer */
+ void *socketp) /* private socket
+ pointer */
+{
+ struct events *ev = userp;
+ struct socketmonitor *m;
+ struct socketmonitor *prev=NULL;
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) easy;
+#endif
+ (void)socketp;
+
+ m = ev->list;
+ while(m) {
+ if(m->socket.fd == s) {
+
+ if(what == CURL_POLL_REMOVE) {
+ struct socketmonitor *nxt = m->next;
+ /* remove this node from the list of monitored sockets */
+ if(prev)
+ prev->next = nxt;
+ else
+ ev->list = nxt;
+ free(m);
+ m = nxt;
+ infof(easy, "socket cb: socket %d REMOVED\n", s);
+ }
+ else {
+ /* The socket 's' is already being monitored, update the activity
+ mask. Convert from libcurl bitmask to the poll one. */
+ m->socket.events = socketcb2poll(what);
+ infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
+ what&CURL_POLL_IN?"IN":"",
+ what&CURL_POLL_OUT?"OUT":"");
+ }
+ break;
+ }
+ prev = m;
+ m = m->next; /* move to next node */
+ }
+ if(!m) {
+ if(what == CURL_POLL_REMOVE) {
+ /* this happens a bit too often, libcurl fix perhaps? */
+ /* fprintf(stderr,
+ "%s: socket %d asked to be REMOVED but not present!\n",
+ __func__, s); */
+ }
+ else {
+ m = malloc(sizeof(struct socketmonitor));
+ m->next = ev->list;
+ m->socket.fd = s;
+ m->socket.events = socketcb2poll(what);
+ m->socket.revents = 0;
+ ev->list = m;
+ infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
+ what&CURL_POLL_IN?"IN":"",
+ what&CURL_POLL_OUT?"OUT":"");
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * events_setup()
+ *
+ * Do the multi handle setups that only event-based transfers need.
+ */
+static void events_setup(CURLM *multi, struct events *ev)
+{
+ /* timer callback */
+ curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
+ curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
+
+ /* socket callback */
+ curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
+ curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
+}
+
+
+/* wait_or_timeout()
+ *
+ * waits for activity on any of the given sockets, or the timeout to trigger.
+ */
+
+static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
+{
+ bool done = FALSE;
+ CURLMcode mcode;
+ CURLcode result = CURLE_OK;
+
+ while(!done) {
+ CURLMsg *msg;
+ struct socketmonitor *m;
+ struct pollfd *f;
+ struct pollfd fds[4];
+ int numfds=0;
+ int pollrc;
+ int i;
+ struct timeval before;
+ struct timeval after;
+
+ /* populate the fds[] array */
+ for(m = ev->list, f=&fds[0]; m; m = m->next) {
+ f->fd = m->socket.fd;
+ f->events = m->socket.events;
+ f->revents = 0;
+ /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
+ f++;
+ numfds++;
+ }
+
+ /* get the time stamp to use to figure out how long poll takes */
+ before = curlx_tvnow();
+
+ /* wait for activity or timeout */
+ pollrc = Curl_poll(fds, numfds, (int)ev->ms);
+
+ after = curlx_tvnow();
+
+ ev->msbump = FALSE; /* reset here */
+
+ if(0 == pollrc) {
+ /* timeout! */
+ ev->ms = 0;
+ /* fprintf(stderr, "call curl_multi_socket_action( TIMEOUT )\n"); */
+ mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
+ &ev->running_handles);
+ }
+ else if(pollrc > 0) {
+ /* loop over the monitored sockets to see which ones had activity */
+ for(i = 0; i< numfds; i++) {
+ if(fds[i].revents) {
+ /* socket activity, tell libcurl */
+ int act = poll2cselect(fds[i].revents); /* convert */
+ infof(multi->easyp, "call curl_multi_socket_action( socket %d )\n",
+ fds[i].fd);
+ mcode = curl_multi_socket_action(multi, fds[i].fd, act,
+ &ev->running_handles);
+ }
+ }
+
+ if(!ev->msbump)
+ /* If nothing updated the timeout, we decrease it by the spent time.
+ * If it was updated, it has the new timeout time stored already.
+ */
+ ev->ms += curlx_tvdiff(after, before);
+
+ }
+ else
+ return CURLE_RECV_ERROR;
+
+ if(mcode)
+ return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
+
+ /* we don't really care about the "msgs_in_queue" value returned in the
+ second argument */
+ msg = curl_multi_info_read(multi, &pollrc);
+ if(msg) {
+ result = msg->data.result;
+ done = TRUE;
+ }
+ }
+
+ return result;
+}
+
+
+/* easy_events()
+ *
+ * Runs a transfer in a blocking manner using the events-based API
+ */
+static CURLcode easy_events(CURLM *multi)
+{
+ struct events evs= {2, FALSE, 0, NULL, 0};
+
+ /* if running event-based, do some further multi inits */
+ events_setup(multi, &evs);
+
+ return wait_or_timeout(multi, &evs);
+}
+#else /* CURLDEBUG */
+/* when not built with debug, this function doesn't exist */
+#define easy_events(x) CURLE_NOT_BUILT_IN
+#endif
+
+static CURLcode easy_transfer(CURLM *multi)
+{
+ bool done = FALSE;
+ CURLMcode mcode = CURLM_OK;
+ CURLcode result = CURLE_OK;
+ struct timeval before;
+ int without_fds = 0; /* count number of consecutive returns from
+ curl_multi_wait() without any filedescriptors */
+
+ while(!done && !mcode) {
+ int still_running = 0;
+ int ret;
+
+ before = curlx_tvnow();
+ mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret);
+
+ if(mcode == CURLM_OK) {
+ if(ret == -1) {
+ /* poll() failed not on EINTR, indicate a network problem */
+ result = CURLE_RECV_ERROR;
+ break;
+ }
+ else if(ret == 0) {
+ struct timeval after = curlx_tvnow();
+ /* If it returns without any filedescriptor instantly, we need to
+ avoid busy-looping during periods where it has nothing particular
+ to wait for */
+ if(curlx_tvdiff(after, before) <= 10) {
+ without_fds++;
+ if(without_fds > 2) {
+ int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000;
+ Curl_wait_ms(sleep_ms);
+ }
+ }
+ else
+ /* it wasn't "instant", restart counter */
+ without_fds = 0;
+ }
+ else
+ /* got file descriptor, restart counter */
+ without_fds = 0;
+
+ mcode = curl_multi_perform(multi, &still_running);
+ }
+
+ /* only read 'still_running' if curl_multi_perform() return OK */
+ if((mcode == CURLM_OK) && !still_running) {
+ int rc;
+ CURLMsg *msg = curl_multi_info_read(multi, &rc);
+ if(msg) {
+ result = msg->data.result;
+ done = TRUE;
+ }
+ }
+ }
+
+ /* Make sure to return some kind of error if there was a multi problem */
+ if(mcode) {
+ return (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
+ /* The other multi errors should never happen, so return
+ something suitably generic */
+ CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ return result;
+}
+
+
+/*
+ * easy_perform() is the external interface that performs a blocking
+ * transfer as previously setup.
+ *
+ * CONCEPT: This function creates a multi handle, adds the easy handle to it,
+ * runs curl_multi_perform() until the transfer is done, then detaches the
+ * easy handle, destroys the multi handle and returns the easy handle's return
+ * code.
+ *
+ * REALITY: it can't just create and destroy the multi handle that easily. It
+ * needs to keep it around since if this easy handle is used again by this
+ * function, the same multi handle must be re-used so that the same pools and
+ * caches can be used.
+ *
+ * DEBUG: if 'events' is set TRUE, this function will use a replacement engine
+ * instead of curl_multi_perform() and use curl_multi_socket_action().
+ */
+static CURLcode easy_perform(struct SessionHandle *data, bool events)
+{
+ CURLM *multi;
+ CURLMcode mcode;
+ CURLcode result = CURLE_OK;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ if(!data)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(data->multi) {
+ failf(data, "easy handle already used in multi handle");
+ return CURLE_FAILED_INIT;
+ }
+
+ if(data->multi_easy)
+ multi = data->multi_easy;
+ else {
+ /* this multi handle will only ever have a single easy handled attached
+ to it, so make it use minimal hashes */
+ multi = Curl_multi_handle(1, 3);
+ if(!multi)
+ return CURLE_OUT_OF_MEMORY;
+ data->multi_easy = multi;
+ }
+
+ /* Copy the MAXCONNECTS option to the multi handle */
+ curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
+
+ mcode = curl_multi_add_handle(multi, data);
+ if(mcode) {
+ curl_multi_cleanup(multi);
+ if(mcode == CURLM_OUT_OF_MEMORY)
+ return CURLE_OUT_OF_MEMORY;
+ else
+ return CURLE_FAILED_INIT;
+ }
+
+ sigpipe_ignore(data, &pipe_st);
+
+ /* assign this after curl_multi_add_handle() since that function checks for
+ it and rejects this handle otherwise */
+ data->multi = multi;
+
+ /* run the transfer */
+ result = events ? easy_events(multi) : easy_transfer(multi);
+
+ /* ignoring the return code isn't nice, but atm we can't really handle
+ a failure here, room for future improvement! */
+ (void)curl_multi_remove_handle(multi, data);
+
+ sigpipe_restore(&pipe_st);
+
+ /* The multi handle is kept alive, owned by the easy handle */
+ return result;
+}
+
+
+/*
+ * curl_easy_perform() is the external interface that performs a blocking
+ * transfer as previously setup.
+ */
+CURLcode curl_easy_perform(CURL *easy)
+{
+ return easy_perform(easy, FALSE);
+}
+
+#ifdef CURLDEBUG
+/*
+ * curl_easy_perform_ev() is the external interface that performs a blocking
+ * transfer using the event-based API internally.
+ */
+CURLcode curl_easy_perform_ev(CURL *easy)
+{
+ return easy_perform(easy, TRUE);
+}
+
+#endif
+
+/*
+ * curl_easy_cleanup() is the external interface to cleaning/freeing the given
+ * easy handle.
+ */
+void curl_easy_cleanup(CURL *curl)
+{
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ if(!data)
+ return;
+
+ sigpipe_ignore(data, &pipe_st);
+ Curl_close(data);
+ sigpipe_restore(&pipe_st);
+}
+
+/*
+ * curl_easy_getinfo() is an external interface that allows an app to retrieve
+ * information from a performed transfer and similar.
+ */
+//#undef curl_easy_getinfo
+CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
+{
+ va_list arg;
+ void *paramp;
+ CURLcode result;
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ va_start(arg, info);
+ paramp = va_arg(arg, void *);
+
+ result = Curl_getinfo(data, info, paramp);
+
+ va_end(arg);
+ return result;
+}
+
+/*
+ * curl_easy_duphandle() is an external interface to allow duplication of a
+ * given input easy handle. The returned handle will be a new working handle
+ * with all options set exactly as the input source handle.
+ */
+CURL *curl_easy_duphandle(CURL *incurl)
+{
+ struct SessionHandle *data=(struct SessionHandle *)incurl;
+
+ struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle));
+ if(NULL == outcurl)
+ goto fail;
+
+ /*
+ * We setup a few buffers we need. We should probably make them
+ * get setup on-demand in the code, as that would probably decrease
+ * the likeliness of us forgetting to init a buffer here in the future.
+ */
+ outcurl->state.headerbuff = malloc(HEADERSIZE);
+ if(!outcurl->state.headerbuff)
+ goto fail;
+ outcurl->state.headersize = HEADERSIZE;
+
+ /* copy all userdefined values */
+ if(Curl_dupset(outcurl, data))
+ goto fail;
+
+ /* the connection cache is setup on demand */
+ outcurl->state.conn_cache = NULL;
+
+ outcurl->state.lastconnect = NULL;
+
+ outcurl->progress.flags = data->progress.flags;
+ outcurl->progress.callback = data->progress.callback;
+
+ if(data->cookies) {
+ /* If cookies are enabled in the parent handle, we enable them
+ in the clone as well! */
+ outcurl->cookies = Curl_cookie_init(data,
+ data->cookies->filename,
+ outcurl->cookies,
+ data->set.cookiesession);
+ if(!outcurl->cookies)
+ goto fail;
+ }
+
+ /* duplicate all values in 'change' */
+ if(data->change.cookielist) {
+ outcurl->change.cookielist =
+ Curl_slist_duplicate(data->change.cookielist);
+ if(!outcurl->change.cookielist)
+ goto fail;
+ }
+
+ if(data->change.url) {
+ outcurl->change.url = strdup(data->change.url);
+ if(!outcurl->change.url)
+ goto fail;
+ outcurl->change.url_alloc = TRUE;
+ }
+
+ if(data->change.referer) {
+ outcurl->change.referer = strdup(data->change.referer);
+ if(!outcurl->change.referer)
+ goto fail;
+ outcurl->change.referer_alloc = TRUE;
+ }
+
+ /* Clone the resolver handle, if present, for the new handle */
+ if(Curl_resolver_duphandle(&outcurl->state.resolver,
+ data->state.resolver))
+ goto fail;
+
+ Curl_convert_setup(outcurl);
+
+ outcurl->magic = CURLEASY_MAGIC_NUMBER;
+
+ /* we reach this point and thus we are OK */
+
+ return outcurl;
+
+ fail:
+
+ if(outcurl) {
+ curl_slist_free_all(outcurl->change.cookielist);
+ outcurl->change.cookielist = NULL;
+ Curl_safefree(outcurl->state.headerbuff);
+ Curl_safefree(outcurl->change.url);
+ Curl_safefree(outcurl->change.referer);
+ Curl_freeset(outcurl);
+ free(outcurl);
+ }
+
+ return NULL;
+}
+
+/*
+ * curl_easy_reset() is an external interface that allows an app to re-
+ * initialize a session handle to the default values.
+ */
+void curl_easy_reset(CURL *curl)
+{
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ Curl_safefree(data->state.pathbuffer);
+
+ data->state.path = NULL;
+
+ Curl_free_request_state(data);
+
+ /* zero out UserDefined data: */
+ Curl_freeset(data);
+ memset(&data->set, 0, sizeof(struct UserDefined));
+ (void)Curl_init_userdefined(&data->set);
+
+ /* zero out Progress data: */
+ memset(&data->progress, 0, sizeof(struct Progress));
+
+ data->progress.flags |= PGRS_HIDE;
+ data->state.current_speed = -1; /* init to negative == impossible */
+}
+
+/*
+ * curl_easy_pause() allows an application to pause or unpause a specific
+ * transfer and direction. This function sets the full new state for the
+ * current connection this easy handle operates on.
+ *
+ * NOTE: if you have the receiving paused and you call this function to remove
+ * the pausing, you may get your write callback called at this point.
+ *
+ * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
+ */
+CURLcode curl_easy_pause(CURL *curl, int action)
+{
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+ struct SingleRequest *k = &data->req;
+ CURLcode result = CURLE_OK;
+
+ /* first switch off both pause bits */
+ int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
+
+ /* set the new desired pause bits */
+ newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
+ ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
+
+ /* put it back in the keepon */
+ k->keepon = newstate;
+
+ if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
+ /* we have a buffer for sending that we now seem to be able to deliver
+ since the receive pausing is lifted! */
+
+ /* get the pointer in local copy since the function may return PAUSE
+ again and then we'll get a new copy allocted and stored in
+ the tempwrite variables */
+ char *tempwrite = data->state.tempwrite;
+
+ data->state.tempwrite = NULL;
+ result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype,
+ tempwrite, data->state.tempwritesize);
+ free(tempwrite);
+ }
+
+ /* if there's no error and we're not pausing both directions, we want
+ to have this handle checked soon */
+ if(!result &&
+ ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
+ (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
+ Curl_expire(data, 1); /* get this handle going again */
+
+ return result;
+}
+
+
+static CURLcode easy_connection(struct SessionHandle *data,
+ curl_socket_t *sfd,
+ struct connectdata **connp)
+{
+ if(data == NULL)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
+ if(!data->set.connect_only) {
+ failf(data, "CONNECT_ONLY is required!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ *sfd = Curl_getconnectinfo(data, connp);
+
+ if(*sfd == CURL_SOCKET_BAD) {
+ failf(data, "Failed to get recent socket");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ * Returns CURLE_OK on success, error code on error.
+ */
+CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
+{
+ curl_socket_t sfd;
+ CURLcode result;
+ ssize_t n1;
+ struct connectdata *c;
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ result = easy_connection(data, &sfd, &c);
+ if(result)
+ return result;
+
+ *n = 0;
+ result = Curl_read(c, sfd, buffer, buflen, &n1);
+
+ if(result)
+ return result;
+
+ *n = (size_t)n1;
+
+ return CURLE_OK;
+}
+
+/*
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen,
+ size_t *n)
+{
+ curl_socket_t sfd;
+ CURLcode result;
+ ssize_t n1;
+ struct connectdata *c = NULL;
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ result = easy_connection(data, &sfd, &c);
+ if(result)
+ return result;
+
+ *n = 0;
+ result = Curl_write(c, sfd, buffer, buflen, &n1);
+
+ if(n1 == -1)
+ return CURLE_SEND_ERROR;
+
+ /* detect EAGAIN */
+ if(!result && !n1)
+ return CURLE_AGAIN;
+
+ *n = (size_t)n1;
+
+ return result;
+}
diff --git a/libcurl/src/lib/easyif.h b/libcurl/src/lib/easyif.h
new file mode 100644
index 0000000..043ff43
--- /dev/null
+++ b/libcurl/src/lib/easyif.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_EASYIF_H
+#define HEADER_CURL_EASYIF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Prototypes for library-wide functions provided by easy.c
+ */
+#ifdef CURLDEBUG
+CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy);
+#endif
+
+#endif /* HEADER_CURL_EASYIF_H */
+
diff --git a/libcurl/src/lib/escape.c b/libcurl/src/lib/escape.c
new file mode 100644
index 0000000..417a91a
--- /dev/null
+++ b/libcurl/src/lib/escape.c
@@ -0,0 +1,231 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Escape and unescape URL encoding in strings. The functions return a new
+ * allocated string or NULL if an error occurred. */
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "warnless.h"
+#include "non-ascii.h"
+#include "escape.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* Portable character check (remember EBCDIC). Do not use isalnum() because
+ its behavior is altered by the current locale.
+ See http://tools.ietf.org/html/rfc3986#section-2.3
+*/
+static bool Curl_isunreserved(unsigned char in)
+{
+ switch (in) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case '-': case '.': case '_': case '~':
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/* for ABI-compatibility with previous versions */
+char *curl_escape(const char *string, int inlength)
+{
+ return curl_easy_escape(NULL, string, inlength);
+}
+
+/* for ABI-compatibility with previous versions */
+char *curl_unescape(const char *string, int length)
+{
+ return curl_easy_unescape(NULL, string, length, NULL);
+}
+
+char *curl_easy_escape(CURL *handle, const char *string, int inlength)
+{
+ size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
+ char *ns;
+ char *testing_ptr = NULL;
+ unsigned char in; /* we need to treat the characters unsigned */
+ size_t newlen = alloc;
+ size_t strindex=0;
+ size_t length;
+ CURLcode result;
+
+ ns = malloc(alloc);
+ if(!ns)
+ return NULL;
+
+ length = alloc-1;
+ while(length--) {
+ in = *string;
+
+ if(Curl_isunreserved(in))
+ /* just copy this */
+ ns[strindex++]=in;
+ else {
+ /* encode it */
+ newlen += 2; /* the size grows with two, since this'll become a %XX */
+ if(newlen > alloc) {
+ alloc *= 2;
+ testing_ptr = realloc(ns, alloc);
+ if(!testing_ptr) {
+ free( ns );
+ return NULL;
+ }
+ else {
+ ns = testing_ptr;
+ }
+ }
+
+ result = Curl_convert_to_network(handle, &in, 1);
+ if(result) {
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ free(ns);
+ return NULL;
+ }
+
+ snprintf(&ns[strindex], 4, "%%%02X", in);
+
+ strindex+=3;
+ }
+ string++;
+ }
+ ns[strindex]=0; /* terminate it */
+ return ns;
+}
+
+/*
+ * Curl_urldecode() URL decodes the given string.
+ *
+ * Optionally detects control characters (byte codes lower than 32) in the
+ * data and rejects such data.
+ *
+ * Returns a pointer to a malloced string in *ostring with length given in
+ * *olen. If length == 0, the length is assumed to be strlen(string).
+ *
+ */
+CURL_STATIC CURLcode Curl_urldecode(struct SessionHandle *data,
+ const char *string, size_t length,
+ char **ostring, size_t *olen,
+ bool reject_ctrl)
+{
+ size_t alloc = (length?length:strlen(string))+1;
+ char *ns = malloc(alloc);
+ unsigned char in;
+ size_t strindex=0;
+ unsigned long hex;
+ CURLcode result;
+
+ if(!ns)
+ return CURLE_OUT_OF_MEMORY;
+
+ while(--alloc > 0) {
+ in = *string;
+ if(('%' == in) && (alloc > 2) &&
+ ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
+ /* this is two hexadecimal digits following a '%' */
+ char hexstr[3];
+ char *ptr;
+ hexstr[0] = string[1];
+ hexstr[1] = string[2];
+ hexstr[2] = 0;
+
+ hex = strtoul(hexstr, &ptr, 16);
+
+ in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
+
+ result = Curl_convert_from_network(data, &in, 1);
+ if(result) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(ns);
+ return result;
+ }
+
+ string+=2;
+ alloc-=2;
+ }
+
+ if(reject_ctrl && (in < 0x20)) {
+ free(ns);
+ return CURLE_URL_MALFORMAT;
+ }
+
+ ns[strindex++] = in;
+ string++;
+ }
+ ns[strindex]=0; /* terminate it */
+
+ if(olen)
+ /* store output size */
+ *olen = strindex;
+
+ /* store output string */
+ *ostring = ns;
+
+ return CURLE_OK;
+}
+
+/*
+ * Unescapes the given URL escaped string of given length. Returns a
+ * pointer to a malloced string with length given in *olen.
+ * If length == 0, the length is assumed to be strlen(string).
+ * If olen == NULL, no output length is stored.
+ */
+char *curl_easy_unescape(CURL *handle, const char *string, int length,
+ int *olen)
+{
+ char *str = NULL;
+ size_t inputlen = length;
+ size_t outputlen;
+ CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen,
+ FALSE);
+ if(res)
+ return NULL;
+ if(olen)
+ *olen = curlx_uztosi(outputlen);
+ return str;
+}
+
+/* For operating systems/environments that use different malloc/free
+ systems for the app and for this library, we provide a free that uses
+ the library's memory system */
+void curl_free(void *p)
+{
+ free(p);
+}
diff --git a/libcurl/src/lib/escape.h b/libcurl/src/lib/escape.h
new file mode 100644
index 0000000..b640c17
--- /dev/null
+++ b/libcurl/src/lib/escape.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_ESCAPE_H
+#define HEADER_CURL_ESCAPE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/* Escape and unescape URL encoding in strings. The functions return a new
+ * allocated string or NULL if an error occurred. */
+
+CURL_STATIC CURLcode Curl_urldecode(struct SessionHandle *data,
+ const char *string, size_t length,
+ char **ostring, size_t *olen,
+ bool reject_crlf);
+
+#endif /* HEADER_CURL_ESCAPE_H */
+
diff --git a/libcurl/src/lib/file.c b/libcurl/src/lib/file.c
new file mode 100644
index 0000000..324d4e2
--- /dev/null
+++ b/libcurl/src/lib/file.c
@@ -0,0 +1,588 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FILE
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "strtoofft.h"
+#include "urldata.h"
+#include <curl/curl.h>
+#include "progress.h"
+#include "sendf.h"
+#include "escape.h"
+#include "file.h"
+#include "speedcheck.h"
+#include "getinfo.h"
+#include "transfer.h"
+#include "url.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "warnless.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \
+ defined(__SYMBIAN32__)
+#define DOS_FILESYSTEM 1
+#endif
+
+#ifdef OPEN_NEEDS_ARG3
+# define open_readonly(p,f) open((p),(f),(0))
+#else
+# define open_readonly(p,f) open((p),(f))
+#endif
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode file_do(struct connectdata *, bool *done);
+static CURLcode file_done(struct connectdata *conn,
+ CURLcode status, bool premature);
+static CURLcode file_connect(struct connectdata *conn, bool *done);
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection);
+static CURLcode file_setup_connection(struct connectdata *conn);
+
+/*
+ * FILE scheme handler.
+ */
+
+const struct Curl_handler Curl_handler_file = {
+ "FILE", /* scheme */
+ file_setup_connection, /* setup_connection */
+ file_do, /* do_it */
+ file_done, /* done */
+ ZERO_NULL, /* do_more */
+ file_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ file_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ 0, /* defport */
+ CURLPROTO_FILE, /* protocol */
+ PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+static CURLcode file_setup_connection(struct connectdata *conn)
+{
+ /* allocate the FILE specific struct */
+ conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO));
+ if(!conn->data->req.protop)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+ /*
+ Check if this is a range download, and if so, set the internal variables
+ properly. This code is copied from the FTP implementation and might as
+ well be factored out.
+ */
+static CURLcode file_range(struct connectdata *conn)
+{
+ curl_off_t from, to;
+ curl_off_t totalsize=-1;
+ char *ptr;
+ char *ptr2;
+ struct SessionHandle *data = conn->data;
+
+ if(data->state.use_range && data->state.range) {
+ from=curlx_strtoofft(data->state.range, &ptr, 0);
+ while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ ptr++;
+ to=curlx_strtoofft(ptr, &ptr2, 0);
+ if(ptr == ptr2) {
+ /* we didn't get any digit */
+ to=-1;
+ }
+ if((-1 == to) && (from>=0)) {
+ /* X - */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
+ from));
+ }
+ else if(from < 0) {
+ /* -Y */
+ data->req.maxdownload = -from;
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ -from));
+ }
+ else {
+ /* X-Y */
+ totalsize = to-from;
+ data->req.maxdownload = totalsize+1; /* include last byte */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, data->req.maxdownload));
+ }
+ DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
+ " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, to, data->req.maxdownload));
+ }
+ else
+ data->req.maxdownload = -1;
+ return CURLE_OK;
+}
+
+/*
+ * file_connect() gets called from Curl_protocol_connect() to allow us to
+ * do protocol-specific actions at connect-time. We emulate a
+ * connect-then-transfer protocol and "connect" to the file here
+ */
+static CURLcode file_connect(struct connectdata *conn, bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ char *real_path;
+ struct FILEPROTO *file = data->req.protop;
+ int fd;
+#ifdef DOS_FILESYSTEM
+ int i;
+ char *actual_path;
+#endif
+ int real_path_len;
+
+ real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len);
+ if(!real_path)
+ return CURLE_OUT_OF_MEMORY;
+
+#ifdef DOS_FILESYSTEM
+ /* If the first character is a slash, and there's
+ something that looks like a drive at the beginning of
+ the path, skip the slash. If we remove the initial
+ slash in all cases, paths without drive letters end up
+ relative to the current directory which isn't how
+ browsers work.
+
+ Some browsers accept | instead of : as the drive letter
+ separator, so we do too.
+
+ On other platforms, we need the slash to indicate an
+ absolute pathname. On Windows, absolute paths start
+ with a drive letter.
+ */
+ actual_path = real_path;
+ if((actual_path[0] == '/') &&
+ actual_path[1] &&
+ (actual_path[2] == ':' || actual_path[2] == '|')) {
+ actual_path[2] = ':';
+ actual_path++;
+ real_path_len--;
+ }
+
+ /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
+ for(i=0; i < real_path_len; ++i)
+ if(actual_path[i] == '/')
+ actual_path[i] = '\\';
+ else if(!actual_path[i]) /* binary zero */
+ return CURLE_URL_MALFORMAT;
+
+ fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
+ file->path = actual_path;
+#else
+ if(memchr(real_path, 0, real_path_len))
+ /* binary zeroes indicate foul play */
+ return CURLE_URL_MALFORMAT;
+
+ fd = open_readonly(real_path, O_RDONLY);
+ file->path = real_path;
+#endif
+ file->freepath = real_path; /* free this when done */
+
+ file->fd = fd;
+ if(!data->set.upload && (fd == -1)) {
+ failf(data, "Couldn't open file %s", data->state.path);
+ file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
+ return CURLE_FILE_COULDNT_READ_FILE;
+ }
+ *done = TRUE;
+
+ return CURLE_OK;
+}
+
+static CURLcode file_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct FILEPROTO *file = conn->data->req.protop;
+ (void)status; /* not used */
+ (void)premature; /* not used */
+
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ struct FILEPROTO *file = conn->data->req.protop;
+ (void)dead_connection; /* not used */
+
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
+
+ return CURLE_OK;
+}
+
+#ifdef DOS_FILESYSTEM
+#define DIRSEP '\\'
+#else
+#define DIRSEP '/'
+#endif
+
+static CURLcode file_upload(struct connectdata *conn)
+{
+ struct FILEPROTO *file = conn->data->req.protop;
+ const char *dir = strchr(file->path, DIRSEP);
+ int fd;
+ int mode;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *buf = data->state.buffer;
+ size_t nread;
+ size_t nwrite;
+ curl_off_t bytecount = 0;
+ struct timeval now = Curl_tvnow();
+ struct_stat file_stat;
+ const char* buf2;
+
+ /*
+ * Since FILE: doesn't do the full init, we need to provide some extra
+ * assignments here.
+ */
+ conn->fread_func = data->set.fread_func;
+ conn->fread_in = data->set.in;
+ conn->data->req.upload_fromhere = buf;
+
+ if(!dir)
+ return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
+
+ if(!dir[1])
+ return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
+
+#ifdef O_BINARY
+#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY
+#else
+#define MODE_DEFAULT O_WRONLY|O_CREAT
+#endif
+
+ if(data->state.resume_from)
+ mode = MODE_DEFAULT|O_APPEND;
+ else
+ mode = MODE_DEFAULT|O_TRUNC;
+
+ fd = open(file->path, mode, conn->data->set.new_file_perms);
+ if(fd < 0) {
+ failf(data, "Can't open %s for writing", file->path);
+ return CURLE_WRITE_ERROR;
+ }
+
+ if(-1 != data->state.infilesize)
+ /* known size of data to "upload" */
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* treat the negative resume offset value as the case of "-" */
+ if(data->state.resume_from < 0) {
+ if(fstat(fd, &file_stat)) {
+ close(fd);
+ failf(data, "Can't get the size of %s", file->path);
+ return CURLE_WRITE_ERROR;
+ }
+ else
+ data->state.resume_from = (curl_off_t)file_stat.st_size;
+ }
+
+ while(!result) {
+ int readcount;
+ result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
+ if(result)
+ break;
+
+ if(readcount <= 0) /* fix questionable compare error. curlvms */
+ break;
+
+ nread = (size_t)readcount;
+
+ /*skip bytes before resume point*/
+ if(data->state.resume_from) {
+ if((curl_off_t)nread <= data->state.resume_from ) {
+ data->state.resume_from -= nread;
+ nread = 0;
+ buf2 = buf;
+ }
+ else {
+ buf2 = buf + data->state.resume_from;
+ nread -= (size_t)data->state.resume_from;
+ data->state.resume_from = 0;
+ }
+ }
+ else
+ buf2 = buf;
+
+ /* write the data to the target */
+ nwrite = write(fd, buf2, nread);
+ if(nwrite != nread) {
+ result = CURLE_SEND_ERROR;
+ break;
+ }
+
+ bytecount += nread;
+
+ Curl_pgrsSetUploadCounter(data, bytecount);
+
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(data, now);
+ }
+ if(!result && Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+
+ close(fd);
+
+ return result;
+}
+
+/*
+ * file_do() is the protocol-specific function for the do-phase, separated
+ * from the connect-phase above. Other protocols merely setup the transfer in
+ * the do-phase, to have it done in the main transfer loop but since some
+ * platforms we support don't allow select()ing etc on file handles (as
+ * opposed to sockets) we instead perform the whole do-operation in this
+ * function.
+ */
+static CURLcode file_do(struct connectdata *conn, bool *done)
+{
+ /* This implementation ignores the host name in conformance with
+ RFC 1738. Only local files (reachable via the standard file system)
+ are supported. This means that files on remotely mounted directories
+ (via NFS, Samba, NT sharing) can be accessed through a file:// URL
+ */
+ CURLcode result = CURLE_OK;
+ struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
+ Windows version to have a different struct without
+ having to redefine the simple word 'stat' */
+ curl_off_t expected_size=0;
+ bool fstated=FALSE;
+ ssize_t nread;
+ struct SessionHandle *data = conn->data;
+ char *buf = data->state.buffer;
+ curl_off_t bytecount = 0;
+ int fd;
+ struct timeval now = Curl_tvnow();
+ struct FILEPROTO *file;
+
+ *done = TRUE; /* unconditionally */
+
+ Curl_initinfo(data);
+ Curl_pgrsStartNow(data);
+
+ if(data->set.upload)
+ return file_upload(conn);
+
+ file = conn->data->req.protop;
+
+ /* get the fd from the connection phase */
+ fd = file->fd;
+
+ /* VMS: This only works reliable for STREAMLF files */
+ if(-1 != fstat(fd, &statbuf)) {
+ /* we could stat it, then read out the size */
+ expected_size = statbuf.st_size;
+ /* and store the modification time */
+ data->info.filetime = (long)statbuf.st_mtime;
+ fstated = TRUE;
+ }
+
+ if(fstated && !data->state.range && data->set.timecondition) {
+ if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ }
+
+ /* If we have selected NOBODY and HEADER, it means that we only want file
+ information. Which for FILE can't be much more than the file size and
+ date. */
+ if(data->set.opt_no_body && data->set.include_header && fstated) {
+ snprintf(buf, sizeof(data->state.buffer),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ if(result)
+ return result;
+
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH,
+ (char *)"Accept-ranges: bytes\r\n", 0);
+ if(result)
+ return result;
+
+ if(fstated) {
+ time_t filetime = (time_t)statbuf.st_mtime;
+ struct tm buffer;
+ const struct tm *tm = &buffer;
+ result = Curl_gmtime(filetime, &buffer);
+ if(result)
+ return result;
+
+ /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
+ snprintf(buf, BUFSIZE-1,
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ }
+ /* if we fstat()ed the file, set the file size to make it available post-
+ transfer */
+ if(fstated)
+ Curl_pgrsSetDownloadSize(data, expected_size);
+ return result;
+ }
+
+ /* Check whether file range has been specified */
+ file_range(conn);
+
+ /* Adjust the start offset in case we want to get the N last bytes
+ * of the stream iff the filesize could be determined */
+ if(data->state.resume_from < 0) {
+ if(!fstated) {
+ failf(data, "Can't get the size of file.");
+ return CURLE_READ_ERROR;
+ }
+ else
+ data->state.resume_from += (curl_off_t)statbuf.st_size;
+ }
+
+ if(data->state.resume_from <= expected_size)
+ expected_size -= data->state.resume_from;
+ else {
+ failf(data, "failed to resume file:// transfer");
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+
+ /* A high water mark has been specified so we obey... */
+ if(data->req.maxdownload > 0)
+ expected_size = data->req.maxdownload;
+
+ if(fstated && (expected_size == 0))
+ return CURLE_OK;
+
+ /* The following is a shortcut implementation of file reading
+ this is both more efficient than the former call to download() and
+ it avoids problems with select() and recv() on file descriptors
+ in Winsock */
+ if(fstated)
+ Curl_pgrsSetDownloadSize(data, expected_size);
+
+ if(data->state.resume_from) {
+ if(data->state.resume_from !=
+ lseek(fd, data->state.resume_from, SEEK_SET))
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+
+ while(!result) {
+ /* Don't fill a whole buffer if we want less than all data */
+ size_t bytestoread =
+ (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
+ curlx_sotouz(expected_size) : BUFSIZE - 1;
+
+ nread = read(fd, buf, bytestoread);
+
+ if(nread > 0)
+ buf[nread] = 0;
+
+ if(nread <= 0 || expected_size == 0)
+ break;
+
+ bytecount += nread;
+ expected_size -= nread;
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
+ if(result)
+ return result;
+
+ Curl_pgrsSetDownloadCounter(data, bytecount);
+
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(data, now);
+ }
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+
+ return result;
+}
+
+#endif
diff --git a/libcurl/src/lib/file.h b/libcurl/src/lib/file.h
new file mode 100644
index 0000000..997474b
--- /dev/null
+++ b/libcurl/src/lib/file.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_FILE_H
+#define HEADER_CURL_FILE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/****************************************************************************
+ * FILE unique setup
+ ***************************************************************************/
+struct FILEPROTO {
+ char *path; /* the path we operate on */
+ char *freepath; /* pointer to the allocated block we must free, this might
+ differ from the 'path' pointer */
+ int fd; /* open file descriptor to read from! */
+};
+
+#ifndef CURL_DISABLE_FILE
+extern const struct Curl_handler Curl_handler_file;
+#endif
+
+#endif /* HEADER_CURL_FILE_H */
+
diff --git a/libcurl/src/lib/fileinfo.c b/libcurl/src/lib/fileinfo.c
new file mode 100644
index 0000000..68a2e9c
--- /dev/null
+++ b/libcurl/src/lib/fileinfo.c
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "strdup.h"
+#include "fileinfo.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURL_STATIC struct curl_fileinfo *Curl_fileinfo_alloc(void)
+{
+ struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo));
+ if(!tmp)
+ return NULL;
+ memset(tmp, 0, sizeof(struct curl_fileinfo));
+ return tmp;
+}
+
+CURL_STATIC void Curl_fileinfo_dtor(void *user, void *element)
+{
+ struct curl_fileinfo *finfo = element;
+ (void) user;
+ if(!finfo)
+ return;
+
+ Curl_safefree(finfo->b_data);
+
+ free(finfo);
+}
diff --git a/libcurl/src/lib/fileinfo.h b/libcurl/src/lib/fileinfo.h
new file mode 100644
index 0000000..7e73fad
--- /dev/null
+++ b/libcurl/src/lib/fileinfo.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_FILEINFO_H
+#define HEADER_CURL_FILEINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+CURL_STATIC struct curl_fileinfo *Curl_fileinfo_alloc(void);
+
+CURL_STATIC void Curl_fileinfo_dtor(void *, void *);
+
+CURL_STATIC struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src);
+
+#endif /* HEADER_CURL_FILEINFO_H */
diff --git a/libcurl/src/lib/formdata.c b/libcurl/src/lib/formdata.c
new file mode 100644
index 0000000..3e97830
--- /dev/null
+++ b/libcurl/src/lib/formdata.c
@@ -0,0 +1,1551 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#ifndef CURL_DISABLE_HTTP
+
+#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
+#include <libgen.h>
+#endif
+
+#include "urldata.h" /* for struct SessionHandle */
+#include "formdata.h"
+#include "vtls/vtls.h"
+#include "strequal.h"
+#include "sendf.h"
+#include "strdup.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef HAVE_BASENAME
+static char *Curl_basename(char *path);
+#define basename(x) Curl_basename((x))
+#endif
+
+static size_t readfromfile(struct Form *form, char *buffer, size_t size);
+static char *formboundary(struct SessionHandle *data);
+
+/* What kind of Content-Type to use on un-specified files with unrecognized
+ extensions. */
+#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
+
+#define FORM_FILE_SEPARATOR ','
+#define FORM_TYPE_SEPARATOR ';'
+
+/***************************************************************************
+ *
+ * AddHttpPost()
+ *
+ * Adds a HttpPost structure to the list, if parent_post is given becomes
+ * a subpost of parent_post instead of a direct list element.
+ *
+ * Returns newly allocated HttpPost on success and NULL if malloc failed.
+ *
+ ***************************************************************************/
+static struct curl_httppost *
+AddHttpPost(char *name, size_t namelength,
+ char *value, size_t contentslength,
+ char *buffer, size_t bufferlength,
+ char *contenttype,
+ long flags,
+ struct curl_slist* contentHeader,
+ char *showfilename, char *userp,
+ struct curl_httppost *parent_post,
+ struct curl_httppost **httppost,
+ struct curl_httppost **last_post)
+{
+ struct curl_httppost *post;
+ post = calloc(1, sizeof(struct curl_httppost));
+ if(post) {
+ post->name = name;
+ post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
+ post->contents = value;
+ post->contentslength = (long)contentslength;
+ post->buffer = buffer;
+ post->bufferlength = (long)bufferlength;
+ post->contenttype = contenttype;
+ post->contentheader = contentHeader;
+ post->showfilename = showfilename;
+ post->userp = userp,
+ post->flags = flags;
+ }
+ else
+ return NULL;
+
+ if(parent_post) {
+ /* now, point our 'more' to the original 'more' */
+ post->more = parent_post->more;
+
+ /* then move the original 'more' to point to ourselves */
+ parent_post->more = post;
+ }
+ else {
+ /* make the previous point to this */
+ if(*last_post)
+ (*last_post)->next = post;
+ else
+ (*httppost) = post;
+
+ (*last_post) = post;
+ }
+ return post;
+}
+
+/***************************************************************************
+ *
+ * AddFormInfo()
+ *
+ * Adds a FormInfo structure to the list presented by parent_form_info.
+ *
+ * Returns newly allocated FormInfo on success and NULL if malloc failed/
+ * parent_form_info is NULL.
+ *
+ ***************************************************************************/
+static FormInfo * AddFormInfo(char *value,
+ char *contenttype,
+ FormInfo *parent_form_info)
+{
+ FormInfo *form_info;
+ form_info = calloc(1, sizeof(struct FormInfo));
+ if(form_info) {
+ if(value)
+ form_info->value = value;
+ if(contenttype)
+ form_info->contenttype = contenttype;
+ form_info->flags = HTTPPOST_FILENAME;
+ }
+ else
+ return NULL;
+
+ if(parent_form_info) {
+ /* now, point our 'more' to the original 'more' */
+ form_info->more = parent_form_info->more;
+
+ /* then move the original 'more' to point to ourselves */
+ parent_form_info->more = form_info;
+ }
+
+ return form_info;
+}
+
+/***************************************************************************
+ *
+ * ContentTypeForFilename()
+ *
+ * Provides content type for filename if one of the known types (else
+ * (either the prevtype or the default is returned).
+ *
+ * Returns some valid contenttype for filename.
+ *
+ ***************************************************************************/
+static const char *ContentTypeForFilename(const char *filename,
+ const char *prevtype)
+{
+ const char *contenttype = NULL;
+ unsigned int i;
+ /*
+ * No type was specified, we scan through a few well-known
+ * extensions and pick the first we match!
+ */
+ struct ContentType {
+ const char *extension;
+ const char *type;
+ };
+ static const struct ContentType ctts[]={
+ {".gif", "image/gif"},
+ {".jpg", "image/jpeg"},
+ {".jpeg", "image/jpeg"},
+ {".txt", "text/plain"},
+ {".html", "text/html"},
+ {".xml", "application/xml"}
+ };
+
+ if(prevtype)
+ /* default to the previously set/used! */
+ contenttype = prevtype;
+ else
+ contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
+
+ if(filename) { /* in case a NULL was passed in */
+ for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
+ if(strlen(filename) >= strlen(ctts[i].extension)) {
+ if(strequal(filename +
+ strlen(filename) - strlen(ctts[i].extension),
+ ctts[i].extension)) {
+ contenttype = ctts[i].type;
+ break;
+ }
+ }
+ }
+ }
+ /* we have a contenttype by now */
+ return contenttype;
+}
+
+/***************************************************************************
+ *
+ * FormAdd()
+ *
+ * Stores a formpost parameter and builds the appropriate linked list.
+ *
+ * Has two principal functionalities: using files and byte arrays as
+ * post parts. Byte arrays are either copied or just the pointer is stored
+ * (as the user requests) while for files only the filename and not the
+ * content is stored.
+ *
+ * While you may have only one byte array for each name, multiple filenames
+ * are allowed (and because of this feature CURLFORM_END is needed after
+ * using CURLFORM_FILE).
+ *
+ * Examples:
+ *
+ * Simple name/value pair with copied contents:
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
+ *
+ * name/value pair where only the content pointer is remembered:
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
+ * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
+ *
+ * storing a filename (CONTENTTYPE is optional!):
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
+ * CURLFORM_END);
+ *
+ * storing multiple filenames:
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
+ *
+ * Returns:
+ * CURL_FORMADD_OK on success
+ * CURL_FORMADD_MEMORY if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
+ * CURL_FORMADD_NULL if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
+ * CURL_FORMADD_MEMORY if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
+ *
+ ***************************************************************************/
+
+static
+CURLFORMcode FormAdd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ va_list params)
+{
+ FormInfo *first_form, *current_form, *form = NULL;
+ CURLFORMcode return_value = CURL_FORMADD_OK;
+ const char *prevtype = NULL;
+ struct curl_httppost *post = NULL;
+ CURLformoption option;
+ struct curl_forms *forms = NULL;
+ char *array_value=NULL; /* value read from an array */
+
+ /* This is a state variable, that if TRUE means that we're parsing an
+ array that we got passed to us. If FALSE we're parsing the input
+ va_list arguments. */
+ bool array_state = FALSE;
+
+ /*
+ * We need to allocate the first struct to fill in.
+ */
+ first_form = calloc(1, sizeof(struct FormInfo));
+ if(!first_form)
+ return CURL_FORMADD_MEMORY;
+
+ current_form = first_form;
+
+ /*
+ * Loop through all the options set. Break if we have an error to report.
+ */
+ while(return_value == CURL_FORMADD_OK) {
+
+ /* first see if we have more parts of the array param */
+ if(array_state && forms) {
+ /* get the upcoming option from the given array */
+ option = forms->option;
+ array_value = (char *)forms->value;
+
+ forms++; /* advance this to next entry */
+ if(CURLFORM_END == option) {
+ /* end of array state */
+ array_state = FALSE;
+ continue;
+ }
+ }
+ else {
+ /* This is not array-state, get next option */
+ option = va_arg(params, CURLformoption);
+ if(CURLFORM_END == option)
+ break;
+ }
+
+ switch (option) {
+ case CURLFORM_ARRAY:
+ if(array_state)
+ /* we don't support an array from within an array */
+ return_value = CURL_FORMADD_ILLEGAL_ARRAY;
+ else {
+ forms = va_arg(params, struct curl_forms *);
+ if(forms)
+ array_state = TRUE;
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ /*
+ * Set the Name property.
+ */
+ case CURLFORM_PTRNAME:
+#ifdef CURL_DOES_CONVERSIONS
+ /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
+ * the data in all cases so that we'll have safe memory for the eventual
+ * conversion.
+ */
+#else
+ current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
+#endif
+ case CURLFORM_COPYNAME:
+ if(current_form->name)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *name = array_state?
+ array_value:va_arg(params, char *);
+ if(name)
+ current_form->name = name; /* store for the moment */
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ case CURLFORM_NAMELENGTH:
+ if(current_form->namelength)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->namelength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ /*
+ * Set the contents property.
+ */
+ case CURLFORM_PTRCONTENTS:
+ current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
+ case CURLFORM_COPYCONTENTS:
+ if(current_form->value)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *value =
+ array_state?array_value:va_arg(params, char *);
+ if(value)
+ current_form->value = value; /* store for the moment */
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ case CURLFORM_CONTENTSLENGTH:
+ if(current_form->contentslength)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->contentslength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ /* Get contents from a given file name */
+ case CURLFORM_FILECONTENT:
+ if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ const char *filename = array_state?
+ array_value:va_arg(params, char *);
+ if(filename) {
+ current_form->value = strdup(filename);
+ if(!current_form->value)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ current_form->flags |= HTTPPOST_READFILE;
+ current_form->value_alloc = TRUE;
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ /* We upload a file */
+ case CURLFORM_FILE:
+ {
+ const char *filename = array_state?array_value:
+ va_arg(params, char *);
+
+ if(current_form->value) {
+ if(current_form->flags & HTTPPOST_FILENAME) {
+ if(filename) {
+ char *fname = strdup(filename);
+ if(!fname)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ form = AddFormInfo(fname, NULL, current_form);
+ if(!form) {
+ free(fname);
+ return_value = CURL_FORMADD_MEMORY;
+ }
+ else {
+ form->value_alloc = TRUE;
+ current_form = form;
+ form = NULL;
+ }
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ else
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ }
+ else {
+ if(filename) {
+ current_form->value = strdup(filename);
+ if(!current_form->value)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ current_form->flags |= HTTPPOST_FILENAME;
+ current_form->value_alloc = TRUE;
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ }
+
+ case CURLFORM_BUFFERPTR:
+ current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
+ if(current_form->buffer)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *buffer =
+ array_state?array_value:va_arg(params, char *);
+ if(buffer) {
+ current_form->buffer = buffer; /* store for the moment */
+ current_form->value = buffer; /* make it non-NULL to be accepted
+ as fine */
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ case CURLFORM_BUFFERLENGTH:
+ if(current_form->bufferlength)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->bufferlength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ case CURLFORM_STREAM:
+ current_form->flags |= HTTPPOST_CALLBACK;
+ if(current_form->userp)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *userp =
+ array_state?array_value:va_arg(params, char *);
+ if(userp) {
+ current_form->userp = userp;
+ current_form->value = userp; /* this isn't strictly true but we
+ derive a value from this later on
+ and we need this non-NULL to be
+ accepted as a fine form part */
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ case CURLFORM_CONTENTTYPE:
+ {
+ const char *contenttype =
+ array_state?array_value:va_arg(params, char *);
+ if(current_form->contenttype) {
+ if(current_form->flags & HTTPPOST_FILENAME) {
+ if(contenttype) {
+ char *type = strdup(contenttype);
+ if(!type)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ form = AddFormInfo(NULL, type, current_form);
+ if(!form) {
+ free(type);
+ return_value = CURL_FORMADD_MEMORY;
+ }
+ else {
+ form->contenttype_alloc = TRUE;
+ current_form = form;
+ form = NULL;
+ }
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ else
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ }
+ else {
+ if(contenttype) {
+ current_form->contenttype = strdup(contenttype);
+ if(!current_form->contenttype)
+ return_value = CURL_FORMADD_MEMORY;
+ else
+ current_form->contenttype_alloc = TRUE;
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ }
+ case CURLFORM_CONTENTHEADER:
+ {
+ /* this "cast increases required alignment of target type" but
+ we consider it OK anyway */
+ struct curl_slist* list = array_state?
+ (struct curl_slist*)array_value:
+ va_arg(params, struct curl_slist*);
+
+ if(current_form->contentheader)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->contentheader = list;
+
+ break;
+ }
+ case CURLFORM_FILENAME:
+ case CURLFORM_BUFFER:
+ {
+ const char *filename = array_state?array_value:
+ va_arg(params, char *);
+ if(current_form->showfilename)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ current_form->showfilename = strdup(filename);
+ if(!current_form->showfilename)
+ return_value = CURL_FORMADD_MEMORY;
+ else
+ current_form->showfilename_alloc = TRUE;
+ }
+ break;
+ }
+ default:
+ return_value = CURL_FORMADD_UNKNOWN_OPTION;
+ break;
+ }
+ }
+
+ if(CURL_FORMADD_OK != return_value) {
+ /* On error, free allocated fields for all nodes of the FormInfo linked
+ list without deallocating nodes. List nodes are deallocated later on */
+ FormInfo *ptr;
+ for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
+ if(ptr->name_alloc) {
+ Curl_safefree(ptr->name);
+ ptr->name_alloc = FALSE;
+ }
+ if(ptr->value_alloc) {
+ Curl_safefree(ptr->value);
+ ptr->value_alloc = FALSE;
+ }
+ if(ptr->contenttype_alloc) {
+ Curl_safefree(ptr->contenttype);
+ ptr->contenttype_alloc = FALSE;
+ }
+ if(ptr->showfilename_alloc) {
+ Curl_safefree(ptr->showfilename);
+ ptr->showfilename_alloc = FALSE;
+ }
+ }
+ }
+
+ if(CURL_FORMADD_OK == return_value) {
+ /* go through the list, check for completeness and if everything is
+ * alright add the HttpPost item otherwise set return_value accordingly */
+
+ post = NULL;
+ for(form = first_form;
+ form != NULL;
+ form = form->more) {
+ if(((!form->name || !form->value) && !post) ||
+ ( (form->contentslength) &&
+ (form->flags & HTTPPOST_FILENAME) ) ||
+ ( (form->flags & HTTPPOST_FILENAME) &&
+ (form->flags & HTTPPOST_PTRCONTENTS) ) ||
+
+ ( (!form->buffer) &&
+ (form->flags & HTTPPOST_BUFFER) &&
+ (form->flags & HTTPPOST_PTRBUFFER) ) ||
+
+ ( (form->flags & HTTPPOST_READFILE) &&
+ (form->flags & HTTPPOST_PTRCONTENTS) )
+ ) {
+ return_value = CURL_FORMADD_INCOMPLETE;
+ break;
+ }
+ else {
+ if(((form->flags & HTTPPOST_FILENAME) ||
+ (form->flags & HTTPPOST_BUFFER)) &&
+ !form->contenttype ) {
+ char *f = form->flags & HTTPPOST_BUFFER?
+ form->showfilename : form->value;
+
+ /* our contenttype is missing */
+ form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
+ if(!form->contenttype) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+ form->contenttype_alloc = TRUE;
+ }
+ if(!(form->flags & HTTPPOST_PTRNAME) &&
+ (form == first_form) ) {
+ /* Note that there's small risk that form->name is NULL here if the
+ app passed in a bad combo, so we better check for that first. */
+ if(form->name) {
+ /* copy name (without strdup; possibly contains null characters) */
+ form->name = Curl_memdup(form->name, form->namelength?
+ form->namelength:
+ strlen(form->name)+1);
+ }
+ if(!form->name) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+ form->name_alloc = TRUE;
+ }
+ if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
+ HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
+ HTTPPOST_CALLBACK)) && form->value) {
+ /* copy value (without strdup; possibly contains null characters) */
+ form->value = Curl_memdup(form->value, form->contentslength?
+ form->contentslength:
+ strlen(form->value)+1);
+ if(!form->value) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+ form->value_alloc = TRUE;
+ }
+ post = AddHttpPost(form->name, form->namelength,
+ form->value, form->contentslength,
+ form->buffer, form->bufferlength,
+ form->contenttype, form->flags,
+ form->contentheader, form->showfilename,
+ form->userp,
+ post, httppost,
+ last_post);
+
+ if(!post) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+
+ if(form->contenttype)
+ prevtype = form->contenttype;
+ }
+ }
+ if(CURL_FORMADD_OK != return_value) {
+ /* On error, free allocated fields for nodes of the FormInfo linked
+ list which are not already owned by the httppost linked list
+ without deallocating nodes. List nodes are deallocated later on */
+ FormInfo *ptr;
+ for(ptr = form; ptr != NULL; ptr = ptr->more) {
+ if(ptr->name_alloc) {
+ Curl_safefree(ptr->name);
+ ptr->name_alloc = FALSE;
+ }
+ if(ptr->value_alloc) {
+ Curl_safefree(ptr->value);
+ ptr->value_alloc = FALSE;
+ }
+ if(ptr->contenttype_alloc) {
+ Curl_safefree(ptr->contenttype);
+ ptr->contenttype_alloc = FALSE;
+ }
+ if(ptr->showfilename_alloc) {
+ Curl_safefree(ptr->showfilename);
+ ptr->showfilename_alloc = FALSE;
+ }
+ }
+ }
+ }
+
+ /* Always deallocate FormInfo linked list nodes without touching node
+ fields given that these have either been deallocated or are owned
+ now by the httppost linked list */
+ while(first_form) {
+ FormInfo *ptr = first_form->more;
+ free(first_form);
+ first_form = ptr;
+ }
+
+ return return_value;
+}
+
+/*
+ * curl_formadd() is a public API to add a section to the multipart formpost.
+ *
+ * @unittest: 1308
+ */
+
+CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...)
+{
+ va_list arg;
+ CURLFORMcode result;
+ va_start(arg, last_post);
+ result = FormAdd(httppost, last_post, arg);
+ va_end(arg);
+ return result;
+}
+
+#ifdef __VMS
+#include <fabdef.h>
+/*
+ * get_vms_file_size does what it takes to get the real size of the file
+ *
+ * For fixed files, find out the size of the EOF block and adjust.
+ *
+ * For all others, have to read the entire file in, discarding the contents.
+ * Most posted text files will be small, and binary files like zlib archives
+ * and CD/DVD images should be either a STREAM_LF format or a fixed format.
+ *
+ */
+curl_off_t VmsRealFileSize(const char * name,
+ const struct_stat * stat_buf)
+{
+ char buffer[8192];
+ curl_off_t count;
+ int ret_stat;
+ FILE * file;
+
+ file = fopen(name, "r");
+ if(file == NULL)
+ return 0;
+
+ count = 0;
+ ret_stat = 1;
+ while(ret_stat > 0) {
+ ret_stat = fread(buffer, 1, sizeof(buffer), file);
+ if(ret_stat != 0)
+ count += ret_stat;
+ }
+ fclose(file);
+
+ return count;
+}
+
+/*
+ *
+ * VmsSpecialSize checks to see if the stat st_size can be trusted and
+ * if not to call a routine to get the correct size.
+ *
+ */
+static curl_off_t VmsSpecialSize(const char * name,
+ const struct_stat * stat_buf)
+{
+ switch(stat_buf->st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ return VmsRealFileSize(name, stat_buf);
+ break;
+ default:
+ return stat_buf->st_size;
+ }
+}
+
+#endif
+
+#ifndef __VMS
+#define filesize(name, stat_data) (stat_data.st_size)
+#else
+ /* Getting the expected file size needs help on VMS */
+#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
+#endif
+
+/*
+ * AddFormData() adds a chunk of data to the FormData linked list.
+ *
+ * size is incremented by the chunk length, unless it is NULL
+ */
+static CURLcode AddFormData(struct FormData **formp,
+ enum formtype type,
+ const void *line,
+ size_t length,
+ curl_off_t *size)
+{
+ struct FormData *newform = malloc(sizeof(struct FormData));
+ if(!newform)
+ return CURLE_OUT_OF_MEMORY;
+ newform->next = NULL;
+
+ if(type <= FORM_CONTENT) {
+ /* we make it easier for plain strings: */
+ if(!length)
+ length = strlen((char *)line);
+
+ newform->line = malloc(length+1);
+ if(!newform->line) {
+ free(newform);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(newform->line, line, length);
+ newform->length = length;
+ newform->line[length]=0; /* zero terminate for easier debugging */
+ }
+ else
+ /* For callbacks and files we don't have any actual data so we just keep a
+ pointer to whatever this points to */
+ newform->line = (char *)line;
+
+ newform->type = type;
+
+ if(*formp) {
+ (*formp)->next = newform;
+ *formp = newform;
+ }
+ else
+ *formp = newform;
+
+ if(size) {
+ if(type != FORM_FILE)
+ /* for static content as well as callback data we add the size given
+ as input argument */
+ *size += length;
+ else {
+ /* Since this is a file to be uploaded here, add the size of the actual
+ file */
+ if(!strequal("-", newform->line)) {
+ struct_stat file;
+ if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
+ *size += filesize(newform->line, file);
+ else
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+ }
+ return CURLE_OK;
+}
+
+/*
+ * AddFormDataf() adds printf()-style formatted data to the formdata chain.
+ */
+
+static CURLcode AddFormDataf(struct FormData **formp,
+ curl_off_t *size,
+ const char *fmt, ...)
+{
+ char s[4096];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(s, sizeof(s), fmt, ap);
+ va_end(ap);
+
+ return AddFormData(formp, FORM_DATA, s, 0, size);
+}
+
+/*
+ * Curl_formclean() is used from http.c, this cleans a built FormData linked
+ * list
+ */
+CURL_STATIC void Curl_formclean(struct FormData **form_ptr)
+{
+ struct FormData *next, *form;
+
+ form = *form_ptr;
+ if(!form)
+ return;
+
+ do {
+ next=form->next; /* the following form line */
+ if(form->type <= FORM_CONTENT)
+ free(form->line); /* free the line */
+ free(form); /* free the struct */
+
+ } while((form = next) != NULL); /* continue */
+
+ *form_ptr = NULL;
+}
+
+/*
+ * curl_formget()
+ * Serialize a curl_httppost struct.
+ * Returns 0 on success.
+ *
+ * @unittest: 1308
+ */
+int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append)
+{
+ CURLcode result;
+ curl_off_t size;
+ struct FormData *data, *ptr;
+
+ result = Curl_getformdata(NULL, &data, form, NULL, &size);
+ if(result)
+ return (int)result;
+
+ for(ptr = data; ptr; ptr = ptr->next) {
+ if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
+ char buffer[8192];
+ size_t nread;
+ struct Form temp;
+
+ Curl_FormInit(&temp, ptr);
+
+ do {
+ nread = readfromfile(&temp, buffer, sizeof(buffer));
+ if((nread == (size_t) -1) ||
+ (nread > sizeof(buffer)) ||
+ (nread != append(arg, buffer, nread))) {
+ if(temp.fp)
+ fclose(temp.fp);
+ Curl_formclean(&data);
+ return -1;
+ }
+ } while(nread);
+ }
+ else {
+ if(ptr->length != append(arg, ptr->line, ptr->length)) {
+ Curl_formclean(&data);
+ return -1;
+ }
+ }
+ }
+ Curl_formclean(&data);
+ return 0;
+}
+
+/*
+ * curl_formfree() is an external function to free up a whole form post
+ * chain
+ */
+void curl_formfree(struct curl_httppost *form)
+{
+ struct curl_httppost *next;
+
+ if(!form)
+ /* no form to free, just get out of this */
+ return;
+
+ do {
+ next=form->next; /* the following form line */
+
+ /* recurse to sub-contents */
+ curl_formfree(form->more);
+
+ if(!(form->flags & HTTPPOST_PTRNAME))
+ free(form->name); /* free the name */
+ if(!(form->flags &
+ (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
+ )
+ free(form->contents); /* free the contents */
+ free(form->contenttype); /* free the content type */
+ free(form->showfilename); /* free the faked file name */
+ free(form); /* free the struct */
+
+ } while((form = next) != NULL); /* continue */
+}
+
+#ifndef HAVE_BASENAME
+/*
+ (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
+ Edition)
+
+ The basename() function shall take the pathname pointed to by path and
+ return a pointer to the final component of the pathname, deleting any
+ trailing '/' characters.
+
+ If the string pointed to by path consists entirely of the '/' character,
+ basename() shall return a pointer to the string "/". If the string pointed
+ to by path is exactly "//", it is implementation-defined whether '/' or "//"
+ is returned.
+
+ If path is a null pointer or points to an empty string, basename() shall
+ return a pointer to the string ".".
+
+ The basename() function may modify the string pointed to by path, and may
+ return a pointer to static storage that may then be overwritten by a
+ subsequent call to basename().
+
+ The basename() function need not be reentrant. A function that is not
+ required to be reentrant is not required to be thread-safe.
+
+*/
+static char *Curl_basename(char *path)
+{
+ /* Ignore all the details above for now and make a quick and simple
+ implementaion here */
+ char *s1;
+ char *s2;
+
+ s1=strrchr(path, '/');
+ s2=strrchr(path, '\\');
+
+ if(s1 && s2) {
+ path = (s1 > s2? s1 : s2)+1;
+ }
+ else if(s1)
+ path = s1 + 1;
+ else if(s2)
+ path = s2 + 1;
+
+ return path;
+}
+#endif
+
+static char *strippath(const char *fullfile)
+{
+ char *filename;
+ char *base;
+ filename = strdup(fullfile); /* duplicate since basename() may ruin the
+ buffer it works on */
+ if(!filename)
+ return NULL;
+ base = strdup(basename(filename));
+
+ free(filename); /* free temporary buffer */
+
+ return base; /* returns an allocated string or NULL ! */
+}
+
+static CURLcode formdata_add_filename(const struct curl_httppost *file,
+ struct FormData **form,
+ curl_off_t *size)
+{
+ CURLcode result = CURLE_OK;
+ char *filename = file->showfilename;
+ char *filebasename = NULL;
+ char *filename_escaped = NULL;
+
+ if(!filename) {
+ filebasename = strippath(file->contents);
+ if(!filebasename)
+ return CURLE_OUT_OF_MEMORY;
+ filename = filebasename;
+ }
+
+ if(strchr(filename, '\\') || strchr(filename, '"')) {
+ char *p0, *p1;
+
+ /* filename need be escaped */
+ filename_escaped = malloc(strlen(filename)*2+1);
+ if(!filename_escaped) {
+ free(filebasename);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ p0 = filename_escaped;
+ p1 = filename;
+ while(*p1) {
+ if(*p1 == '\\' || *p1 == '"')
+ *p0++ = '\\';
+ *p0++ = *p1++;
+ }
+ *p0 = '\0';
+ filename = filename_escaped;
+ }
+ result = AddFormDataf(form, size,
+ "; filename=\"%s\"",
+ filename);
+ free(filename_escaped);
+ free(filebasename);
+ return result;
+}
+
+/*
+ * Curl_getformdata() converts a linked list of "meta data" into a complete
+ * (possibly huge) multipart formdata. The input list is in 'post', while the
+ * output resulting linked lists gets stored in '*finalform'. *sizep will get
+ * the total size of the whole POST.
+ * A multipart/form_data content-type is built, unless a custom content-type
+ * is passed in 'custom_content_type'.
+ *
+ * This function will not do a failf() for the potential memory failures but
+ * should for all other errors it spots. Just note that this function MAY get
+ * a NULL pointer in the 'data' argument.
+ */
+
+CURL_STATIC CURLcode Curl_getformdata(struct SessionHandle *data,
+ struct FormData **finalform,
+ struct curl_httppost *post,
+ const char *custom_content_type,
+ curl_off_t *sizep)
+{
+ struct FormData *form = NULL;
+ struct FormData *firstform;
+ struct curl_httppost *file;
+ CURLcode result = CURLE_OK;
+
+ curl_off_t size = 0; /* support potentially ENORMOUS formposts */
+ char *boundary;
+ char *fileboundary = NULL;
+ struct curl_slist* curList;
+
+ *finalform = NULL; /* default form is empty */
+
+ if(!post)
+ return result; /* no input => no output! */
+
+ boundary = formboundary(data);
+ if(!boundary)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Make the first line of the output */
+ result = AddFormDataf(&form, NULL,
+ "%s; boundary=%s\r\n",
+ custom_content_type?custom_content_type:
+ "Content-Type: multipart/form-data",
+ boundary);
+
+ if(result) {
+ free(boundary);
+ return result;
+ }
+ /* we DO NOT include that line in the total size of the POST, since it'll be
+ part of the header! */
+
+ firstform = form;
+
+ do {
+
+ if(size) {
+ result = AddFormDataf(&form, &size, "\r\n");
+ if(result)
+ break;
+ }
+
+ /* boundary */
+ result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
+ if(result)
+ break;
+
+ /* Maybe later this should be disabled when a custom_content_type is
+ passed, since Content-Disposition is not meaningful for all multipart
+ types.
+ */
+ result = AddFormDataf(&form, &size,
+ "Content-Disposition: form-data; name=\"");
+ if(result)
+ break;
+
+ result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
+ &size);
+ if(result)
+ break;
+
+ result = AddFormDataf(&form, &size, "\"");
+ if(result)
+ break;
+
+ if(post->more) {
+ /* If used, this is a link to more file names, we must then do
+ the magic to include several files with the same field name */
+
+ free(fileboundary);
+ fileboundary = formboundary(data);
+ if(!fileboundary) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ result = AddFormDataf(&form, &size,
+ "\r\nContent-Type: multipart/mixed;"
+ " boundary=%s\r\n",
+ fileboundary);
+ if(result)
+ break;
+ }
+
+ file = post;
+
+ do {
+
+ /* If 'showfilename' is set, that is a faked name passed on to us
+ to use to in the formpost. If that is not set, the actually used
+ local file name should be added. */
+
+ if(post->more) {
+ /* if multiple-file */
+ result = AddFormDataf(&form, &size,
+ "\r\n--%s\r\nContent-Disposition: "
+ "attachment",
+ fileboundary);
+ if(result)
+ break;
+ result = formdata_add_filename(file, &form, &size);
+ if(result)
+ break;
+ }
+ else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
+ HTTPPOST_CALLBACK)) {
+ /* it should be noted that for the HTTPPOST_FILENAME and
+ HTTPPOST_CALLBACK cases the ->showfilename struct member is always
+ assigned at this point */
+ if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
+ result = formdata_add_filename(post, &form, &size);
+ }
+
+ if(result)
+ break;
+ }
+
+ if(file->contenttype) {
+ /* we have a specified type */
+ result = AddFormDataf(&form, &size,
+ "\r\nContent-Type: %s",
+ file->contenttype);
+ if(result)
+ break;
+ }
+
+ curList = file->contentheader;
+ while(curList) {
+ /* Process the additional headers specified for this form */
+ result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
+ if(result)
+ break;
+ curList = curList->next;
+ }
+ if(result)
+ break;
+
+ result = AddFormDataf(&form, &size, "\r\n\r\n");
+ if(result)
+ break;
+
+ if((post->flags & HTTPPOST_FILENAME) ||
+ (post->flags & HTTPPOST_READFILE)) {
+ /* we should include the contents from the specified file */
+ FILE *fileread;
+
+ fileread = strequal("-", file->contents)?
+ stdin:fopen(file->contents, "rb"); /* binary read for win32 */
+
+ /*
+ * VMS: This only allows for stream files on VMS. Stream files are
+ * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
+ * every record needs to have a \n appended & 1 added to SIZE
+ */
+
+ if(fileread) {
+ if(fileread != stdin) {
+ /* close the file */
+ fclose(fileread);
+ /* add the file name only - for later reading from this */
+ result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
+ }
+ else {
+ /* When uploading from stdin, we can't know the size of the file,
+ * thus must read the full file as before. We *could* use chunked
+ * transfer-encoding, but that only works for HTTP 1.1 and we
+ * can't be sure we work with such a server.
+ */
+ size_t nread;
+ char buffer[512];
+ while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
+ result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
+ if(result)
+ break;
+ }
+ }
+ }
+ else {
+ if(data)
+ failf(data, "couldn't open file \"%s\"", file->contents);
+ *finalform = NULL;
+ result = CURLE_READ_ERROR;
+ }
+ }
+ else if(post->flags & HTTPPOST_BUFFER)
+ /* include contents of buffer */
+ result = AddFormData(&form, FORM_CONTENT, post->buffer,
+ post->bufferlength, &size);
+ else if(post->flags & HTTPPOST_CALLBACK)
+ /* the contents should be read with the callback and the size
+ is set with the contentslength */
+ result = AddFormData(&form, FORM_CALLBACK, post->userp,
+ post->contentslength, &size);
+ else
+ /* include the contents we got */
+ result = AddFormData(&form, FORM_CONTENT, post->contents,
+ post->contentslength, &size);
+
+ file = file->more;
+ } while(file && !result); /* for each specified file for this field */
+
+ if(result)
+ break;
+
+ if(post->more) {
+ /* this was a multiple-file inclusion, make a termination file
+ boundary: */
+ result = AddFormDataf(&form, &size,
+ "\r\n--%s--",
+ fileboundary);
+ if(result)
+ break;
+ }
+
+ } while((post = post->next) != NULL); /* for each field */
+
+ /* end-boundary for everything */
+ if(!result)
+ result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
+
+ if(result) {
+ Curl_formclean(&firstform);
+ free(fileboundary);
+ free(boundary);
+ return result;
+ }
+
+ *sizep = size;
+
+ free(fileboundary);
+ free(boundary);
+
+ *finalform = firstform;
+
+ return result;
+}
+
+/*
+ * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
+ * and resets the 'sent' counter.
+ */
+CURL_STATIC int Curl_FormInit(struct Form *form, struct FormData *formdata )
+{
+ if(!formdata)
+ return 1; /* error */
+
+ form->data = formdata;
+ form->sent = 0;
+ form->fp = NULL;
+ form->fread_func = ZERO_NULL;
+
+ return 0;
+}
+
+#ifndef __VMS
+# define fopen_read fopen
+#else
+ /*
+ * vmsfopenread
+ *
+ * For upload to work as expected on VMS, different optional
+ * parameters must be added to the fopen command based on
+ * record format of the file.
+ *
+ */
+# define fopen_read vmsfopenread
+static FILE * vmsfopenread(const char *file, const char *mode) {
+ struct_stat statbuf;
+ int result;
+
+ result = stat(file, &statbuf);
+
+ switch (statbuf.st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ case FAB$C_STMCR:
+ return fopen(file, "r");
+ break;
+ default:
+ return fopen(file, "r", "rfm=stmlf", "ctx=stm");
+ }
+}
+#endif
+
+/*
+ * readfromfile()
+ *
+ * The read callback that this function may use can return a value larger than
+ * 'size' (which then this function returns) that indicates a problem and it
+ * must be properly dealt with
+ */
+static size_t readfromfile(struct Form *form, char *buffer,
+ size_t size)
+{
+ size_t nread;
+ bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
+
+ if(callback) {
+ if(form->fread_func == ZERO_NULL)
+ return 0;
+ else
+ nread = form->fread_func(buffer, 1, size, form->data->line);
+ }
+ else {
+ if(!form->fp) {
+ /* this file hasn't yet been opened */
+ form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
+ if(!form->fp)
+ return (size_t)-1; /* failure */
+ }
+ nread = fread(buffer, 1, size, form->fp);
+ }
+ if(!nread) {
+ /* this is the last chunk from the file, move on */
+ if(form->fp) {
+ fclose(form->fp);
+ form->fp = NULL;
+ }
+ form->data = form->data->next;
+ }
+
+ return nread;
+}
+
+/*
+ * Curl_FormReader() is the fread() emulation function that will be used to
+ * deliver the formdata to the transfer loop and then sent away to the peer.
+ */
+CURL_STATIC size_t Curl_FormReader(char *buffer,
+ size_t size,
+ size_t nitems,
+ FILE *mydata)
+{
+ struct Form *form;
+ size_t wantedsize;
+ size_t gotsize = 0;
+
+ form=(struct Form *)mydata;
+
+ wantedsize = size * nitems;
+
+ if(!form->data)
+ return 0; /* nothing, error, empty */
+
+ if((form->data->type == FORM_FILE) ||
+ (form->data->type == FORM_CALLBACK)) {
+ gotsize = readfromfile(form, buffer, wantedsize);
+
+ if(gotsize)
+ /* If positive or -1, return. If zero, continue! */
+ return gotsize;
+ }
+ do {
+
+ if((form->data->length - form->sent ) > wantedsize - gotsize) {
+
+ memcpy(buffer + gotsize , form->data->line + form->sent,
+ wantedsize - gotsize);
+
+ form->sent += wantedsize-gotsize;
+
+ return wantedsize;
+ }
+
+ memcpy(buffer+gotsize,
+ form->data->line + form->sent,
+ (form->data->length - form->sent) );
+ gotsize += form->data->length - form->sent;
+
+ form->sent = 0;
+
+ form->data = form->data->next; /* advance */
+
+ } while(form->data && (form->data->type < FORM_CALLBACK));
+ /* If we got an empty line and we have more data, we proceed to the next
+ line immediately to avoid returning zero before we've reached the end. */
+
+ return gotsize;
+}
+
+/*
+ * Curl_formpostheader() returns the first line of the formpost, the
+ * request-header part (which is not part of the request-body like the rest of
+ * the post).
+ */
+CURL_STATIC char *Curl_formpostheader(void *formp, size_t *len)
+{
+ char *header;
+ struct Form *form=(struct Form *)formp;
+
+ if(!form->data)
+ return 0; /* nothing, ERROR! */
+
+ header = form->data->line;
+ *len = form->data->length;
+
+ form->data = form->data->next; /* advance */
+
+ return header;
+}
+
+/*
+ * formboundary() creates a suitable boundary string and returns an allocated
+ * one.
+ */
+static char *formboundary(struct SessionHandle *data)
+{
+ /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
+ combinations */
+ return aprintf("------------------------%08x%08x",
+ Curl_rand(data), Curl_rand(data));
+}
+
+#else /* CURL_DISABLE_HTTP */
+CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...)
+{
+ (void)httppost;
+ (void)last_post;
+ return CURL_FORMADD_DISABLED;
+}
+
+int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append)
+{
+ (void) form;
+ (void) arg;
+ (void) append;
+ return CURL_FORMADD_DISABLED;
+}
+
+void curl_formfree(struct curl_httppost *form)
+{
+ (void)form;
+ /* does nothing HTTP is disabled */
+}
+
+
+#endif /* !defined(CURL_DISABLE_HTTP) */
diff --git a/libcurl/src/lib/formdata.h b/libcurl/src/lib/formdata.h
new file mode 100644
index 0000000..25480f1
--- /dev/null
+++ b/libcurl/src/lib/formdata.h
@@ -0,0 +1,98 @@
+#ifndef HEADER_CURL_FORMDATA_H
+#define HEADER_CURL_FORMDATA_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+enum formtype {
+ FORM_DATA, /* form metadata (convert to network encoding if necessary) */
+ FORM_CONTENT, /* form content (never convert) */
+ FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback
+ */
+ FORM_FILE /* 'line' points to a file name we should read from
+ to create the form data (never convert) */
+};
+
+/* plain and simple linked list with lines to send */
+struct FormData {
+ struct FormData *next;
+ enum formtype type;
+ char *line;
+ size_t length;
+};
+
+struct Form {
+ struct FormData *data; /* current form line to send */
+ size_t sent; /* number of bytes of the current line that has
+ already been sent in a previous invoke */
+ FILE *fp; /* file to read from */
+ curl_read_callback fread_func; /* fread callback pointer */
+};
+
+/* used by FormAdd for temporary storage */
+typedef struct FormInfo {
+ char *name;
+ bool name_alloc;
+ size_t namelength;
+ char *value;
+ bool value_alloc;
+ size_t contentslength;
+ char *contenttype;
+ bool contenttype_alloc;
+ long flags;
+ char *buffer; /* pointer to existing buffer used for file upload */
+ size_t bufferlength;
+ char *showfilename; /* The file name to show. If not set, the actual
+ file name will be used */
+ bool showfilename_alloc;
+ char *userp; /* pointer for the read callback */
+ struct curl_slist* contentheader;
+ struct FormInfo *more;
+} FormInfo;
+
+CURL_STATIC int Curl_FormInit(struct Form *form, struct FormData *formdata );
+
+CURL_STATIC CURLcode Curl_getformdata(struct SessionHandle *data,
+ struct FormData **,
+ struct curl_httppost *post,
+ const char *custom_contenttype,
+ curl_off_t *size);
+
+/* fread() emulation */
+CURL_STATIC size_t Curl_FormReader(char *buffer,
+ size_t size,
+ size_t nitems,
+ FILE *mydata);
+
+/*
+ * Curl_formpostheader() returns the first line of the formpost, the
+ * request-header part (which is not part of the request-body like the rest of
+ * the post).
+ */
+CURL_STATIC char *Curl_formpostheader(void *formp, size_t *len);
+
+CURL_STATIC char *Curl_FormBoundary(void);
+
+CURL_STATIC void Curl_formclean(struct FormData **);
+
+CURL_STATIC CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *);
+
+#endif /* HEADER_CURL_FORMDATA_H */
diff --git a/libcurl/src/lib/ftp.c b/libcurl/src/lib/ftp.c
new file mode 100644
index 0000000..527d209
--- /dev/null
+++ b/libcurl/src/lib/ftp.c
@@ -0,0 +1,4586 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "ftp.h"
+#include "fileinfo.h"
+#include "ftplistparser.h"
+#include "curl_sec.h"
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "inet_ntop.h"
+#include "inet_pton.h"
+#include "select.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "speedcheck.h"
+#include "warnless.h"
+#include "http_proxy.h"
+#include "non-ascii.h"
+#include "curl_printf.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#endif
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt
+#endif
+
+/* Local API functions */
+#ifndef DEBUGBUILD
+static void _state(struct connectdata *conn,
+ ftpstate newstate);
+#define state(x,y) _state(x,y)
+#else
+static void _state(struct connectdata *conn,
+ ftpstate newstate,
+ int lineno);
+#define state(x,y) _state(x,y,__LINE__)
+#endif
+
+static CURLcode ftp_sendquote(struct connectdata *conn,
+ struct curl_slist *quote);
+static CURLcode ftp_quit(struct connectdata *conn);
+static CURLcode ftp_parse_url_path(struct connectdata *conn);
+static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void ftp_pasv_verbose(struct connectdata *conn,
+ Curl_addrinfo *ai,
+ char *newhost, /* ascii version */
+ int port);
+#endif
+static CURLcode ftp_state_prepare_transfer(struct connectdata *conn);
+static CURLcode ftp_state_mdtm(struct connectdata *conn);
+static CURLcode ftp_state_quote(struct connectdata *conn,
+ bool init, ftpstate instate);
+static CURLcode ftp_nb_type(struct connectdata *conn,
+ bool ascii, ftpstate newstate);
+static int ftp_need_type(struct connectdata *conn,
+ bool ascii);
+static CURLcode ftp_do(struct connectdata *conn, bool *done);
+static CURLcode ftp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode ftp_connect(struct connectdata *conn, bool *done);
+static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
+static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
+static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
+static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode ftp_doing(struct connectdata *conn,
+ bool *dophase_done);
+static CURLcode ftp_setup_connection(struct connectdata * conn);
+
+static CURLcode init_wc_data(struct connectdata *conn);
+static CURLcode wc_statemach(struct connectdata *conn);
+
+static void wc_data_dtor(void *ptr);
+
+static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
+
+static CURLcode ftp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *ftpcode,
+ size_t *size);
+static CURLcode ftp_dophase_done(struct connectdata *conn,
+ bool connected);
+
+/* easy-to-use macro: */
+#define PPSENDF(x,y,z) if((result = Curl_pp_sendf(x,y,z))) \
+ return result
+
+
+/*
+ * FTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftp = {
+ "FTP", /* scheme */
+ ftp_setup_connection, /* setup_connection */
+ ftp_do, /* do_it */
+ ftp_done, /* done */
+ ftp_do_more, /* do_more */
+ ftp_connect, /* connect_it */
+ ftp_multi_statemach, /* connecting */
+ ftp_doing, /* doing */
+ ftp_getsock, /* proto_getsock */
+ ftp_getsock, /* doing_getsock */
+ ftp_domore_getsock, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTP, /* defport */
+ CURLPROTO_FTP, /* protocol */
+ PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD
+ | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+#ifdef USE_SSL
+/*
+ * FTPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftps = {
+ "FTPS", /* scheme */
+ ftp_setup_connection, /* setup_connection */
+ ftp_do, /* do_it */
+ ftp_done, /* done */
+ ftp_do_more, /* do_more */
+ ftp_connect, /* connect_it */
+ ftp_multi_statemach, /* connecting */
+ ftp_doing, /* doing */
+ ftp_getsock, /* proto_getsock */
+ ftp_getsock, /* doing_getsock */
+ ftp_domore_getsock, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTPS, /* defport */
+ CURLPROTO_FTPS, /* protocol */
+ PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
+ PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed FTP protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_ftp_proxy = {
+ "FTP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed FTPS protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_ftps_proxy = {
+ "FTPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTPS, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+
+/*
+ * NOTE: back in the old days, we added code in the FTP code that made NOBODY
+ * requests on files respond with headers passed to the client/stdout that
+ * looked like HTTP ones.
+ *
+ * This approach is not very elegant, it causes confusion and is error-prone.
+ * It is subject for removal at the next (or at least a future) soname bump.
+ * Until then you can test the effects of the removal by undefining the
+ * following define named CURL_FTP_HTTPSTYLE_HEAD.
+ */
+#define CURL_FTP_HTTPSTYLE_HEAD 1
+
+static void freedirs(struct ftp_conn *ftpc)
+{
+ int i;
+ if(ftpc->dirs) {
+ for(i=0; i < ftpc->dirdepth; i++) {
+ free(ftpc->dirs[i]);
+ ftpc->dirs[i]=NULL;
+ }
+ free(ftpc->dirs);
+ ftpc->dirs = NULL;
+ ftpc->dirdepth = 0;
+ }
+ Curl_safefree(ftpc->file);
+
+ /* no longer of any use */
+ Curl_safefree(ftpc->newhost);
+}
+
+/* Returns non-zero if the given string contains CR (\r) or LF (\n),
+ which are not allowed within RFC 959 <string>.
+ Note: The input string is in the client's encoding which might
+ not be ASCII, so escape sequences \r & \n must be used instead
+ of hex values 0x0d & 0x0a.
+*/
+static bool isBadFtpString(const char *string)
+{
+ return ((NULL != strchr(string, '\r')) ||
+ (NULL != strchr(string, '\n'))) ? TRUE : FALSE;
+}
+
+/***********************************************************************
+ *
+ * AcceptServerConnect()
+ *
+ * After connection request is received from the server this function is
+ * called to accept the connection and close the listening socket
+ *
+ */
+static CURLcode AcceptServerConnect(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sock = conn->sock[SECONDARYSOCKET];
+ curl_socket_t s = CURL_SOCKET_BAD;
+#ifdef ENABLE_IPV6
+ struct Curl_sockaddr_storage add;
+#else
+ struct sockaddr_in add;
+#endif
+ curl_socklen_t size = (curl_socklen_t) sizeof(add);
+
+ if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
+ size = sizeof(add);
+
+ s=accept(sock, (struct sockaddr *) &add, &size);
+ }
+ Curl_closesocket(conn, sock); /* close the first socket */
+
+ if(CURL_SOCKET_BAD == s) {
+ failf(data, "Error accept()ing server connect");
+ return CURLE_FTP_PORT_FAILED;
+ }
+ infof(data, "Connection accepted from server\n");
+
+ conn->sock[SECONDARYSOCKET] = s;
+ (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
+ conn->sock_accepted[SECONDARYSOCKET] = TRUE;
+
+ if(data->set.fsockopt) {
+ int error = 0;
+
+ /* activate callback for setting socket options */
+ error = data->set.fsockopt(data->set.sockopt_client,
+ s,
+ CURLSOCKTYPE_ACCEPT);
+
+ if(error) {
+ Curl_closesocket(conn, s); /* close the socket and bail out */
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ }
+
+ return CURLE_OK;
+
+}
+
+/*
+ * ftp_timeleft_accept() returns the amount of milliseconds left allowed for
+ * waiting server to connect. If the value is negative, the timeout time has
+ * already elapsed.
+ *
+ * The start time is stored in progress.t_acceptdata - as set with
+ * Curl_pgrsTime(..., TIMER_STARTACCEPT);
+ *
+ */
+static long ftp_timeleft_accept(struct SessionHandle *data)
+{
+ long timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
+ long other;
+ struct timeval now;
+
+ if(data->set.accepttimeout > 0)
+ timeout_ms = data->set.accepttimeout;
+
+ now = Curl_tvnow();
+
+ /* check if the generic timeout possibly is set shorter */
+ other = Curl_timeleft(data, &now, FALSE);
+ if(other && (other < timeout_ms))
+ /* note that this also works fine for when other happens to be negative
+ due to it already having elapsed */
+ timeout_ms = other;
+ else {
+ /* subtract elapsed time */
+ timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata);
+ if(!timeout_ms)
+ /* avoid returning 0 as that means no timeout! */
+ return -1;
+ }
+
+ return timeout_ms;
+}
+
+
+/***********************************************************************
+ *
+ * ReceivedServerConnect()
+ *
+ * After allowing server to connect to us from data port, this function
+ * checks both data connection for connection establishment and ctrl
+ * connection for a negative response regarding a failure in connecting
+ *
+ */
+static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
+ curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ int result;
+ long timeout_ms;
+ ssize_t nread;
+ int ftpcode;
+
+ *received = FALSE;
+
+ timeout_ms = ftp_timeleft_accept(data);
+ infof(data, "Checking for server connect\n");
+ if(timeout_ms < 0) {
+ /* if a timeout was already reached, bail out */
+ failf(data, "Accept timeout occurred while waiting server connect");
+ return CURLE_FTP_ACCEPT_TIMEOUT;
+ }
+
+ /* First check whether there is a cached response from server */
+ if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
+ /* Data connection could not be established, let's return */
+ infof(data, "There is negative response in cache while serv connect\n");
+ Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ return CURLE_FTP_ACCEPT_FAILED;
+ }
+
+ result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
+
+ /* see if the connection request is already here */
+ switch (result) {
+ case -1: /* error */
+ /* let's die here */
+ failf(data, "Error while waiting for server connect");
+ return CURLE_FTP_ACCEPT_FAILED;
+ case 0: /* Server connect is not received yet */
+ break; /* loop */
+ default:
+
+ if(result & CURL_CSELECT_IN2) {
+ infof(data, "Ready to accept data connection from server\n");
+ *received = TRUE;
+ }
+ else if(result & CURL_CSELECT_IN) {
+ infof(data, "Ctrl conn has data while waiting for data conn\n");
+ Curl_GetFTPResponse(&nread, conn, &ftpcode);
+
+ if(ftpcode/100 > 3)
+ return CURLE_FTP_ACCEPT_FAILED;
+
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+
+ break;
+ } /* switch() */
+
+ return CURLE_OK;
+}
+
+
+/***********************************************************************
+ *
+ * InitiateTransfer()
+ *
+ * After connection from server is accepted this function is called to
+ * setup transfer parameters and initiate the data transfer.
+ *
+ */
+static CURLcode InitiateTransfer(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ CURLcode result = CURLE_OK;
+
+ if(conn->ssl[SECONDARYSOCKET].use) {
+ /* since we only have a plaintext TCP connection here, we must now
+ * do the TLS stuff */
+ infof(data, "Doing the SSL/TLS handshake on the data stream\n");
+ result = Curl_ssl_connect(conn, SECONDARYSOCKET);
+ if(result)
+ return result;
+ }
+
+ if(conn->proto.ftpc.state_saved == FTP_STOR) {
+ *(ftp->bytecountp)=0;
+
+ /* When we know we're uploading a specified file, we can get the file
+ size prior to the actual upload. */
+
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* set the SO_SNDBUF for the secondary socket for those who need it */
+ Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
+
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
+ SECONDARYSOCKET, ftp->bytecountp);
+ }
+ else {
+ /* FTP download: */
+ Curl_setup_transfer(conn, SECONDARYSOCKET,
+ conn->proto.ftpc.retr_size_saved, FALSE,
+ ftp->bytecountp, -1, NULL); /* no upload here */
+ }
+
+ conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
+ state(conn, FTP_STOP);
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * AllowServerConnect()
+ *
+ * When we've issue the PORT command, we have told the server to connect to
+ * us. This function checks whether data connection is established if so it is
+ * accepted.
+ *
+ */
+static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
+{
+ struct SessionHandle *data = conn->data;
+ long timeout_ms;
+ CURLcode result = CURLE_OK;
+
+ *connected = FALSE;
+ infof(data, "Preparing for accepting server on data port\n");
+
+ /* Save the time we start accepting server connect */
+ Curl_pgrsTime(data, TIMER_STARTACCEPT);
+
+ timeout_ms = ftp_timeleft_accept(data);
+ if(timeout_ms < 0) {
+ /* if a timeout was already reached, bail out */
+ failf(data, "Accept timeout occurred while waiting server connect");
+ return CURLE_FTP_ACCEPT_TIMEOUT;
+ }
+
+ /* see if the connection request is already here */
+ result = ReceivedServerConnect(conn, connected);
+ if(result)
+ return result;
+
+ if(*connected) {
+ result = AcceptServerConnect(conn);
+ if(result)
+ return result;
+
+ result = InitiateTransfer(conn);
+ if(result)
+ return result;
+ }
+ else {
+ /* Add timeout to multi handle and break out of the loop */
+ if(!result && *connected == FALSE) {
+ if(data->set.accepttimeout > 0)
+ Curl_expire(data, data->set.accepttimeout);
+ else
+ Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
+ }
+ }
+
+ return result;
+}
+
+/* macro to check for a three-digit ftp status code at the start of the
+ given string */
+#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \
+ ISDIGIT(line[2]))
+
+/* macro to check for the last line in an FTP server response */
+#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
+
+static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *code)
+{
+ (void)conn;
+
+ if((len > 3) && LASTLINE(line)) {
+ *code = curlx_sltosi(strtol(line, NULL, 10));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static CURLcode ftp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *ftpcode, /* return the ftp-code if done */
+ size_t *size) /* size of the response */
+{
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data = conn->data;
+#ifdef HAVE_GSSAPI
+ char * const buf = data->state.buffer;
+#endif
+ CURLcode result = CURLE_OK;
+ int code;
+
+ result = Curl_pp_readresp(sockfd, pp, &code, size);
+
+#if defined(HAVE_GSSAPI)
+ /* handle the security-oriented responses 6xx ***/
+ /* FIXME: some errorchecking perhaps... ***/
+ switch(code) {
+ case 631:
+ code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
+ break;
+ case 632:
+ code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE);
+ break;
+ case 633:
+ code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL);
+ break;
+ default:
+ /* normal ftp stuff we pass through! */
+ break;
+ }
+#endif
+
+ /* store the latest code for later retrieval */
+ data->info.httpcode=code;
+
+ if(ftpcode)
+ *ftpcode = code;
+
+ if(421 == code) {
+ /* 421 means "Service not available, closing control connection." and FTP
+ * servers use it to signal that idle session timeout has been exceeded.
+ * If we ignored the response, it could end up hanging in some cases.
+ *
+ * This response code can come at any point so having it treated
+ * generically is a good idea.
+ */
+ infof(data, "We got a 421 - timeout!\n");
+ state(conn, FTP_STOP);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ return result;
+}
+
+/* --- parse FTP server responses --- */
+
+/*
+ * Curl_GetFTPResponse() is a BLOCKING function to read the full response
+ * from a server after a command.
+ *
+ */
+
+CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
+ struct connectdata *conn,
+ int *ftpcode) /* return the ftp-code */
+{
+ /*
+ * We cannot read just one byte per read() and then go back to select() as
+ * the OpenSSL read() doesn't grok that properly.
+ *
+ * Alas, read as much as possible, split up into lines, use the ending
+ * line in a response or continue reading. */
+
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+ long timeout; /* timeout in milliseconds */
+ long interval_ms;
+ struct SessionHandle *data = conn->data;
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ size_t nread;
+ int cache_skip=0;
+ int value_to_be_ignored=0;
+
+ if(ftpcode)
+ *ftpcode = 0; /* 0 for errors */
+ else
+ /* make the pointer point to something for the rest of this function */
+ ftpcode = &value_to_be_ignored;
+
+ *nreadp=0;
+
+ while(!*ftpcode && !result) {
+ /* check and reset timeout value every lap */
+ timeout = Curl_pp_state_timeout(pp);
+
+ if(timeout <=0 ) {
+ failf(data, "FTP response timeout");
+ return CURLE_OPERATION_TIMEDOUT; /* already too little time */
+ }
+
+ interval_ms = 1000; /* use 1 second timeout intervals */
+ if(timeout < interval_ms)
+ interval_ms = timeout;
+
+ /*
+ * Since this function is blocking, we need to wait here for input on the
+ * connection and only then we call the response reading function. We do
+ * timeout at least every second to make the timeout check run.
+ *
+ * A caution here is that the ftp_readresp() function has a cache that may
+ * contain pieces of a response from the previous invoke and we need to
+ * make sure we don't just wait for input while there is unhandled data in
+ * that cache. But also, if the cache is there, we call ftp_readresp() and
+ * the cache wasn't good enough to continue we must not just busy-loop
+ * around this function.
+ *
+ */
+
+ if(pp->cache && (cache_skip < 2)) {
+ /*
+ * There's a cache left since before. We then skipping the wait for
+ * socket action, unless this is the same cache like the previous round
+ * as then the cache was deemed not enough to act on and we then need to
+ * wait for more data anyway.
+ */
+ }
+ else {
+ switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
+ case -1: /* select() error, stop reading */
+ failf(data, "FTP response aborted due to select/poll error: %d",
+ SOCKERRNO);
+ return CURLE_RECV_ERROR;
+
+ case 0: /* timeout */
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ continue; /* just continue in our loop for the timeout duration */
+
+ default: /* for clarity */
+ break;
+ }
+ }
+ result = ftp_readresp(sockfd, pp, ftpcode, &nread);
+ if(result)
+ break;
+
+ if(!nread && pp->cache)
+ /* bump cache skip counter as on repeated skips we must wait for more
+ data */
+ cache_skip++;
+ else
+ /* when we got data or there is no cache left, we reset the cache skip
+ counter */
+ cache_skip=0;
+
+ *nreadp += nread;
+
+ } /* while there's buffer left and loop is requested */
+
+ pp->pending_resp = FALSE;
+
+ return result;
+}
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+static const char * const ftp_state_names[]={
+ "STOP",
+ "WAIT220",
+ "AUTH",
+ "USER",
+ "PASS",
+ "ACCT",
+ "PBSZ",
+ "PROT",
+ "CCC",
+ "PWD",
+ "SYST",
+ "NAMEFMT",
+ "QUOTE",
+ "RETR_PREQUOTE",
+ "STOR_PREQUOTE",
+ "POSTQUOTE",
+ "CWD",
+ "MKD",
+ "MDTM",
+ "TYPE",
+ "LIST_TYPE",
+ "RETR_TYPE",
+ "STOR_TYPE",
+ "SIZE",
+ "RETR_SIZE",
+ "STOR_SIZE",
+ "REST",
+ "RETR_REST",
+ "PORT",
+ "PRET",
+ "PASV",
+ "LIST",
+ "RETR",
+ "STOR",
+ "QUIT"
+};
+#endif
+
+/* This is the ONLY way to change FTP state! */
+static void _state(struct connectdata *conn,
+ ftpstate newstate
+#ifdef DEBUGBUILD
+ , int lineno
+#endif
+ )
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+#if defined(DEBUGBUILD)
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) lineno;
+#else
+ if(ftpc->state != newstate)
+ infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
+ (void *)ftpc, lineno, ftp_state_names[ftpc->state],
+ ftp_state_names[newstate]);
+#endif
+#endif
+
+ ftpc->state = newstate;
+}
+
+static CURLcode ftp_state_user(struct connectdata *conn)
+{
+ CURLcode result;
+ struct FTP *ftp = conn->data->req.protop;
+ /* send USER */
+ PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
+
+ state(conn, FTP_USER);
+ conn->data->state.ftp_trying_alternative = FALSE;
+
+ return CURLE_OK;
+}
+
+static CURLcode ftp_state_pwd(struct connectdata *conn)
+{
+ CURLcode result;
+
+ /* send PWD to discover our entry point */
+ PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
+ state(conn, FTP_PWD);
+
+ return CURLE_OK;
+}
+
+/* For the FTP "protocol connect" and "doing" phases only */
+static int ftp_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
+}
+
+/* For the FTP "DO_MORE" phase only */
+static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ /* When in DO_MORE state, we could be either waiting for us to connect to a
+ * remote site, or we could wait for that site to connect to us. Or just
+ * handle ordinary commands.
+ */
+
+ if(FTP_STOP == ftpc->state) {
+ int bits = GETSOCK_READSOCK(0);
+
+ /* if stopped and still in this state, then we're also waiting for a
+ connect on the secondary connection */
+ socks[0] = conn->sock[FIRSTSOCKET];
+
+ if(!conn->data->set.ftp_use_port) {
+ int s;
+ int i;
+ /* PORT is used to tell the server to connect to us, and during that we
+ don't do happy eyeballs, but we do if we connect to the server */
+ for(s=1, i=0; i<2; i++) {
+ if(conn->tempsock[i] != CURL_SOCKET_BAD) {
+ socks[s] = conn->tempsock[i];
+ bits |= GETSOCK_WRITESOCK(s++);
+ }
+ }
+ }
+ else {
+ socks[1] = conn->sock[SECONDARYSOCKET];
+ bits |= GETSOCK_WRITESOCK(1);
+ }
+
+ return bits;
+ }
+ else
+ return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
+}
+
+/* This is called after the FTP_QUOTE state is passed.
+
+ ftp_state_cwd() sends the range of CWD commands to the server to change to
+ the correct directory. It may also need to send MKD commands to create
+ missing ones, if that option is enabled.
+*/
+static CURLcode ftp_state_cwd(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(ftpc->cwddone)
+ /* already done and fine */
+ result = ftp_state_mdtm(conn);
+ else {
+ ftpc->count2 = 0; /* count2 counts failed CWDs */
+
+ /* count3 is set to allow a MKD to fail once. In the case when first CWD
+ fails and then MKD fails (due to another session raced it to create the
+ dir) this then allows for a second try to CWD to it */
+ ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0;
+
+ if(conn->bits.reuse && ftpc->entrypath) {
+ /* This is a re-used connection. Since we change directory to where the
+ transfer is taking place, we must first get back to the original dir
+ where we ended up after login: */
+ ftpc->count1 = 0; /* we count this as the first path, then we add one
+ for all upcoming ones in the ftp->dirs[] array */
+ PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
+ state(conn, FTP_CWD);
+ }
+ else {
+ if(ftpc->dirdepth) {
+ ftpc->count1 = 1;
+ /* issue the first CWD, the rest is sent when the CWD responses are
+ received... */
+ PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->count1 -1]);
+ state(conn, FTP_CWD);
+ }
+ else {
+ /* No CWD necessary */
+ result = ftp_state_mdtm(conn);
+ }
+ }
+ }
+ return result;
+}
+
+typedef enum {
+ EPRT,
+ PORT,
+ DONE
+} ftpport;
+
+static CURLcode ftp_state_use_port(struct connectdata *conn,
+ ftpport fcmd) /* start with this */
+
+{
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct SessionHandle *data=conn->data;
+ curl_socket_t portsock= CURL_SOCKET_BAD;
+ char myhost[256] = "";
+
+ struct Curl_sockaddr_storage ss;
+ Curl_addrinfo *res, *ai;
+ curl_socklen_t sslen;
+ char hbuf[NI_MAXHOST];
+ struct sockaddr *sa=(struct sockaddr *)&ss;
+ struct sockaddr_in * const sa4 = (void *)sa;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 * const sa6 = (void *)sa;
+#endif
+ char tmp[1024];
+ static const char mode[][5] = { "EPRT", "PORT" };
+ int rc;
+ int error;
+ char *host = NULL;
+ char *string_ftpport = data->set.str[STRING_FTPPORT];
+ struct Curl_dns_entry *h=NULL;
+ unsigned short port_min = 0;
+ unsigned short port_max = 0;
+ unsigned short port;
+ bool possibly_non_local = TRUE;
+
+ char *addr = NULL;
+
+ /* Step 1, figure out what is requested,
+ * accepted format :
+ * (ipv4|ipv6|domain|interface)?(:port(-range)?)?
+ */
+
+ if(data->set.str[STRING_FTPPORT] &&
+ (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
+
+#ifdef ENABLE_IPV6
+ size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
+ INET6_ADDRSTRLEN : strlen(string_ftpport);
+#else
+ size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
+ INET_ADDRSTRLEN : strlen(string_ftpport);
+#endif
+ char *ip_start = string_ftpport;
+ char *ip_end = NULL;
+ char *port_start = NULL;
+ char *port_sep = NULL;
+
+ addr = calloc(addrlen+1, 1);
+ if(!addr)
+ return CURLE_OUT_OF_MEMORY;
+
+#ifdef ENABLE_IPV6
+ if(*string_ftpport == '[') {
+ /* [ipv6]:port(-range) */
+ ip_start = string_ftpport + 1;
+ if((ip_end = strchr(string_ftpport, ']')) != NULL )
+ strncpy(addr, ip_start, ip_end - ip_start);
+ }
+ else
+#endif
+ if(*string_ftpport == ':') {
+ /* :port */
+ ip_end = string_ftpport;
+ }
+ else if((ip_end = strchr(string_ftpport, ':')) != NULL) {
+ /* either ipv6 or (ipv4|domain|interface):port(-range) */
+#ifdef ENABLE_IPV6
+ if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
+ /* ipv6 */
+ port_min = port_max = 0;
+ strcpy(addr, string_ftpport);
+ ip_end = NULL; /* this got no port ! */
+ }
+ else
+#endif
+ /* (ipv4|domain|interface):port(-range) */
+ strncpy(addr, string_ftpport, ip_end - ip_start );
+ }
+ else
+ /* ipv4|interface */
+ strcpy(addr, string_ftpport);
+
+ /* parse the port */
+ if(ip_end != NULL) {
+ if((port_start = strchr(ip_end, ':')) != NULL) {
+ port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
+ if((port_sep = strchr(port_start, '-')) != NULL) {
+ port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
+ }
+ else
+ port_max = port_min;
+ }
+ }
+
+ /* correct errors like:
+ * :1234-1230
+ * :-4711 , in this case port_min is (unsigned)-1,
+ * therefore port_min > port_max for all cases
+ * but port_max = (unsigned)-1
+ */
+ if(port_min > port_max )
+ port_min = port_max = 0;
+
+
+ if(*addr != '\0') {
+ /* attempt to get the address of the given interface name */
+ switch(Curl_if2ip(conn->ip_addr->ai_family,
+ Curl_ipv6_scope(conn->ip_addr->ai_addr),
+ conn->scope_id, addr, hbuf, sizeof(hbuf))) {
+ case IF2IP_NOT_FOUND:
+ /* not an interface, use the given string as host name instead */
+ host = addr;
+ break;
+ case IF2IP_AF_NOT_SUPPORTED:
+ return CURLE_FTP_PORT_FAILED;
+ case IF2IP_FOUND:
+ host = hbuf; /* use the hbuf for host name */
+ }
+ }
+ else
+ /* there was only a port(-range) given, default the host */
+ host = NULL;
+ } /* data->set.ftpport */
+
+ if(!host) {
+ /* not an interface and not a host name, get default by extracting
+ the IP from the control connection */
+
+ sslen = sizeof(ss);
+ if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
+ failf(data, "getsockname() failed: %s",
+ Curl_strerror(conn, SOCKERRNO) );
+ free(addr);
+ return CURLE_FTP_PORT_FAILED;
+ }
+ switch(sa->sa_family) {
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
+ break;
+#endif
+ default:
+ Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
+ break;
+ }
+ host = hbuf; /* use this host name */
+ possibly_non_local = FALSE; /* we know it is local now */
+ }
+
+ /* resolv ip/host to ip */
+ rc = Curl_resolv(conn, host, 0, &h);
+ if(rc == CURLRESOLV_PENDING)
+ (void)Curl_resolver_wait_resolv(conn, &h);
+ if(h) {
+ res = h->addr;
+ /* when we return from this function, we can forget about this entry
+ to we can unlock it now already */
+ Curl_resolv_unlock(data, h);
+ } /* (h) */
+ else
+ res = NULL; /* failure! */
+
+ if(res == NULL) {
+ failf(data, "failed to resolve the address provided to PORT: %s", host);
+ free(addr);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ free(addr);
+ host = NULL;
+
+ /* step 2, create a socket for the requested address */
+
+ portsock = CURL_SOCKET_BAD;
+ error = 0;
+ for(ai = res; ai; ai = ai->ai_next) {
+ result = Curl_socket(conn, ai, NULL, &portsock);
+ if(result) {
+ error = SOCKERRNO;
+ continue;
+ }
+ break;
+ }
+ if(!ai) {
+ failf(data, "socket failure: %s", Curl_strerror(conn, error));
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* step 3, bind to a suitable local address */
+
+ memcpy(sa, ai->ai_addr, ai->ai_addrlen);
+ sslen = ai->ai_addrlen;
+
+ for(port = port_min; port <= port_max;) {
+ if(sa->sa_family == AF_INET)
+ sa4->sin_port = htons(port);
+#ifdef ENABLE_IPV6
+ else
+ sa6->sin6_port = htons(port);
+#endif
+ /* Try binding the given address. */
+ if(bind(portsock, sa, sslen) ) {
+ /* It failed. */
+ error = SOCKERRNO;
+ if(possibly_non_local && (error == EADDRNOTAVAIL)) {
+ /* The requested bind address is not local. Use the address used for
+ * the control connection instead and restart the port loop
+ */
+
+ infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
+ Curl_strerror(conn, error) );
+
+ sslen = sizeof(ss);
+ if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
+ failf(data, "getsockname() failed: %s",
+ Curl_strerror(conn, SOCKERRNO) );
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+ port = port_min;
+ possibly_non_local = FALSE; /* don't try this again */
+ continue;
+ }
+ else if(error != EADDRINUSE && error != EACCES) {
+ failf(data, "bind(port=%hu) failed: %s", port,
+ Curl_strerror(conn, error) );
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+ }
+ else
+ break;
+
+ port++;
+ }
+
+ /* maybe all ports were in use already*/
+ if(port > port_max) {
+ failf(data, "bind() failed, we ran out of ports!");
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* get the name again after the bind() so that we can extract the
+ port number it uses now */
+ sslen = sizeof(ss);
+ if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
+ failf(data, "getsockname() failed: %s",
+ Curl_strerror(conn, SOCKERRNO) );
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* step 4, listen on the socket */
+
+ if(listen(portsock, 1)) {
+ failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* step 5, send the proper FTP command */
+
+ /* get a plain printable version of the numerical address to work with
+ below */
+ Curl_printable_address(ai, myhost, sizeof(myhost));
+
+#ifdef ENABLE_IPV6
+ if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
+ /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
+ request and enable EPRT again! */
+ conn->bits.ftp_use_eprt = TRUE;
+#endif
+
+ for(; fcmd != DONE; fcmd++) {
+
+ if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
+ /* if disabled, goto next */
+ continue;
+
+ if((PORT == fcmd) && sa->sa_family != AF_INET)
+ /* PORT is IPv4 only */
+ continue;
+
+ switch(sa->sa_family) {
+ case AF_INET:
+ port = ntohs(sa4->sin_port);
+ break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ port = ntohs(sa6->sin6_port);
+ break;
+#endif
+ default:
+ continue; /* might as well skip this */
+ }
+
+ if(EPRT == fcmd) {
+ /*
+ * Two fine examples from RFC2428;
+ *
+ * EPRT |1|132.235.1.2|6275|
+ *
+ * EPRT |2|1080::8:800:200C:417A|5282|
+ */
+
+ result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
+ sa->sa_family == AF_INET?1:2,
+ myhost, port);
+ if(result) {
+ failf(data, "Failure sending EPRT command: %s",
+ curl_easy_strerror(result));
+ Curl_closesocket(conn, portsock);
+ /* don't retry using PORT */
+ ftpc->count1 = PORT;
+ /* bail out */
+ state(conn, FTP_STOP);
+ return result;
+ }
+ break;
+ }
+ else if(PORT == fcmd) {
+ char *source = myhost;
+ char *dest = tmp;
+
+ /* translate x.x.x.x to x,x,x,x */
+ while(source && *source) {
+ if(*source == '.')
+ *dest=',';
+ else
+ *dest = *source;
+ dest++;
+ source++;
+ }
+ *dest = 0;
+ snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
+
+ result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
+ if(result) {
+ failf(data, "Failure sending PORT command: %s",
+ curl_easy_strerror(result));
+ Curl_closesocket(conn, portsock);
+ /* bail out */
+ state(conn, FTP_STOP);
+ return result;
+ }
+ break;
+ }
+ }
+
+ /* store which command was sent */
+ ftpc->count1 = fcmd;
+
+ /* we set the secondary socket variable to this for now, it is only so that
+ the cleanup function will close it in case we fail before the true
+ secondary stuff is made */
+ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ conn->sock[SECONDARYSOCKET] = portsock;
+
+ /* this tcpconnect assignment below is a hackish work-around to make the
+ multi interface with active FTP work - as it will not wait for a
+ (passive) connect in Curl_is_connected().
+
+ The *proper* fix is to make sure that the active connection from the
+ server is done in a non-blocking way. Currently, it is still BLOCKING.
+ */
+ conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
+
+ state(conn, FTP_PORT);
+ return result;
+}
+
+static CURLcode ftp_state_use_pasv(struct connectdata *conn)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result = CURLE_OK;
+ /*
+ Here's the excecutive summary on what to do:
+
+ PASV is RFC959, expect:
+ 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
+
+ LPSV is RFC1639, expect:
+ 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
+
+ EPSV is RFC2428, expect:
+ 229 Entering Extended Passive Mode (|||port|)
+
+ */
+
+ static const char mode[][5] = { "EPSV", "PASV" };
+ int modeoff;
+
+#ifdef PF_INET6
+ if(!conn->bits.ftp_use_epsv && conn->bits.ipv6)
+ /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the
+ request and enable EPSV again! */
+ conn->bits.ftp_use_epsv = TRUE;
+#endif
+
+ modeoff = conn->bits.ftp_use_epsv?0:1;
+
+ PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
+
+ ftpc->count1 = modeoff;
+ state(conn, FTP_PASV);
+ infof(conn->data, "Connect data stream passively\n");
+
+ return result;
+}
+
+/*
+ * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc.
+ *
+ * REST is the last command in the chain of commands when a "head"-like
+ * request is made. Thus, if an actual transfer is to be made this is where we
+ * take off for real.
+ */
+static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct SessionHandle *data = conn->data;
+
+ if(ftp->transfer != FTPTRANSFER_BODY) {
+ /* doesn't transfer any data */
+
+ /* still possibly do PRE QUOTE jobs */
+ state(conn, FTP_RETR_PREQUOTE);
+ result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+ }
+ else if(data->set.ftp_use_port) {
+ /* We have chosen to use the PORT (or similar) command */
+ result = ftp_state_use_port(conn, EPRT);
+ }
+ else {
+ /* We have chosen (this is default) to use the PASV (or similar) command */
+ if(data->set.ftp_use_pret) {
+ /* The user has requested that we send a PRET command
+ to prepare the server for the upcoming PASV */
+ if(!conn->proto.ftpc.file) {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET %s",
+ data->set.str[STRING_CUSTOMREQUEST]?
+ data->set.str[STRING_CUSTOMREQUEST]:
+ (data->set.ftp_list_only?"NLST":"LIST"));
+ }
+ else if(data->set.upload) {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file);
+ }
+ else {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file);
+ }
+ state(conn, FTP_PRET);
+ }
+ else {
+ result = ftp_state_use_pasv(conn);
+ }
+ }
+ return result;
+}
+
+static CURLcode ftp_state_rest(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
+ /* if a "head"-like request is being made (on a file) */
+
+ /* Determine if server can respond to REST command and therefore
+ whether it supports range */
+ PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
+
+ state(conn, FTP_REST);
+ }
+ else
+ result = ftp_state_prepare_transfer(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_size(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
+ /* if a "head"-like request is being made (on a file) */
+
+ /* we know ftpc->file is a valid pointer to a file name */
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
+
+ state(conn, FTP_SIZE);
+ }
+ else
+ result = ftp_state_rest(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_list(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ /* If this output is to be machine-parsed, the NLST command might be better
+ to use, since the LIST command output is not specified or standard in any
+ way. It has turned out that the NLST list output is not the same on all
+ servers either... */
+
+ /*
+ if FTPFILE_NOCWD was specified, we are currently in
+ the user's home directory, so we should add the path
+ as argument for the LIST / NLST / or custom command.
+ Whether the server will support this, is uncertain.
+
+ The other ftp_filemethods will CWD into dir/dir/ first and
+ then just do LIST (in that case: nothing to do here)
+ */
+ char *cmd, *lstArg, *slashPos;
+
+ lstArg = NULL;
+ if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
+ data->state.path &&
+ data->state.path[0] &&
+ strchr(data->state.path, '/')) {
+
+ lstArg = strdup(data->state.path);
+ if(!lstArg)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Check if path does not end with /, as then we cut off the file part */
+ if(lstArg[strlen(lstArg) - 1] != '/') {
+
+ /* chop off the file part if format is dir/dir/file */
+ slashPos = strrchr(lstArg, '/');
+ if(slashPos)
+ *(slashPos+1) = '\0';
+ }
+ }
+
+ cmd = aprintf( "%s%s%s",
+ data->set.str[STRING_CUSTOMREQUEST]?
+ data->set.str[STRING_CUSTOMREQUEST]:
+ (data->set.ftp_list_only?"NLST":"LIST"),
+ lstArg? " ": "",
+ lstArg? lstArg: "" );
+
+ if(!cmd) {
+ free(lstArg);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
+
+ free(lstArg);
+ free(cmd);
+
+ if(result)
+ return result;
+
+ state(conn, FTP_LIST);
+
+ return result;
+}
+
+static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* We've sent the TYPE, now we must send the list of prequote strings */
+
+ result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+
+ return result;
+}
+
+static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* We've sent the TYPE, now we must send the list of prequote strings */
+
+ result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
+
+ return result;
+}
+
+static CURLcode ftp_state_type(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ /* If we have selected NOBODY and HEADER, it means that we only want file
+ information. Which in FTP can't be much more than the file size and
+ date. */
+ if(data->set.opt_no_body && ftpc->file &&
+ ftp_need_type(conn, data->set.prefer_ascii)) {
+ /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
+ may not support it! It is however the only way we have to get a file's
+ size! */
+
+ ftp->transfer = FTPTRANSFER_INFO;
+ /* this means no actual transfer will be made */
+
+ /* Some servers return different sizes for different modes, and thus we
+ must set the proper type before we check the size */
+ result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE);
+ if(result)
+ return result;
+ }
+ else
+ result = ftp_state_size(conn);
+
+ return result;
+}
+
+/* This is called after the CWD commands have been done in the beginning of
+ the DO phase */
+static CURLcode ftp_state_mdtm(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ /* Requested time of file or time-depended transfer? */
+ if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
+
+ /* we have requested to get the modified-time of the file, this is a white
+ spot as the MDTM is not mentioned in RFC959 */
+ PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
+
+ state(conn, FTP_MDTM);
+ }
+ else
+ result = ftp_state_type(conn);
+
+ return result;
+}
+
+
+/* This is called after the TYPE and possible quote commands have been sent */
+static CURLcode ftp_state_ul_setup(struct connectdata *conn,
+ bool sizechecked)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ int seekerr = CURL_SEEKFUNC_OK;
+
+ if((data->state.resume_from && !sizechecked) ||
+ ((data->state.resume_from > 0) && sizechecked)) {
+ /* we're about to continue the uploading of a file */
+ /* 1. get already existing file's size. We use the SIZE command for this
+ which may not exist in the server! The SIZE command is not in
+ RFC959. */
+
+ /* 2. This used to set REST. But since we can do append, we
+ don't another ftp command. We just skip the source file
+ offset and then we APPEND the rest on the file instead */
+
+ /* 3. pass file-size number of bytes in the source file */
+ /* 4. lower the infilesize counter */
+ /* => transfer as usual */
+
+ if(data->state.resume_from < 0 ) {
+ /* Got no given size to start from, figure it out */
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
+ state(conn, FTP_STOR_SIZE);
+ return result;
+ }
+
+ /* enable append */
+ data->set.ftp_append = TRUE;
+
+ /* Let's read off the proper amount of bytes from the input. */
+ if(conn->seek_func) {
+ seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+ SEEK_SET);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
+ BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ conn->fread_func(data->state.buffer, 1, readthisamountnow,
+ conn->fread_in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ } while(passed < data->state.resume_from);
+ }
+ }
+ /* now, decrease the size of the read */
+ if(data->state.infilesize>0) {
+ data->state.infilesize -= data->state.resume_from;
+
+ if(data->state.infilesize <= 0) {
+ infof(data, "File already completely uploaded\n");
+
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ /* Set ->transfer so that we won't get any error in
+ * ftp_done() because we didn't transfer anything! */
+ ftp->transfer = FTPTRANSFER_NONE;
+
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+ }
+ /* we've passed, proceed as normal */
+ } /* resume_from */
+
+ PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
+ ftpc->file);
+
+ state(conn, FTP_STOR);
+
+ return result;
+}
+
+static CURLcode ftp_state_quote(struct connectdata *conn,
+ bool init,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ bool quote=FALSE;
+ struct curl_slist *item;
+
+ switch(instate) {
+ case FTP_QUOTE:
+ default:
+ item = data->set.quote;
+ break;
+ case FTP_RETR_PREQUOTE:
+ case FTP_STOR_PREQUOTE:
+ item = data->set.prequote;
+ break;
+ case FTP_POSTQUOTE:
+ item = data->set.postquote;
+ break;
+ }
+
+ /*
+ * This state uses:
+ * 'count1' to iterate over the commands to send
+ * 'count2' to store wether to allow commands to fail
+ */
+
+ if(init)
+ ftpc->count1 = 0;
+ else
+ ftpc->count1++;
+
+ if(item) {
+ int i = 0;
+
+ /* Skip count1 items in the linked list */
+ while((i< ftpc->count1) && item) {
+ item = item->next;
+ i++;
+ }
+ if(item) {
+ char *cmd = item->data;
+ if(cmd[0] == '*') {
+ cmd++;
+ ftpc->count2 = 1; /* the sent command is allowed to fail */
+ }
+ else
+ ftpc->count2 = 0; /* failure means cancel operation */
+
+ PPSENDF(&ftpc->pp, "%s", cmd);
+ state(conn, instate);
+ quote = TRUE;
+ }
+ }
+
+ if(!quote) {
+ /* No more quote to send, continue to ... */
+ switch(instate) {
+ case FTP_QUOTE:
+ default:
+ result = ftp_state_cwd(conn);
+ break;
+ case FTP_RETR_PREQUOTE:
+ if(ftp->transfer != FTPTRANSFER_BODY)
+ state(conn, FTP_STOP);
+ else {
+ if(ftpc->known_filesize != -1) {
+ Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
+ result = ftp_state_retr(conn, ftpc->known_filesize);
+ }
+ else {
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
+ state(conn, FTP_RETR_SIZE);
+ }
+ }
+ break;
+ case FTP_STOR_PREQUOTE:
+ result = ftp_state_ul_setup(conn, FALSE);
+ break;
+ case FTP_POSTQUOTE:
+ break;
+ }
+ }
+
+ return result;
+}
+
+/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
+ problems */
+static CURLcode ftp_epsv_disable(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ if(conn->bits.ipv6) {
+ /* We can't disable EPSV when doing IPv6, so this is instead a fail */
+ failf(conn->data, "Failed EPSV attempt, exiting\n");
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+
+ infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
+ /* disable it for next transfer */
+ conn->bits.ftp_use_epsv = FALSE;
+ conn->data->state.errorbuf = FALSE; /* allow error message to get
+ rewritten */
+ PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
+ conn->proto.ftpc.count1++;
+ /* remain in/go to the FTP_PASV state */
+ state(conn, FTP_PASV);
+ return result;
+}
+
+/*
+ * Perform the necessary magic that needs to be done once the TCP connection
+ * to the proxy has completed.
+ */
+static CURLcode proxy_magic(struct connectdata *conn,
+ char *newhost, unsigned short newport,
+ bool *magicdone)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+#if defined(CURL_DISABLE_PROXY)
+ (void) newhost;
+ (void) newport;
+#endif
+
+ *magicdone = FALSE;
+
+ switch(conn->proxytype) {
+ case CURLPROXY_SOCKS5:
+ case CURLPROXY_SOCKS5_HOSTNAME:
+ result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
+ newport, SECONDARYSOCKET, conn);
+ *magicdone = TRUE;
+ break;
+ case CURLPROXY_SOCKS4:
+ result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
+ SECONDARYSOCKET, conn, FALSE);
+ *magicdone = TRUE;
+ break;
+ case CURLPROXY_SOCKS4A:
+ result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
+ SECONDARYSOCKET, conn, TRUE);
+ *magicdone = TRUE;
+ break;
+ case CURLPROXY_HTTP:
+ case CURLPROXY_HTTP_1_0:
+ /* do nothing here. handled later. */
+ break;
+ default:
+ failf(data, "unknown proxytype option given");
+ result = CURLE_COULDNT_CONNECT;
+ break;
+ }
+
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
+ /* BLOCKING */
+ /* We want "seamless" FTP operations through HTTP proxy tunnel */
+
+ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
+ * member conn->proto.http; we want FTP through HTTP and we have to
+ * change the member temporarily for connecting to the HTTP proxy. After
+ * Curl_proxyCONNECT we have to set back the member to the original
+ * struct FTP pointer
+ */
+ struct HTTP http_proxy;
+ struct FTP *ftp_save = data->req.protop;
+ memset(&http_proxy, 0, sizeof(http_proxy));
+ data->req.protop = &http_proxy;
+
+ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
+
+ data->req.protop = ftp_save;
+
+ if(result)
+ return result;
+
+ if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
+ /* the CONNECT procedure is not complete, the tunnel is not yet up */
+ state(conn, FTP_STOP); /* this phase is completed */
+ return result;
+ }
+ else
+ *magicdone = TRUE;
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result;
+ struct SessionHandle *data=conn->data;
+ struct Curl_dns_entry *addr=NULL;
+ int rc;
+ unsigned short connectport; /* the local port connect() should use! */
+ char *str=&data->state.buffer[4]; /* start on the first letter */
+
+ /* if we come here again, make sure the former name is cleared */
+ Curl_safefree(ftpc->newhost);
+
+ if((ftpc->count1 == 0) &&
+ (ftpcode == 229)) {
+ /* positive EPSV response */
+ char *ptr = strchr(str, '(');
+ if(ptr) {
+ unsigned int num;
+ char separator[4];
+ ptr++;
+ if(5 == sscanf(ptr, "%c%c%c%u%c",
+ &separator[0],
+ &separator[1],
+ &separator[2],
+ &num,
+ &separator[3])) {
+ const char sep1 = separator[0];
+ int i;
+
+ /* The four separators should be identical, or else this is an oddly
+ formatted reply and we bail out immediately. */
+ for(i=1; i<4; i++) {
+ if(separator[i] != sep1) {
+ ptr=NULL; /* set to NULL to signal error */
+ break;
+ }
+ }
+ if(num > 0xffff) {
+ failf(data, "Illegal port number in EPSV reply");
+ return CURLE_FTP_WEIRD_PASV_REPLY;
+ }
+ if(ptr) {
+ ftpc->newport = (unsigned short)(num & 0xffff);
+
+ /* use the original host name again */
+ ftpc->newhost = strdup(conn->host.name);
+ if(!ftpc->newhost)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else
+ ptr=NULL;
+ }
+ if(!ptr) {
+ failf(data, "Weirdly formatted EPSV reply");
+ return CURLE_FTP_WEIRD_PASV_REPLY;
+ }
+ }
+ else if((ftpc->count1 == 1) &&
+ (ftpcode == 227)) {
+ /* positive PASV response */
+ int ip[4];
+ int port[2];
+
+ /*
+ * Scan for a sequence of six comma-separated numbers and use them as
+ * IP+port indicators.
+ *
+ * Found reply-strings include:
+ * "227 Entering Passive Mode (127,0,0,1,4,51)"
+ * "227 Data transfer will passively listen to 127,0,0,1,4,51"
+ * "227 Entering passive mode. 127,0,0,1,4,51"
+ */
+ while(*str) {
+ if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d",
+ &ip[0], &ip[1], &ip[2], &ip[3],
+ &port[0], &port[1]))
+ break;
+ str++;
+ }
+
+ if(!*str) {
+ failf(data, "Couldn't interpret the 227-response");
+ return CURLE_FTP_WEIRD_227_FORMAT;
+ }
+
+ /* we got OK from server */
+ if(data->set.ftp_skip_ip) {
+ /* told to ignore the remotely given IP but instead use the host we used
+ for the control connection */
+ infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n",
+ ip[0], ip[1], ip[2], ip[3],
+ conn->host.name);
+
+ /* use the original host name again */
+ ftpc->newhost = strdup(conn->host.name);
+ }
+ else
+ ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+
+ if(!ftpc->newhost)
+ return CURLE_OUT_OF_MEMORY;
+
+ ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
+ }
+ else if(ftpc->count1 == 0) {
+ /* EPSV failed, move on to PASV */
+ return ftp_epsv_disable(conn);
+ }
+ else {
+ failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
+ return CURLE_FTP_WEIRD_PASV_REPLY;
+ }
+
+ if(conn->bits.proxy) {
+ /*
+ * This connection uses a proxy and we need to connect to the proxy again
+ * here. We don't want to rely on a former host lookup that might've
+ * expired now, instead we remake the lookup here and now!
+ */
+ rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
+ if(rc == CURLRESOLV_PENDING)
+ /* BLOCKING, ignores the return code but 'addr' will be NULL in
+ case of failure */
+ (void)Curl_resolver_wait_resolv(conn, &addr);
+
+ connectport =
+ (unsigned short)conn->port; /* we connect to the proxy's port */
+
+ if(!addr) {
+ failf(data, "Can't resolve proxy host %s:%hu",
+ conn->proxy.name, connectport);
+ return CURLE_FTP_CANT_GET_HOST;
+ }
+ }
+ else {
+ /* normal, direct, ftp connection */
+ rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
+ if(rc == CURLRESOLV_PENDING)
+ /* BLOCKING */
+ (void)Curl_resolver_wait_resolv(conn, &addr);
+
+ connectport = ftpc->newport; /* we connect to the remote port */
+
+ if(!addr) {
+ failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
+ return CURLE_FTP_CANT_GET_HOST;
+ }
+ }
+
+ conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
+ result = Curl_connecthost(conn, addr);
+
+ Curl_resolv_unlock(data, addr); /* we're done using this address */
+
+ if(result) {
+ if(ftpc->count1 == 0 && ftpcode == 229)
+ return ftp_epsv_disable(conn);
+
+ return result;
+ }
+
+
+ /*
+ * When this is used from the multi interface, this might've returned with
+ * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
+ * connect to connect.
+ */
+
+ if(data->set.verbose)
+ /* this just dumps information about this second connection */
+ ftp_pasv_verbose(conn, conn->ip_addr, ftpc->newhost, connectport);
+
+ conn->bits.do_more = TRUE;
+ state(conn, FTP_STOP); /* this phase is completed */
+
+ return result;
+}
+
+static CURLcode ftp_state_port_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ ftpport fcmd = (ftpport)ftpc->count1;
+ CURLcode result = CURLE_OK;
+
+ /* The FTP spec tells a positive response should have code 200.
+ Be more permissive here to tolerate deviant servers. */
+ if(ftpcode / 100 != 2) {
+ /* the command failed */
+
+ if(EPRT == fcmd) {
+ infof(data, "disabling EPRT usage\n");
+ conn->bits.ftp_use_eprt = FALSE;
+ }
+ fcmd++;
+
+ if(fcmd == DONE) {
+ failf(data, "Failed to do PORT");
+ result = CURLE_FTP_PORT_FAILED;
+ }
+ else
+ /* try next */
+ result = ftp_state_use_port(conn, fcmd);
+ }
+ else {
+ infof(data, "Connect data stream actively\n");
+ state(conn, FTP_STOP); /* end of DO phase */
+ result = ftp_dophase_done(conn, FALSE);
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ switch(ftpcode) {
+ case 213:
+ {
+ /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
+ last .sss part is optional and means fractions of a second */
+ int year, month, day, hour, minute, second;
+ char *buf = data->state.buffer;
+ if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
+ &year, &month, &day, &hour, &minute, &second)) {
+ /* we have a time, reformat it */
+ time_t secs=time(NULL);
+ /* using the good old yacc/bison yuck */
+ snprintf(buf, sizeof(conn->data->state.buffer),
+ "%04d%02d%02d %02d:%02d:%02d GMT",
+ year, month, day, hour, minute, second);
+ /* now, convert this into a time() value: */
+ data->info.filetime = (long)curl_getdate(buf, &secs);
+ }
+
+#ifdef CURL_FTP_HTTPSTYLE_HEAD
+ /* If we asked for a time of the file and we actually got one as well,
+ we "emulate" a HTTP-style header in our output. */
+
+ if(data->set.opt_no_body &&
+ ftpc->file &&
+ data->set.get_filetime &&
+ (data->info.filetime>=0) ) {
+ time_t filetime = (time_t)data->info.filetime;
+ struct tm buffer;
+ const struct tm *tm = &buffer;
+
+ result = Curl_gmtime(filetime, &buffer);
+ if(result)
+ return result;
+
+ /* format: "Tue, 15 Nov 1994 12:45:26" */
+ snprintf(buf, BUFSIZE-1,
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ if(result)
+ return result;
+ } /* end of a ridiculous amount of conditionals */
+#endif
+ }
+ break;
+ default:
+ infof(data, "unsupported MDTM reply format\n");
+ break;
+ case 550: /* "No such file or directory" */
+ failf(data, "Given file does not exist");
+ result = CURLE_FTP_COULDNT_RETR_FILE;
+ break;
+ }
+
+ if(data->set.timecondition) {
+ if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
+ switch(data->set.timecondition) {
+ case CURL_TIMECOND_IFMODSINCE:
+ default:
+ if(data->info.filetime <= data->set.timevalue) {
+ infof(data, "The requested document is not new enough\n");
+ ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
+ data->info.timecond = TRUE;
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+ break;
+ case CURL_TIMECOND_IFUNMODSINCE:
+ if(data->info.filetime > data->set.timevalue) {
+ infof(data, "The requested document is not old enough\n");
+ ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
+ data->info.timecond = TRUE;
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+ break;
+ } /* switch */
+ }
+ else {
+ infof(data, "Skipping time comparison\n");
+ }
+ }
+
+ if(!result)
+ result = ftp_state_type(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_type_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+
+ if(ftpcode/100 != 2) {
+ /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
+ successful 'TYPE I'. While that is not as RFC959 says, it is still a
+ positive response code and we allow that. */
+ failf(data, "Couldn't set desired mode");
+ return CURLE_FTP_COULDNT_SET_TYPE;
+ }
+ if(ftpcode != 200)
+ infof(data, "Got a %03d response code instead of the assumed 200\n",
+ ftpcode);
+
+ if(instate == FTP_TYPE)
+ result = ftp_state_size(conn);
+ else if(instate == FTP_LIST_TYPE)
+ result = ftp_state_list(conn);
+ else if(instate == FTP_RETR_TYPE)
+ result = ftp_state_retr_prequote(conn);
+ else if(instate == FTP_STOR_TYPE)
+ result = ftp_state_stor_prequote(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_retr(struct connectdata *conn,
+ curl_off_t filesize)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+ ftp->downloadsize = filesize;
+
+ if(data->state.resume_from) {
+ /* We always (attempt to) get the size of downloads, so it is done before
+ this even when not doing resumes. */
+ if(filesize == -1) {
+ infof(data, "ftp server doesn't support SIZE\n");
+ /* We couldn't get the size and therefore we can't know if there really
+ is a part of the file left to get, although the server will just
+ close the connection when we start the connection so it won't cause
+ us any harm, just not make us exit as nicely. */
+ }
+ else {
+ /* We got a file size report, so we check that there actually is a
+ part of the file left to get, or else we go home. */
+ if(data->state.resume_from< 0) {
+ /* We're supposed to download the last abs(from) bytes */
+ if(filesize < -data->state.resume_from) {
+ failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
+ ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ /* convert to size to download */
+ ftp->downloadsize = -data->state.resume_from;
+ /* download from where? */
+ data->state.resume_from = filesize - ftp->downloadsize;
+ }
+ else {
+ if(filesize < data->state.resume_from) {
+ failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
+ ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ /* Now store the number of bytes we are expected to download */
+ ftp->downloadsize = filesize-data->state.resume_from;
+ }
+ }
+
+ if(ftp->downloadsize == 0) {
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ infof(data, "File already completely downloaded\n");
+
+ /* Set ->transfer so that we won't get any error in ftp_done()
+ * because we didn't transfer the any file */
+ ftp->transfer = FTPTRANSFER_NONE;
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+
+ /* Set resume file transfer offset */
+ infof(data, "Instructs server to resume from offset %"
+ CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
+
+ PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
+ data->state.resume_from);
+
+ state(conn, FTP_RETR_REST);
+ }
+ else {
+ /* no resume */
+ PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
+ state(conn, FTP_RETR);
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_size_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ curl_off_t filesize;
+ char *buf = data->state.buffer;
+
+ /* get the size from the ascii string: */
+ filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1;
+
+ if(instate == FTP_SIZE) {
+#ifdef CURL_FTP_HTTPSTYLE_HEAD
+ if(-1 != filesize) {
+ snprintf(buf, sizeof(data->state.buffer),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ if(result)
+ return result;
+ }
+#endif
+ Curl_pgrsSetDownloadSize(data, filesize);
+ result = ftp_state_rest(conn);
+ }
+ else if(instate == FTP_RETR_SIZE) {
+ Curl_pgrsSetDownloadSize(data, filesize);
+ result = ftp_state_retr(conn, filesize);
+ }
+ else if(instate == FTP_STOR_SIZE) {
+ data->state.resume_from = filesize;
+ result = ftp_state_ul_setup(conn, TRUE);
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_rest_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ switch(instate) {
+ case FTP_REST:
+ default:
+#ifdef CURL_FTP_HTTPSTYLE_HEAD
+ if(ftpcode == 350) {
+ char buffer[24]= { "Accept-ranges: bytes\r\n" };
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0);
+ if(result)
+ return result;
+ }
+#endif
+ result = ftp_state_prepare_transfer(conn);
+ break;
+
+ case FTP_RETR_REST:
+ if(ftpcode != 350) {
+ failf(conn->data, "Couldn't use REST");
+ result = CURLE_FTP_COULDNT_USE_REST;
+ }
+ else {
+ PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
+ state(conn, FTP_RETR);
+ }
+ break;
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_stor_resp(struct connectdata *conn,
+ int ftpcode, ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ if(ftpcode>=400) {
+ failf(data, "Failed FTP upload: %0d", ftpcode);
+ state(conn, FTP_STOP);
+ /* oops, we never close the sockets! */
+ return CURLE_UPLOAD_FAILED;
+ }
+
+ conn->proto.ftpc.state_saved = instate;
+
+ /* PORT means we are now awaiting the server to connect to us. */
+ if(data->set.ftp_use_port) {
+ bool connected;
+
+ state(conn, FTP_STOP); /* no longer in STOR state */
+
+ result = AllowServerConnect(conn, &connected);
+ if(result)
+ return result;
+
+ if(!connected) {
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ infof(data, "Data conn was not available immediately\n");
+ ftpc->wait_data_conn = TRUE;
+ }
+
+ return CURLE_OK;
+ }
+ else
+ return InitiateTransfer(conn);
+}
+
+/* for LIST and RETR responses */
+static CURLcode ftp_state_get_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ char *buf = data->state.buffer;
+
+ if((ftpcode == 150) || (ftpcode == 125)) {
+
+ /*
+ A;
+ 150 Opening BINARY mode data connection for /etc/passwd (2241
+ bytes). (ok, the file is being transferred)
+
+ B:
+ 150 Opening ASCII mode data connection for /bin/ls
+
+ C:
+ 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes).
+
+ D:
+ 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes)
+
+ E:
+ 125 Data connection already open; Transfer starting. */
+
+ curl_off_t size=-1; /* default unknown size */
+
+
+ /*
+ * It appears that there are FTP-servers that return size 0 for files when
+ * SIZE is used on the file while being in BINARY mode. To work around
+ * that (stupid) behavior, we attempt to parse the RETR response even if
+ * the SIZE returned size zero.
+ *
+ * Debugging help from Salvatore Sorrentino on February 26, 2003.
+ */
+
+ if((instate != FTP_LIST) &&
+ !data->set.prefer_ascii &&
+ (ftp->downloadsize < 1)) {
+ /*
+ * It seems directory listings either don't show the size or very
+ * often uses size 0 anyway. ASCII transfers may very well turn out
+ * that the transferred amount of data is not the same as this line
+ * tells, why using this number in those cases only confuses us.
+ *
+ * Example D above makes this parsing a little tricky */
+ char *bytes;
+ bytes=strstr(buf, " bytes");
+ if(bytes--) {
+ long in=(long)(bytes-buf);
+ /* this is a hint there is size information in there! ;-) */
+ while(--in) {
+ /* scan for the left parenthesis and break there */
+ if('(' == *bytes)
+ break;
+ /* skip only digits */
+ if(!ISDIGIT(*bytes)) {
+ bytes=NULL;
+ break;
+ }
+ /* one more estep backwards */
+ bytes--;
+ }
+ /* if we have nothing but digits: */
+ if(bytes++) {
+ /* get the number! */
+ size = curlx_strtoofft(bytes, NULL, 0);
+ }
+ }
+ }
+ else if(ftp->downloadsize > -1)
+ size = ftp->downloadsize;
+
+ if(size > data->req.maxdownload && data->req.maxdownload > 0)
+ size = data->req.size = data->req.maxdownload;
+ else if((instate != FTP_LIST) && (data->set.prefer_ascii))
+ size = -1; /* kludge for servers that understate ASCII mode file size */
+
+ infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
+ data->req.maxdownload);
+
+ if(instate != FTP_LIST)
+ infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n",
+ size);
+
+ /* FTP download: */
+ conn->proto.ftpc.state_saved = instate;
+ conn->proto.ftpc.retr_size_saved = size;
+
+ if(data->set.ftp_use_port) {
+ bool connected;
+
+ result = AllowServerConnect(conn, &connected);
+ if(result)
+ return result;
+
+ if(!connected) {
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ infof(data, "Data conn was not available immediately\n");
+ state(conn, FTP_STOP);
+ ftpc->wait_data_conn = TRUE;
+ }
+ }
+ else
+ return InitiateTransfer(conn);
+ }
+ else {
+ if((instate == FTP_LIST) && (ftpcode == 450)) {
+ /* simply no matching files in the dir listing */
+ ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
+ state(conn, FTP_STOP); /* this phase is over */
+ }
+ else {
+ failf(data, "RETR response: %03d", ftpcode);
+ return instate == FTP_RETR && ftpcode == 550?
+ CURLE_REMOTE_FILE_NOT_FOUND:
+ CURLE_FTP_COULDNT_RETR_FILE;
+ }
+ }
+
+ return result;
+}
+
+/* after USER, PASS and ACCT */
+static CURLcode ftp_state_loggedin(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ if(conn->ssl[FIRSTSOCKET].use) {
+ /* PBSZ = PROTECTION BUFFER SIZE.
+
+ The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
+
+ Specifically, the PROT command MUST be preceded by a PBSZ
+ command and a PBSZ command MUST be preceded by a successful
+ security data exchange (the TLS negotiation in this case)
+
+ ... (and on page 8):
+
+ Thus the PBSZ command must still be issued, but must have a
+ parameter of '0' to indicate that no buffering is taking place
+ and the data connection should not be encapsulated.
+ */
+ PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
+ state(conn, FTP_PBSZ);
+ }
+ else {
+ result = ftp_state_pwd(conn);
+ }
+ return result;
+}
+
+/* for USER and PASS responses */
+static CURLcode ftp_state_user_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ (void)instate; /* no use for this yet */
+
+ /* some need password anyway, and others just return 2xx ignored */
+ if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
+ /* 331 Password required for ...
+ (the server requires to send the user's password too) */
+ PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:"");
+ state(conn, FTP_PASS);
+ }
+ else if(ftpcode/100 == 2) {
+ /* 230 User ... logged in.
+ (the user logged in with or without password) */
+ result = ftp_state_loggedin(conn);
+ }
+ else if(ftpcode == 332) {
+ if(data->set.str[STRING_FTP_ACCOUNT]) {
+ PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
+ state(conn, FTP_ACCT);
+ }
+ else {
+ failf(data, "ACCT requested but none available");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+ else {
+ /* All other response codes, like:
+
+ 530 User ... access denied
+ (the server denies to log the specified user) */
+
+ if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
+ !conn->data->state.ftp_trying_alternative) {
+ /* Ok, USER failed. Let's try the supplied command. */
+ PPSENDF(&conn->proto.ftpc.pp, "%s",
+ conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ conn->data->state.ftp_trying_alternative = TRUE;
+ state(conn, FTP_USER);
+ result = CURLE_OK;
+ }
+ else {
+ failf(data, "Access denied: %03d", ftpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+ return result;
+}
+
+/* for ACCT response */
+static CURLcode ftp_state_acct_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ if(ftpcode != 230) {
+ failf(data, "ACCT rejected by server: %03d", ftpcode);
+ result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
+ }
+ else
+ result = ftp_state_loggedin(conn);
+
+ return result;
+}
+
+
+static CURLcode ftp_statemach_act(struct connectdata *conn)
+{
+ CURLcode result;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ struct SessionHandle *data=conn->data;
+ int ftpcode;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ static const char ftpauth[][4] = { "SSL", "TLS" };
+ size_t nread = 0;
+
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ result = ftp_readresp(sock, pp, &ftpcode, &nread);
+ if(result)
+ return result;
+
+ if(ftpcode) {
+ /* we have now received a full FTP server response */
+ switch(ftpc->state) {
+ case FTP_WAIT220:
+ if(ftpcode == 230)
+ /* 230 User logged in - already! */
+ return ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ else if(ftpcode != 220) {
+ failf(data, "Got a %03d ftp-server response when 220 was expected",
+ ftpcode);
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+
+ /* We have received a 220 response fine, now we proceed. */
+#ifdef HAVE_GSSAPI
+ if(data->set.krb) {
+ /* If not anonymous login, try a secure login. Note that this
+ procedure is still BLOCKING. */
+
+ Curl_sec_request_prot(conn, "private");
+ /* We set private first as default, in case the line below fails to
+ set a valid level */
+ Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
+
+ if(Curl_sec_login(conn))
+ infof(data, "Logging in with password in cleartext!\n");
+ else
+ infof(data, "Authentication successful\n");
+ }
+#endif
+
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but FTPS is
+ requested. Try a FTPS connection now */
+
+ ftpc->count3=0;
+ switch(data->set.ftpsslauth) {
+ case CURLFTPAUTH_DEFAULT:
+ case CURLFTPAUTH_SSL:
+ ftpc->count2 = 1; /* add one to get next */
+ ftpc->count1 = 0;
+ break;
+ case CURLFTPAUTH_TLS:
+ ftpc->count2 = -1; /* subtract one to get next */
+ ftpc->count1 = 1;
+ break;
+ default:
+ failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d",
+ (int)data->set.ftpsslauth);
+ return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
+ }
+ PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
+ state(conn, FTP_AUTH);
+ }
+ else {
+ result = ftp_state_user(conn);
+ if(result)
+ return result;
+ }
+
+ break;
+
+ case FTP_AUTH:
+ /* we have gotten the response to a previous AUTH command */
+
+ /* RFC2228 (page 5) says:
+ *
+ * If the server is willing to accept the named security mechanism,
+ * and does not require any security data, it must respond with
+ * reply code 234/334.
+ */
+
+ if((ftpcode == 234) || (ftpcode == 334)) {
+ /* Curl_ssl_connect is BLOCKING */
+ result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ if(!result) {
+ conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
+ result = ftp_state_user(conn);
+ }
+ }
+ else if(ftpc->count3 < 1) {
+ ftpc->count3++;
+ ftpc->count1 += ftpc->count2; /* get next attempt */
+ result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
+ /* remain in this same state */
+ }
+ else {
+ if(data->set.use_ssl > CURLUSESSL_TRY)
+ /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */
+ result = CURLE_USE_SSL_FAILED;
+ else
+ /* ignore the failure and continue */
+ result = ftp_state_user(conn);
+ }
+
+ if(result)
+ return result;
+ break;
+
+ case FTP_USER:
+ case FTP_PASS:
+ result = ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_ACCT:
+ result = ftp_state_acct_resp(conn, ftpcode);
+ break;
+
+ case FTP_PBSZ:
+ PPSENDF(&ftpc->pp, "PROT %c",
+ data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
+ state(conn, FTP_PROT);
+
+ break;
+
+ case FTP_PROT:
+ if(ftpcode/100 == 2)
+ /* We have enabled SSL for the data connection! */
+ conn->ssl[SECONDARYSOCKET].use =
+ (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
+ /* FTP servers typically responds with 500 if they decide to reject
+ our 'P' request */
+ else if(data->set.use_ssl > CURLUSESSL_CONTROL)
+ /* we failed and bails out */
+ return CURLE_USE_SSL_FAILED;
+
+ if(data->set.ftp_ccc) {
+ /* CCC - Clear Command Channel
+ */
+ PPSENDF(&ftpc->pp, "%s", "CCC");
+ state(conn, FTP_CCC);
+ }
+ else {
+ result = ftp_state_pwd(conn);
+ if(result)
+ return result;
+ }
+ break;
+
+ case FTP_CCC:
+ if(ftpcode < 500) {
+ /* First shut down the SSL layer (note: this call will block) */
+ result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
+
+ if(result) {
+ failf(conn->data, "Failed to clear the command channel (CCC)");
+ return result;
+ }
+ }
+
+ /* Then continue as normal */
+ result = ftp_state_pwd(conn);
+ if(result)
+ return result;
+ break;
+
+ case FTP_PWD:
+ if(ftpcode == 257) {
+ char *ptr=&data->state.buffer[4]; /* start on the first letter */
+ char *dir;
+ char *store;
+
+ dir = malloc(nread + 1);
+ if(!dir)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Reply format is like
+ 257<space>[rubbish]"<directory-name>"<space><commentary> and the
+ RFC959 says
+
+ The directory name can contain any character; embedded
+ double-quotes should be escaped by double-quotes (the
+ "quote-doubling" convention).
+ */
+
+ /* scan for the first double-quote for non-standard responses */
+ while(ptr < &data->state.buffer[sizeof(data->state.buffer)]
+ && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
+ ptr++;
+
+ if('\"' == *ptr) {
+ /* it started good */
+ ptr++;
+ for(store = dir; *ptr;) {
+ if('\"' == *ptr) {
+ if('\"' == ptr[1]) {
+ /* "quote-doubling" */
+ *store = ptr[1];
+ ptr++;
+ }
+ else {
+ /* end of path */
+ *store = '\0'; /* zero terminate */
+ break; /* get out of this loop */
+ }
+ }
+ else
+ *store = *ptr;
+ store++;
+ ptr++;
+ }
+
+ /* If the path name does not look like an absolute path (i.e.: it
+ does not start with a '/'), we probably need some server-dependent
+ adjustments. For example, this is the case when connecting to
+ an OS400 FTP server: this server supports two name syntaxes,
+ the default one being incompatible with standard pathes. In
+ addition, this server switches automatically to the regular path
+ syntax when one is encountered in a command: this results in
+ having an entrypath in the wrong syntax when later used in CWD.
+ The method used here is to check the server OS: we do it only
+ if the path name looks strange to minimize overhead on other
+ systems. */
+
+ if(!ftpc->server_os && dir[0] != '/') {
+
+ result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
+ if(result) {
+ free(dir);
+ return result;
+ }
+ Curl_safefree(ftpc->entrypath);
+ ftpc->entrypath = dir; /* remember this */
+ infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ /* also save it where getinfo can access it: */
+ data->state.most_recent_ftp_entrypath = ftpc->entrypath;
+ state(conn, FTP_SYST);
+ break;
+ }
+
+ Curl_safefree(ftpc->entrypath);
+ ftpc->entrypath = dir; /* remember this */
+ infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ /* also save it where getinfo can access it: */
+ data->state.most_recent_ftp_entrypath = ftpc->entrypath;
+ }
+ else {
+ /* couldn't get the path */
+ free(dir);
+ infof(data, "Failed to figure out path\n");
+ }
+ }
+ state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ break;
+
+ case FTP_SYST:
+ if(ftpcode == 215) {
+ char *ptr=&data->state.buffer[4]; /* start on the first letter */
+ char *os;
+ char *store;
+
+ os = malloc(nread + 1);
+ if(!os)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Reply format is like
+ 215<space><OS-name><space><commentary>
+ */
+ while(*ptr == ' ')
+ ptr++;
+ for(store = os; *ptr && *ptr != ' ';)
+ *store++ = *ptr++;
+ *store = '\0'; /* zero terminate */
+
+ /* Check for special servers here. */
+
+ if(strequal(os, "OS/400")) {
+ /* Force OS400 name format 1. */
+ result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
+ if(result) {
+ free(os);
+ return result;
+ }
+ /* remember target server OS */
+ Curl_safefree(ftpc->server_os);
+ ftpc->server_os = os;
+ state(conn, FTP_NAMEFMT);
+ break;
+ }
+ else {
+ /* Nothing special for the target server. */
+ /* remember target server OS */
+ Curl_safefree(ftpc->server_os);
+ ftpc->server_os = os;
+ }
+ }
+ else {
+ /* Cannot identify server OS. Continue anyway and cross fingers. */
+ }
+
+ state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ break;
+
+ case FTP_NAMEFMT:
+ if(ftpcode == 250) {
+ /* Name format change successful: reload initial path. */
+ ftp_state_pwd(conn);
+ break;
+ }
+
+ state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ break;
+
+ case FTP_QUOTE:
+ case FTP_POSTQUOTE:
+ case FTP_RETR_PREQUOTE:
+ case FTP_STOR_PREQUOTE:
+ if((ftpcode >= 400) && !ftpc->count2) {
+ /* failure response code, and not allowed to fail */
+ failf(conn->data, "QUOT command failed with %03d", ftpcode);
+ return CURLE_QUOTE_ERROR;
+ }
+ result = ftp_state_quote(conn, FALSE, ftpc->state);
+ if(result)
+ return result;
+
+ break;
+
+ case FTP_CWD:
+ if(ftpcode/100 != 2) {
+ /* failure to CWD there */
+ if(conn->data->set.ftp_create_missing_dirs &&
+ ftpc->count1 && !ftpc->count2) {
+ /* try making it */
+ ftpc->count2++; /* counter to prevent CWD-MKD loops */
+ PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->count1 - 1]);
+ state(conn, FTP_MKD);
+ }
+ else {
+ /* return failure */
+ failf(data, "Server denied you to change to the given directory");
+ ftpc->cwdfail = TRUE; /* don't remember this path as we failed
+ to enter it */
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+ }
+ else {
+ /* success */
+ ftpc->count2=0;
+ if(++ftpc->count1 <= ftpc->dirdepth) {
+ /* send next CWD */
+ PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
+ }
+ else {
+ result = ftp_state_mdtm(conn);
+ if(result)
+ return result;
+ }
+ }
+ break;
+
+ case FTP_MKD:
+ if((ftpcode/100 != 2) && !ftpc->count3--) {
+ /* failure to MKD the dir */
+ failf(data, "Failed to MKD dir: %03d", ftpcode);
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+ state(conn, FTP_CWD);
+ /* send CWD */
+ PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
+ break;
+
+ case FTP_MDTM:
+ result = ftp_state_mdtm_resp(conn, ftpcode);
+ break;
+
+ case FTP_TYPE:
+ case FTP_LIST_TYPE:
+ case FTP_RETR_TYPE:
+ case FTP_STOR_TYPE:
+ result = ftp_state_type_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_SIZE:
+ case FTP_RETR_SIZE:
+ case FTP_STOR_SIZE:
+ result = ftp_state_size_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_REST:
+ case FTP_RETR_REST:
+ result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_PRET:
+ if(ftpcode != 200) {
+ /* there only is this one standard OK return code. */
+ failf(data, "PRET command not accepted: %03d", ftpcode);
+ return CURLE_FTP_PRET_FAILED;
+ }
+ result = ftp_state_use_pasv(conn);
+ break;
+
+ case FTP_PASV:
+ result = ftp_state_pasv_resp(conn, ftpcode);
+ break;
+
+ case FTP_PORT:
+ result = ftp_state_port_resp(conn, ftpcode);
+ break;
+
+ case FTP_LIST:
+ case FTP_RETR:
+ result = ftp_state_get_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_STOR:
+ result = ftp_state_stor_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, FTP_STOP);
+ break;
+ }
+ } /* if(ftpcode) */
+
+ return result;
+}
+
+
+/* called repeatedly until done from multi.c */
+static CURLcode ftp_multi_statemach(struct connectdata *conn,
+ bool *done)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
+
+ /* Check for the state outside of the Curl_socket_ready() return code checks
+ since at times we are in fact already in this state when this function
+ gets called. */
+ *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode ftp_block_statemach(struct connectdata *conn)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ CURLcode result = CURLE_OK;
+
+ while(ftpc->state != FTP_STOP) {
+ result = Curl_pp_statemach(pp, TRUE);
+ if(result)
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * ftp_connect() should do everything that is to be considered a part of
+ * the connection phase.
+ *
+ * The variable 'done' points to will be TRUE if the protocol-layer connect
+ * phase is done when this function returns, or FALSE if not.
+ *
+ */
+static CURLcode ftp_connect(struct connectdata *conn,
+ bool *done) /* see description above */
+{
+ CURLcode result;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections on ftp */
+ connkeep(conn, "FTP default");
+
+ pp->response_time = RESP_TIMEOUT; /* set default response time-out */
+ pp->statemach_act = ftp_statemach_act;
+ pp->endofresp = ftp_endofresp;
+ pp->conn = conn;
+
+ if(conn->handler->flags & PROTOPT_SSL) {
+ /* BLOCKING */
+ result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ if(result)
+ return result;
+ }
+
+ Curl_pp_init(pp); /* init the generic pingpong data */
+
+ /* When we connect, we start in the state where we await the 220
+ response */
+ state(conn, FTP_WAIT220);
+
+ result = ftp_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ ssize_t nread;
+ int ftpcode;
+ CURLcode result = CURLE_OK;
+ bool was_ctl_valid = ftpc->ctl_valid;
+ char *path;
+ const char *path_to_use = data->state.path;
+
+ if(!ftp)
+ /* When the easy handle is removed from the multi while libcurl is still
+ * trying to resolve the host name, it seems that the ftp struct is not
+ * yet initialized, but the removal action calls Curl_done() which calls
+ * this function. So we simply return success if no ftp pointer is set.
+ */
+ return CURLE_OK;
+
+ switch(status) {
+ case CURLE_BAD_DOWNLOAD_RESUME:
+ case CURLE_FTP_WEIRD_PASV_REPLY:
+ case CURLE_FTP_PORT_FAILED:
+ case CURLE_FTP_ACCEPT_FAILED:
+ case CURLE_FTP_ACCEPT_TIMEOUT:
+ case CURLE_FTP_COULDNT_SET_TYPE:
+ case CURLE_FTP_COULDNT_RETR_FILE:
+ case CURLE_PARTIAL_FILE:
+ case CURLE_UPLOAD_FAILED:
+ case CURLE_REMOTE_ACCESS_DENIED:
+ case CURLE_FILESIZE_EXCEEDED:
+ case CURLE_REMOTE_FILE_NOT_FOUND:
+ case CURLE_WRITE_ERROR:
+ /* the connection stays alive fine even though this happened */
+ /* fall-through */
+ case CURLE_OK: /* doesn't affect the control connection's status */
+ if(!premature) {
+ ftpc->ctl_valid = was_ctl_valid;
+ break;
+ }
+ /* until we cope better with prematurely ended requests, let them
+ * fallback as if in complete failure */
+ default: /* by default, an error means the control connection is
+ wedged and should not be used anymore */
+ ftpc->ctl_valid = FALSE;
+ ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the
+ current path, as this connection is going */
+ connclose(conn, "FTP ended with bad error code");
+ result = status; /* use the already set error code */
+ break;
+ }
+
+ /* now store a copy of the directory we are in */
+ free(ftpc->prevpath);
+
+ if(data->set.wildcardmatch) {
+ if(data->set.chunk_end && ftpc->file) {
+ data->set.chunk_end(data->wildcard.customptr);
+ }
+ ftpc->known_filesize = -1;
+ }
+
+ /* get the "raw" path */
+ path = curl_easy_unescape(data, path_to_use, 0, NULL);
+ if(!path) {
+ /* out of memory, but we can limp along anyway (and should try to
+ * since we may already be in the out of memory cleanup path) */
+ if(!result)
+ result = CURLE_OUT_OF_MEMORY;
+ ftpc->ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
+ ftpc->prevpath = NULL; /* no path remembering */
+ }
+ else {
+ size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */
+ size_t dlen = strlen(path)-flen;
+ if(!ftpc->cwdfail) {
+ if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) {
+ ftpc->prevpath = path;
+ if(flen)
+ /* if 'path' is not the whole string */
+ ftpc->prevpath[dlen]=0; /* terminate */
+ }
+ else {
+ /* we never changed dir */
+ ftpc->prevpath=strdup("");
+ free(path);
+ }
+ if(ftpc->prevpath)
+ infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
+ }
+ else {
+ ftpc->prevpath = NULL; /* no path */
+ free(path);
+ }
+ }
+ /* free the dir tree and file parts */
+ freedirs(ftpc);
+
+ /* shut down the socket to inform the server we're done */
+
+#ifdef _WIN32_WCE
+ shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */
+#endif
+
+ if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
+ if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
+ /* partial download completed */
+ result = Curl_pp_sendf(pp, "%s", "ABOR");
+ if(result) {
+ failf(data, "Failure sending ABOR command: %s",
+ curl_easy_strerror(result));
+ ftpc->ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "ABOR command failed"); /* connection closure */
+ }
+ }
+
+ if(conn->ssl[SECONDARYSOCKET].use) {
+ /* The secondary socket is using SSL so we must close down that part
+ first before we close the socket for real */
+ Curl_ssl_close(conn, SECONDARYSOCKET);
+
+ /* Note that we keep "use" set to TRUE since that (next) connection is
+ still requested to use SSL */
+ }
+ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
+ conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
+ }
+ }
+
+ if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
+ pp->pending_resp && !premature) {
+ /*
+ * Let's see what the server says about the transfer we just performed,
+ * but lower the timeout as sometimes this connection has died while the
+ * data has been transferred. This happens when doing through NATs etc that
+ * abandon old silent connections.
+ */
+ long old_time = pp->response_time;
+
+ pp->response_time = 60*1000; /* give it only a minute for now */
+ pp->response = Curl_tvnow(); /* timeout relative now */
+
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+
+ pp->response_time = old_time; /* set this back to previous value */
+
+ if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
+ failf(data, "control connection looks dead");
+ ftpc->ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
+ }
+
+ if(result)
+ return result;
+
+ if(ftpc->dont_check && data->req.maxdownload > 0) {
+ /* we have just sent ABOR and there is no reliable way to check if it was
+ * successful or not; we have to close the connection now */
+ infof(data, "partial download completed, closing connection\n");
+ connclose(conn, "Partial download with no ability to check");
+ return result;
+ }
+
+ if(!ftpc->dont_check) {
+ /* 226 Transfer complete, 250 Requested file action okay, completed. */
+ if((ftpcode != 226) && (ftpcode != 250)) {
+ failf(data, "server did not report OK, got %d", ftpcode);
+ result = CURLE_PARTIAL_FILE;
+ }
+ }
+ }
+
+ if(result || premature)
+ /* the response code from the transfer showed an error already so no
+ use checking further */
+ ;
+ else if(data->set.upload) {
+ if((-1 != data->state.infilesize) &&
+ (data->state.infilesize != *ftp->bytecountp) &&
+ !data->set.crlf &&
+ (ftp->transfer == FTPTRANSFER_BODY)) {
+ failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
+ " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
+ *ftp->bytecountp, data->state.infilesize);
+ result = CURLE_PARTIAL_FILE;
+ }
+ }
+ else {
+ if((-1 != data->req.size) &&
+ (data->req.size != *ftp->bytecountp) &&
+#ifdef CURL_DO_LINEEND_CONV
+ /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
+ * we'll check to see if the discrepancy can be explained by the number
+ * of CRLFs we've changed to LFs.
+ */
+ ((data->req.size + data->state.crlf_conversions) !=
+ *ftp->bytecountp) &&
+#endif /* CURL_DO_LINEEND_CONV */
+ (data->req.maxdownload != *ftp->bytecountp)) {
+ failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
+ " bytes", *ftp->bytecountp);
+ result = CURLE_PARTIAL_FILE;
+ }
+ else if(!ftpc->dont_check &&
+ !*ftp->bytecountp &&
+ (data->req.size>0)) {
+ failf(data, "No data was received!");
+ result = CURLE_FTP_COULDNT_RETR_FILE;
+ }
+ }
+
+ /* clear these for next connection */
+ ftp->transfer = FTPTRANSFER_BODY;
+ ftpc->dont_check = FALSE;
+
+ /* Send any post-transfer QUOTE strings? */
+ if(!status && !result && !premature && data->set.postquote)
+ result = ftp_sendquote(conn, data->set.postquote);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_sendquote()
+ *
+ * Where a 'quote' means a list of custom commands to send to the server.
+ * The quote list is passed as an argument.
+ *
+ * BLOCKING
+ */
+
+static
+CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
+{
+ struct curl_slist *item;
+ ssize_t nread;
+ int ftpcode;
+ CURLcode result;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+
+ item = quote;
+ while(item) {
+ if(item->data) {
+ char *cmd = item->data;
+ bool acceptfail = FALSE;
+
+ /* if a command starts with an asterisk, which a legal FTP command never
+ can, the command will be allowed to fail without it causing any
+ aborts or cancels etc. It will cause libcurl to act as if the command
+ is successful, whatever the server reponds. */
+
+ if(cmd[0] == '*') {
+ cmd++;
+ acceptfail = TRUE;
+ }
+
+ PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
+
+ pp->response = Curl_tvnow(); /* timeout relative now */
+
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
+
+ if(!acceptfail && (ftpcode >= 400)) {
+ failf(conn->data, "QUOT string not accepted: %s", cmd);
+ return CURLE_QUOTE_ERROR;
+ }
+ }
+
+ item = item->next;
+ }
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * ftp_need_type()
+ *
+ * Returns TRUE if we in the current situation should send TYPE
+ */
+static int ftp_need_type(struct connectdata *conn,
+ bool ascii_wanted)
+{
+ return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I');
+}
+
+/***********************************************************************
+ *
+ * ftp_nb_type()
+ *
+ * Set TYPE. We only deal with ASCII or BINARY so this function
+ * sets one of them.
+ * If the transfer type is not sent, simulate on OK response in newstate
+ */
+static CURLcode ftp_nb_type(struct connectdata *conn,
+ bool ascii, ftpstate newstate)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result;
+ char want = (char)(ascii?'A':'I');
+
+ if(ftpc->transfertype == want) {
+ state(conn, newstate);
+ return ftp_state_type_resp(conn, 200, newstate);
+ }
+
+ PPSENDF(&ftpc->pp, "TYPE %c", want);
+ state(conn, newstate);
+
+ /* keep track of our current transfer type */
+ ftpc->transfertype = want;
+ return CURLE_OK;
+}
+
+/***************************************************************************
+ *
+ * ftp_pasv_verbose()
+ *
+ * This function only outputs some informationals about this second connection
+ * when we've issued a PASV command before and thus we have connected to a
+ * possibly new IP address.
+ *
+ */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void
+ftp_pasv_verbose(struct connectdata *conn,
+ Curl_addrinfo *ai,
+ char *newhost, /* ascii version */
+ int port)
+{
+ char buf[256];
+ Curl_printable_address(ai, buf, sizeof(buf));
+ infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
+}
+#endif
+
+/*
+ Check if this is a range download, and if so, set the internal variables
+ properly.
+ */
+
+static CURLcode ftp_range(struct connectdata *conn)
+{
+ curl_off_t from, to;
+ char *ptr;
+ char *ptr2;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(data->state.use_range && data->state.range) {
+ from=curlx_strtoofft(data->state.range, &ptr, 0);
+ while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ ptr++;
+ to=curlx_strtoofft(ptr, &ptr2, 0);
+ if(ptr == ptr2) {
+ /* we didn't get any digit */
+ to=-1;
+ }
+ if((-1 == to) && (from>=0)) {
+ /* X - */
+ data->state.resume_from = from;
+ DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T
+ " to end of file\n", from));
+ }
+ else if(from < 0) {
+ /* -Y */
+ data->req.maxdownload = -from;
+ data->state.resume_from = from;
+ DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
+ " bytes\n", -from));
+ }
+ else {
+ /* X-Y */
+ data->req.maxdownload = (to-from)+1; /* include last byte */
+ data->state.resume_from = from;
+ DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, data->req.maxdownload));
+ }
+ DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T
+ " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, to, data->req.maxdownload));
+ ftpc->dont_check = TRUE; /* dont check for successful transfer */
+ }
+ else
+ data->req.maxdownload = -1;
+ return CURLE_OK;
+}
+
+
+/*
+ * ftp_do_more()
+ *
+ * This function shall be called when the second FTP (data) connection is
+ * connected.
+ *
+ * 'complete' can return 0 for incomplete, 1 for done and -1 for go back
+ * (which basically is only for when PASV is being sent to retry a failed
+ * EPSV).
+ */
+
+static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
+{
+ struct SessionHandle *data=conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ bool complete = FALSE;
+
+ /* the ftp struct is inited in ftp_connect() */
+ struct FTP *ftp = data->req.protop;
+
+ /* if the second connection isn't done yet, wait for it */
+ if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
+ if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
+ /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
+ aren't used so we blank their arguments. TODO: make this nicer */
+ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
+
+ return result;
+ }
+
+ result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
+
+ /* Ready to do more? */
+ if(connected) {
+ DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
+ if(conn->bits.proxy) {
+ infof(data, "Connection to proxy confirmed\n");
+ result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
+ }
+ }
+ else {
+ if(result && (ftpc->count1 == 0)) {
+ *completep = -1; /* go back to DOING please */
+ /* this is a EPSV connect failing, try PASV instead */
+ return ftp_epsv_disable(conn);
+ }
+ return result;
+ }
+ }
+
+ if(ftpc->state) {
+ /* already in a state so skip the intial commands.
+ They are only done to kickstart the do_more state */
+ result = ftp_multi_statemach(conn, &complete);
+
+ *completep = (int)complete;
+
+ /* if we got an error or if we don't wait for a data connection return
+ immediately */
+ if(result || (ftpc->wait_data_conn != TRUE))
+ return result;
+
+ if(ftpc->wait_data_conn)
+ /* if we reach the end of the FTP state machine here, *complete will be
+ TRUE but so is ftpc->wait_data_conn, which says we need to wait for
+ the data connection and therefore we're not actually complete */
+ *completep = 0;
+ }
+
+ if(ftp->transfer <= FTPTRANSFER_INFO) {
+ /* a transfer is about to take place, or if not a file name was given
+ so we'll do a SIZE on it later and then we need the right TYPE first */
+
+ if(ftpc->wait_data_conn == TRUE) {
+ bool serv_conned;
+
+ result = ReceivedServerConnect(conn, &serv_conned);
+ if(result)
+ return result; /* Failed to accept data connection */
+
+ if(serv_conned) {
+ /* It looks data connection is established */
+ result = AcceptServerConnect(conn);
+ ftpc->wait_data_conn = FALSE;
+ if(!result)
+ result = InitiateTransfer(conn);
+
+ if(result)
+ return result;
+
+ *completep = 1; /* this state is now complete when the server has
+ connected back to us */
+ }
+ }
+ else if(data->set.upload) {
+ result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
+ if(result)
+ return result;
+
+ result = ftp_multi_statemach(conn, &complete);
+ *completep = (int)complete;
+ }
+ else {
+ /* download */
+ ftp->downloadsize = -1; /* unknown as of yet */
+
+ result = ftp_range(conn);
+ if(result)
+ ;
+ else if(data->set.ftp_list_only || !ftpc->file) {
+ /* The specified path ends with a slash, and therefore we think this
+ is a directory that is requested, use LIST. But before that we
+ need to set ASCII transfer mode. */
+
+ /* But only if a body transfer was requested. */
+ if(ftp->transfer == FTPTRANSFER_BODY) {
+ result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE);
+ if(result)
+ return result;
+ }
+ /* otherwise just fall through */
+ }
+ else {
+ result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
+ if(result)
+ return result;
+ }
+
+ result = ftp_multi_statemach(conn, &complete);
+ *completep = (int)complete;
+ }
+ return result;
+ }
+
+ if(!result && (ftp->transfer != FTPTRANSFER_BODY))
+ /* no data to transfer. FIX: it feels like a kludge to have this here
+ too! */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ if(!ftpc->wait_data_conn) {
+ /* no waiting for the data connection so this is now complete */
+ *completep = 1;
+ DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
+ }
+
+ return result;
+}
+
+
+
+/***********************************************************************
+ *
+ * ftp_perform()
+ *
+ * This is the actual DO function for FTP. Get a file/directory according to
+ * the options previously setup.
+ */
+
+static
+CURLcode ftp_perform(struct connectdata *conn,
+ bool *connected, /* connect status after PASV / PORT */
+ bool *dophase_done)
+{
+ /* this is FTP and no proxy */
+ CURLcode result=CURLE_OK;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(conn->data->set.opt_no_body) {
+ /* requested no body means no transfer... */
+ struct FTP *ftp = conn->data->req.protop;
+ ftp->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* start the first command in the DO phase */
+ result = ftp_state_quote(conn, TRUE, FTP_QUOTE);
+ if(result)
+ return result;
+
+ /* run the state-machine */
+ result = ftp_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[SECONDARYSOCKET];
+
+ infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete1\n"));
+
+ return result;
+}
+
+static void wc_data_dtor(void *ptr)
+{
+ struct ftp_wc_tmpdata *tmp = ptr;
+ if(tmp)
+ Curl_ftp_parselist_data_free(&tmp->parser);
+ free(tmp);
+}
+
+static CURLcode init_wc_data(struct connectdata *conn)
+{
+ char *last_slash;
+ char *path = conn->data->state.path;
+ struct WildcardData *wildcard = &(conn->data->wildcard);
+ CURLcode result = CURLE_OK;
+ struct ftp_wc_tmpdata *ftp_tmp;
+
+ last_slash = strrchr(conn->data->state.path, '/');
+ if(last_slash) {
+ last_slash++;
+ if(last_slash[0] == '\0') {
+ wildcard->state = CURLWC_CLEAN;
+ result = ftp_parse_url_path(conn);
+ return result;
+ }
+ else {
+ wildcard->pattern = strdup(last_slash);
+ if(!wildcard->pattern)
+ return CURLE_OUT_OF_MEMORY;
+ last_slash[0] = '\0'; /* cut file from path */
+ }
+ }
+ else { /* there is only 'wildcard pattern' or nothing */
+ if(path[0]) {
+ wildcard->pattern = strdup(path);
+ if(!wildcard->pattern)
+ return CURLE_OUT_OF_MEMORY;
+ path[0] = '\0';
+ }
+ else { /* only list */
+ wildcard->state = CURLWC_CLEAN;
+ result = ftp_parse_url_path(conn);
+ return result;
+ }
+ }
+
+ /* program continues only if URL is not ending with slash, allocate needed
+ resources for wildcard transfer */
+
+ /* allocate ftp protocol specific temporary wildcard data */
+ ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata));
+ if(!ftp_tmp) {
+ Curl_safefree(wildcard->pattern);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* INITIALIZE parselist structure */
+ ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
+ if(!ftp_tmp->parser) {
+ Curl_safefree(wildcard->pattern);
+ free(ftp_tmp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
+ wildcard->tmp_dtor = wc_data_dtor;
+
+ /* wildcard does not support NOCWD option (assert it?) */
+ if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
+ conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
+
+ /* try to parse ftp url */
+ result = ftp_parse_url_path(conn);
+ if(result) {
+ Curl_safefree(wildcard->pattern);
+ wildcard->tmp_dtor(wildcard->tmp);
+ wildcard->tmp_dtor = ZERO_NULL;
+ wildcard->tmp = NULL;
+ return result;
+ }
+
+ wildcard->path = strdup(conn->data->state.path);
+ if(!wildcard->path) {
+ Curl_safefree(wildcard->pattern);
+ wildcard->tmp_dtor(wildcard->tmp);
+ wildcard->tmp_dtor = ZERO_NULL;
+ wildcard->tmp = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* backup old write_function */
+ ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
+ /* parsing write function */
+ conn->data->set.fwrite_func = Curl_ftp_parselist;
+ /* backup old file descriptor */
+ ftp_tmp->backup.file_descriptor = conn->data->set.out;
+ /* let the writefunc callback know what curl pointer is working with */
+ conn->data->set.out = conn;
+
+ infof(conn->data, "Wildcard - Parsing started\n");
+ return CURLE_OK;
+}
+
+/* This is called recursively */
+static CURLcode wc_statemach(struct connectdata *conn)
+{
+ struct WildcardData * const wildcard = &(conn->data->wildcard);
+ CURLcode result = CURLE_OK;
+
+ switch (wildcard->state) {
+ case CURLWC_INIT:
+ result = init_wc_data(conn);
+ if(wildcard->state == CURLWC_CLEAN)
+ /* only listing! */
+ break;
+ else
+ wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
+ break;
+
+ case CURLWC_MATCHING: {
+ /* In this state is LIST response successfully parsed, so lets restore
+ previous WRITEFUNCTION callback and WRITEDATA pointer */
+ struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
+ conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
+ conn->data->set.out = ftp_tmp->backup.file_descriptor;
+ ftp_tmp->backup.write_function = ZERO_NULL;
+ ftp_tmp->backup.file_descriptor = NULL;
+ wildcard->state = CURLWC_DOWNLOADING;
+
+ if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
+ /* error found in LIST parsing */
+ wildcard->state = CURLWC_CLEAN;
+ return wc_statemach(conn);
+ }
+ else if(wildcard->filelist->size == 0) {
+ /* no corresponding file */
+ wildcard->state = CURLWC_CLEAN;
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
+ return wc_statemach(conn);
+ }
+
+ case CURLWC_DOWNLOADING: {
+ /* filelist has at least one file, lets get first one */
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct curl_fileinfo *finfo = wildcard->filelist->head->ptr;
+
+ char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
+ if(!tmp_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* switch default "state.pathbuffer" and tmp_path, good to see
+ ftp_parse_url_path function to understand this trick */
+ Curl_safefree(conn->data->state.pathbuffer);
+ conn->data->state.pathbuffer = tmp_path;
+ conn->data->state.path = tmp_path;
+
+ infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
+ if(conn->data->set.chunk_bgn) {
+ long userresponse = conn->data->set.chunk_bgn(
+ finfo, wildcard->customptr, (int)wildcard->filelist->size);
+ switch(userresponse) {
+ case CURL_CHUNK_BGN_FUNC_SKIP:
+ infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
+ finfo->filename);
+ wildcard->state = CURLWC_SKIP;
+ return wc_statemach(conn);
+ case CURL_CHUNK_BGN_FUNC_FAIL:
+ return CURLE_CHUNK_FAILED;
+ }
+ }
+
+ if(finfo->filetype != CURLFILETYPE_FILE) {
+ wildcard->state = CURLWC_SKIP;
+ return wc_statemach(conn);
+ }
+
+ if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
+ ftpc->known_filesize = finfo->size;
+
+ result = ftp_parse_url_path(conn);
+ if(result)
+ return result;
+
+ /* we don't need the Curl_fileinfo of first file anymore */
+ Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
+
+ if(wildcard->filelist->size == 0) { /* remains only one file to down. */
+ wildcard->state = CURLWC_CLEAN;
+ /* after that will be ftp_do called once again and no transfer
+ will be done because of CURLWC_CLEAN state */
+ return CURLE_OK;
+ }
+ } break;
+
+ case CURLWC_SKIP: {
+ if(conn->data->set.chunk_end)
+ conn->data->set.chunk_end(conn->data->wildcard.customptr);
+ Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
+ wildcard->state = (wildcard->filelist->size == 0) ?
+ CURLWC_CLEAN : CURLWC_DOWNLOADING;
+ return wc_statemach(conn);
+ }
+
+ case CURLWC_CLEAN: {
+ struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
+ result = CURLE_OK;
+ if(ftp_tmp)
+ result = Curl_ftp_parselist_geterror(ftp_tmp->parser);
+
+ wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
+ } break;
+
+ case CURLWC_DONE:
+ case CURLWC_ERROR:
+ break;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (ftp_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode ftp_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ *done = FALSE; /* default to false */
+ ftpc->wait_data_conn = FALSE; /* default to no such wait */
+
+ if(conn->data->set.wildcardmatch) {
+ result = wc_statemach(conn);
+ if(conn->data->wildcard.state == CURLWC_SKIP ||
+ conn->data->wildcard.state == CURLWC_DONE) {
+ /* do not call ftp_regular_transfer */
+ return CURLE_OK;
+ }
+ if(result) /* error, loop or skipping the file */
+ return result;
+ }
+ else { /* no wildcard FSM needed */
+ result = ftp_parse_url_path(conn);
+ if(result)
+ return result;
+ }
+
+ result = ftp_regular_transfer(conn, done);
+
+ return result;
+}
+
+
+CURL_STATIC CURLcode Curl_ftpsendf(struct connectdata *conn,
+ const char *fmt, ...)
+{
+ ssize_t bytes_written;
+#define SBUF_SIZE 1024
+ char s[SBUF_SIZE];
+ size_t write_len;
+ char *sptr=s;
+ CURLcode result = CURLE_OK;
+#ifdef HAVE_GSSAPI
+ enum protection_level data_sec = conn->data_prot;
+#endif
+
+ va_list ap;
+ va_start(ap, fmt);
+ write_len = vsnprintf(s, SBUF_SIZE-3, fmt, ap);
+ va_end(ap);
+
+ strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
+ write_len +=2;
+
+ bytes_written=0;
+
+ result = Curl_convert_to_network(conn->data, s, write_len);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ for(;;) {
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CMD;
+#endif
+ result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
+ &bytes_written);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
+ conn->data_prot = data_sec;
+#endif
+
+ if(result)
+ break;
+
+ if(conn->data->set.verbose)
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT,
+ sptr, (size_t)bytes_written, conn);
+
+ if(bytes_written != (ssize_t)write_len) {
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_quit()
+ *
+ * This should be called before calling sclose() on an ftp control connection
+ * (not data connections). We should then wait for the response from the
+ * server before returning. The calling code should then try to close the
+ * connection.
+ *
+ */
+static CURLcode ftp_quit(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ if(conn->proto.ftpc.ctl_valid) {
+ result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT");
+ if(result) {
+ failf(conn->data, "Failure sending QUIT command: %s",
+ curl_easy_strerror(result));
+ conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "QUIT command failed"); /* mark for connection closure */
+ state(conn, FTP_STOP);
+ return result;
+ }
+
+ state(conn, FTP_QUIT);
+
+ result = ftp_block_statemach(conn);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_disconnect()
+ *
+ * Disconnect from an FTP server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct ftp_conn *ftpc= &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to.
+
+ ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
+ will try to send the QUIT command, otherwise it will just return.
+ */
+ if(dead_connection)
+ ftpc->ctl_valid = FALSE;
+
+ /* The FTP session may or may not have been allocated/setup at this point! */
+ (void)ftp_quit(conn); /* ignore errors on the QUIT */
+
+ if(ftpc->entrypath) {
+ struct SessionHandle *data = conn->data;
+ if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
+ data->state.most_recent_ftp_entrypath = NULL;
+ }
+ free(ftpc->entrypath);
+ ftpc->entrypath = NULL;
+ }
+
+ freedirs(ftpc);
+ free(ftpc->prevpath);
+ ftpc->prevpath = NULL;
+ free(ftpc->server_os);
+ ftpc->server_os = NULL;
+
+ Curl_pp_disconnect(pp);
+
+#ifdef HAVE_GSSAPI
+ Curl_sec_end(conn);
+#endif
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * ftp_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ *
+ */
+static
+CURLcode ftp_parse_url_path(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ /* the ftp struct is already inited in ftp_connect() */
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ const char *slash_pos; /* position of the first '/' char in curpos */
+ const char *path_to_use = data->state.path;
+ const char *cur_pos;
+ const char *filename = NULL;
+
+ cur_pos = path_to_use; /* current position in path. point at the begin
+ of next path component */
+
+ ftpc->ctl_valid = FALSE;
+ ftpc->cwdfail = FALSE;
+
+ switch(data->set.ftp_filemethod) {
+ case FTPFILE_NOCWD:
+ /* fastest, but less standard-compliant */
+
+ /*
+ The best time to check whether the path is a file or directory is right
+ here. so:
+
+ the first condition in the if() right here, is there just in case
+ someone decides to set path to NULL one day
+ */
+ if(data->state.path &&
+ data->state.path[0] &&
+ (data->state.path[strlen(data->state.path) - 1] != '/') )
+ filename = data->state.path; /* this is a full file path */
+ /*
+ ftpc->file is not used anywhere other than for operations on a file.
+ In other words, never for directory operations.
+ So we can safely leave filename as NULL here and use it as a
+ argument in dir/file decisions.
+ */
+ break;
+
+ case FTPFILE_SINGLECWD:
+ /* get the last slash */
+ if(!path_to_use[0]) {
+ /* no dir, no file */
+ ftpc->dirdepth = 0;
+ break;
+ }
+ slash_pos=strrchr(cur_pos, '/');
+ if(slash_pos || !*cur_pos) {
+ size_t dirlen = slash_pos-cur_pos;
+
+ ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
+ if(!ftpc->dirs)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(!dirlen)
+ dirlen++;
+
+ ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
+ slash_pos ? curlx_uztosi(dirlen) : 1,
+ NULL);
+ if(!ftpc->dirs[0]) {
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ftpc->dirdepth = 1; /* we consider it to be a single dir */
+ filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
+ }
+ else
+ filename = cur_pos; /* this is a file name only */
+ break;
+
+ default: /* allow pretty much anything */
+ case FTPFILE_MULTICWD:
+ ftpc->dirdepth = 0;
+ ftpc->diralloc = 5; /* default dir depth to allocate */
+ ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0]));
+ if(!ftpc->dirs)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* we have a special case for listing the root dir only */
+ if(strequal(path_to_use, "/")) {
+ cur_pos++; /* make it point to the zero byte */
+ ftpc->dirs[0] = strdup("/");
+ ftpc->dirdepth++;
+ }
+ else {
+ /* parse the URL path into separate path components */
+ while((slash_pos = strchr(cur_pos, '/')) != NULL) {
+ /* 1 or 0 pointer offset to indicate absolute directory */
+ ssize_t absolute_dir = ((cur_pos - data->state.path > 0) &&
+ (ftpc->dirdepth == 0))?1:0;
+
+ /* seek out the next path component */
+ if(slash_pos-cur_pos) {
+ /* we skip empty path components, like "x//y" since the FTP command
+ CWD requires a parameter and a non-existent parameter a) doesn't
+ work on many servers and b) has no effect on the others. */
+ int len = curlx_sztosi(slash_pos - cur_pos + absolute_dir);
+ ftpc->dirs[ftpc->dirdepth] =
+ curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL);
+ if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */
+ failf(data, "no memory");
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) {
+ free(ftpc->dirs[ftpc->dirdepth]);
+ freedirs(ftpc);
+ return CURLE_URL_MALFORMAT;
+ }
+ }
+ else {
+ cur_pos = slash_pos + 1; /* jump to the rest of the string */
+ if(!ftpc->dirdepth) {
+ /* path starts with a slash, add that as a directory */
+ ftpc->dirs[ftpc->dirdepth] = strdup("/");
+ if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */
+ failf(data, "no memory");
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ continue;
+ }
+
+ cur_pos = slash_pos + 1; /* jump to the rest of the string */
+ if(++ftpc->dirdepth >= ftpc->diralloc) {
+ /* enlarge array */
+ char **bigger;
+ ftpc->diralloc *= 2; /* double the size each time */
+ bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0]));
+ if(!bigger) {
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ftpc->dirs = bigger;
+ }
+ }
+ }
+ filename = cur_pos; /* the rest is the file name */
+ break;
+ } /* switch */
+
+ if(filename && *filename) {
+ ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL);
+ if(NULL == ftpc->file) {
+ freedirs(ftpc);
+ failf(data, "no memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(isBadFtpString(ftpc->file)) {
+ freedirs(ftpc);
+ return CURLE_URL_MALFORMAT;
+ }
+ }
+ else
+ ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL
+ pointer */
+
+ if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
+ /* We need a file name when uploading. Return error! */
+ failf(data, "Uploading to a URL without a file name!");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ ftpc->cwddone = FALSE; /* default to not done */
+
+ if(ftpc->prevpath) {
+ /* prevpath is "raw" so we convert the input path before we compare the
+ strings */
+ int dlen;
+ char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen);
+ if(!path) {
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ dlen -= ftpc->file?curlx_uztosi(strlen(ftpc->file)):0;
+ if((dlen == curlx_uztosi(strlen(ftpc->prevpath))) &&
+ strnequal(path, ftpc->prevpath, dlen)) {
+ infof(data, "Request has same path as previous transfer\n");
+ ftpc->cwddone = TRUE;
+ }
+ free(path);
+ }
+
+ return CURLE_OK;
+}
+
+/* call this when the DO phase has completed */
+static CURLcode ftp_dophase_done(struct connectdata *conn,
+ bool connected)
+{
+ struct FTP *ftp = conn->data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(connected) {
+ int completed;
+ CURLcode result = ftp_do_more(conn, &completed);
+
+ if(result) {
+ if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
+ /* close the second socket if it was created already */
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
+ }
+ return result;
+ }
+ }
+
+ if(ftp->transfer != FTPTRANSFER_BODY)
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ else if(!connected)
+ /* since we didn't connect now, we want do_more to get called */
+ conn->bits.do_more = TRUE;
+
+ ftpc->ctl_valid = TRUE; /* seems good */
+
+ return CURLE_OK;
+}
+
+/* called from multi.c while DOing */
+static CURLcode ftp_doing(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = ftp_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = ftp_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete2\n"));
+ }
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ *
+ * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
+ * ftp_done() function without finding any major problem.
+ */
+static
+CURLcode ftp_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result=CURLE_OK;
+ bool connected=FALSE;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ data->req.size = -1; /* make sure this is unknown at this point */
+
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ ftpc->ctl_valid = TRUE; /* starts good */
+
+ result = ftp_perform(conn,
+ &connected, /* have we connected after PASV/PORT */
+ dophase_done); /* all commands in the DO-phase done? */
+
+ if(!result) {
+
+ if(!*dophase_done)
+ /* the DO phase has not completed yet */
+ return CURLE_OK;
+
+ result = ftp_dophase_done(conn, connected);
+
+ if(result)
+ return result;
+ }
+ else
+ freedirs(ftpc);
+
+ return result;
+}
+
+static CURLcode ftp_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ char *type;
+ char command;
+ struct FTP *ftp;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel ftp operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_ftp)
+ conn->handler = &Curl_handler_ftp_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_ftps_proxy;
+#else
+ failf(data, "FTPS not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+ /* set it up as a HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+#else
+ failf(data, "FTP over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
+ if(NULL == ftp)
+ return CURLE_OUT_OF_MEMORY;
+
+ data->state.path++; /* don't include the initial slash */
+ data->state.slash_removed = TRUE; /* we've skipped the slash */
+
+ /* FTP URLs support an extension like ";type=<typecode>" that
+ * we'll try to get now! */
+ type = strstr(data->state.path, ";type=");
+
+ if(!type)
+ type = strstr(conn->host.rawalloc, ";type=");
+
+ if(type) {
+ *type = 0; /* it was in the middle of the hostname */
+ command = Curl_raw_toupper(type[6]);
+ conn->bits.type_set = TRUE;
+
+ switch (command) {
+ case 'A': /* ASCII mode */
+ data->set.prefer_ascii = TRUE;
+ break;
+
+ case 'D': /* directory mode */
+ data->set.ftp_list_only = TRUE;
+ break;
+
+ case 'I': /* binary mode */
+ default:
+ /* switch off ASCII */
+ data->set.prefer_ascii = FALSE;
+ break;
+ }
+ }
+
+ /* get some initial data into the ftp struct */
+ ftp->bytecountp = &conn->data->req.bytecount;
+ ftp->transfer = FTPTRANSFER_BODY;
+ ftp->downloadsize = 0;
+
+ /* No need to duplicate user+password, the connectdata struct won't change
+ during a session, but we re-init them here since on subsequent inits
+ since the conn struct may have changed or been replaced.
+ */
+ ftp->user = conn->user;
+ ftp->passwd = conn->passwd;
+ if(isBadFtpString(ftp->user))
+ return CURLE_URL_MALFORMAT;
+ if(isBadFtpString(ftp->passwd))
+ return CURLE_URL_MALFORMAT;
+
+ conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
+
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_FTP */
diff --git a/libcurl/src/lib/ftp.h b/libcurl/src/lib/ftp.h
new file mode 100644
index 0000000..942d104
--- /dev/null
+++ b/libcurl/src/lib/ftp.h
@@ -0,0 +1,159 @@
+#ifndef HEADER_CURL_FTP_H
+#define HEADER_CURL_FTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+
+#ifndef CURL_DISABLE_FTP
+extern const struct Curl_handler Curl_handler_ftp;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_ftps;
+#endif
+
+CURL_STATIC CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
+CURL_STATIC CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
+ int *ftpcode);
+#endif /* CURL_DISABLE_FTP */
+
+/****************************************************************************
+ * FTP unique setup
+ ***************************************************************************/
+typedef enum {
+ FTP_STOP, /* do nothing state, stops the state machine */
+ FTP_WAIT220, /* waiting for the initial 220 response immediately after
+ a connect */
+ FTP_AUTH,
+ FTP_USER,
+ FTP_PASS,
+ FTP_ACCT,
+ FTP_PBSZ,
+ FTP_PROT,
+ FTP_CCC,
+ FTP_PWD,
+ FTP_SYST,
+ FTP_NAMEFMT,
+ FTP_QUOTE, /* waiting for a response to a command sent in a quote list */
+ FTP_RETR_PREQUOTE,
+ FTP_STOR_PREQUOTE,
+ FTP_POSTQUOTE,
+ FTP_CWD, /* change dir */
+ FTP_MKD, /* if the dir didn't exist */
+ FTP_MDTM, /* to figure out the datestamp */
+ FTP_TYPE, /* to set type when doing a head-like request */
+ FTP_LIST_TYPE, /* set type when about to do a dir list */
+ FTP_RETR_TYPE, /* set type when about to RETR a file */
+ FTP_STOR_TYPE, /* set type when about to STOR a file */
+ FTP_SIZE, /* get the remote file's size for head-like request */
+ FTP_RETR_SIZE, /* get the remote file's size for RETR */
+ FTP_STOR_SIZE, /* get the size for STOR */
+ FTP_REST, /* when used to check if the server supports it in head-like */
+ FTP_RETR_REST, /* when asking for "resume" in for RETR */
+ FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */
+ FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */
+ FTP_PASV, /* generic state for PASV and EPSV, check count1 */
+ FTP_LIST, /* generic state for LIST, NLST or a custom list command */
+ FTP_RETR,
+ FTP_STOR, /* generic state for STOR and APPE */
+ FTP_QUIT,
+ FTP_LAST /* never used */
+} ftpstate;
+
+struct ftp_parselist_data; /* defined later in ftplistparser.c */
+
+struct ftp_wc_tmpdata {
+ struct ftp_parselist_data *parser;
+
+ struct {
+ curl_write_callback write_function;
+ FILE *file_descriptor;
+ } backup;
+};
+
+typedef enum {
+ FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */
+ FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */
+ FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the
+ file */
+} curl_ftpfile;
+
+/* This FTP struct is used in the SessionHandle. All FTP data that is
+ connection-oriented must be in FTP_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct FTP {
+ curl_off_t *bytecountp;
+ char *user; /* user name string */
+ char *passwd; /* password string */
+
+ /* transfer a file/body or not, done as a typedefed enum just to make
+ debuggers display the full symbol and not just the numerical value */
+ curl_pp_transfer transfer;
+ curl_off_t downloadsize;
+};
+
+
+/* ftp_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct ftp_conn {
+ struct pingpong pp;
+ char *entrypath; /* the PWD reply when we logged on */
+ char **dirs; /* realloc()ed array for path components */
+ int dirdepth; /* number of entries used in the 'dirs' array */
+ int diralloc; /* number of entries allocated for the 'dirs' array */
+ char *file; /* decoded file */
+ bool dont_check; /* Set to TRUE to prevent the final (post-transfer)
+ file size and 226/250 status check. It should still
+ read the line, just ignore the result. */
+ bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If
+ the connection has timed out or been closed, this
+ should be FALSE when it gets to Curl_ftp_quit() */
+ bool cwddone; /* if it has been determined that the proper CWD combo
+ already has been done */
+ bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
+ caching the current directory */
+ bool wait_data_conn; /* this is set TRUE if data connection is waited */
+ char *prevpath; /* conn->path from the previous transfer */
+ char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
+ and others (A/I or zero) */
+ int count1; /* general purpose counter for the state machine */
+ int count2; /* general purpose counter for the state machine */
+ int count3; /* general purpose counter for the state machine */
+ ftpstate state; /* always use ftp.c:state() to change state! */
+ ftpstate state_saved; /* transfer type saved to be reloaded after
+ data connection is established */
+ curl_off_t retr_size_saved; /* Size of retrieved file saved */
+ char * server_os; /* The target server operating system. */
+ curl_off_t known_filesize; /* file size is different from -1, if wildcard
+ LIST parsing was done and wc_statemach set
+ it */
+ /* newhost is the (allocated) IP addr or host name to connect the data
+ connection to */
+ char *newhost; /* this is the pair to connect the DATA... */
+ unsigned short newport; /* connection to */
+
+};
+
+#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */
+
+#endif /* HEADER_CURL_FTP_H */
diff --git a/libcurl/src/lib/ftplistparser.c b/libcurl/src/lib/ftplistparser.c
new file mode 100644
index 0000000..f5a6553
--- /dev/null
+++ b/libcurl/src/lib/ftplistparser.c
@@ -0,0 +1,1048 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/**
+ * Now implemented:
+ *
+ * 1) Unix version 1
+ * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
+ * 2) Unix version 2
+ * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
+ * 3) Unix version 3
+ * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
+ * 4) Unix symlink
+ * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
+ * 5) DOS style
+ * 01-29-97 11:32PM <DIR> prog
+ */
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "fileinfo.h"
+#include "llist.h"
+#include "strtoofft.h"
+#include "rawstr.h"
+#include "ftp.h"
+#include "ftplistparser.h"
+#include "curl_fnmatch.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* allocs buffer which will contain one line of LIST command response */
+#define FTP_BUFFER_ALLOCSIZE 160
+
+typedef enum {
+ PL_UNIX_TOTALSIZE = 0,
+ PL_UNIX_FILETYPE,
+ PL_UNIX_PERMISSION,
+ PL_UNIX_HLINKS,
+ PL_UNIX_USER,
+ PL_UNIX_GROUP,
+ PL_UNIX_SIZE,
+ PL_UNIX_TIME,
+ PL_UNIX_FILENAME,
+ PL_UNIX_SYMLINK
+} pl_unix_mainstate;
+
+typedef union {
+ enum {
+ PL_UNIX_TOTALSIZE_INIT = 0,
+ PL_UNIX_TOTALSIZE_READING
+ } total_dirsize;
+
+ enum {
+ PL_UNIX_HLINKS_PRESPACE = 0,
+ PL_UNIX_HLINKS_NUMBER
+ } hlinks;
+
+ enum {
+ PL_UNIX_USER_PRESPACE = 0,
+ PL_UNIX_USER_PARSING
+ } user;
+
+ enum {
+ PL_UNIX_GROUP_PRESPACE = 0,
+ PL_UNIX_GROUP_NAME
+ } group;
+
+ enum {
+ PL_UNIX_SIZE_PRESPACE = 0,
+ PL_UNIX_SIZE_NUMBER
+ } size;
+
+ enum {
+ PL_UNIX_TIME_PREPART1 = 0,
+ PL_UNIX_TIME_PART1,
+ PL_UNIX_TIME_PREPART2,
+ PL_UNIX_TIME_PART2,
+ PL_UNIX_TIME_PREPART3,
+ PL_UNIX_TIME_PART3
+ } time;
+
+ enum {
+ PL_UNIX_FILENAME_PRESPACE = 0,
+ PL_UNIX_FILENAME_NAME,
+ PL_UNIX_FILENAME_WINDOWSEOL
+ } filename;
+
+ enum {
+ PL_UNIX_SYMLINK_PRESPACE = 0,
+ PL_UNIX_SYMLINK_NAME,
+ PL_UNIX_SYMLINK_PRETARGET1,
+ PL_UNIX_SYMLINK_PRETARGET2,
+ PL_UNIX_SYMLINK_PRETARGET3,
+ PL_UNIX_SYMLINK_PRETARGET4,
+ PL_UNIX_SYMLINK_TARGET,
+ PL_UNIX_SYMLINK_WINDOWSEOL
+ } symlink;
+} pl_unix_substate;
+
+typedef enum {
+ PL_WINNT_DATE = 0,
+ PL_WINNT_TIME,
+ PL_WINNT_DIRORSIZE,
+ PL_WINNT_FILENAME
+} pl_winNT_mainstate;
+
+typedef union {
+ enum {
+ PL_WINNT_TIME_PRESPACE = 0,
+ PL_WINNT_TIME_TIME
+ } time;
+ enum {
+ PL_WINNT_DIRORSIZE_PRESPACE = 0,
+ PL_WINNT_DIRORSIZE_CONTENT
+ } dirorsize;
+ enum {
+ PL_WINNT_FILENAME_PRESPACE = 0,
+ PL_WINNT_FILENAME_CONTENT,
+ PL_WINNT_FILENAME_WINEOL
+ } filename;
+} pl_winNT_substate;
+
+/* This struct is used in wildcard downloading - for parsing LIST response */
+struct ftp_parselist_data {
+ enum {
+ OS_TYPE_UNKNOWN = 0,
+ OS_TYPE_UNIX,
+ OS_TYPE_WIN_NT
+ } os_type;
+
+ union {
+ struct {
+ pl_unix_mainstate main;
+ pl_unix_substate sub;
+ } UNIX;
+
+ struct {
+ pl_winNT_mainstate main;
+ pl_winNT_substate sub;
+ } NT;
+ } state;
+
+ CURLcode error;
+ struct curl_fileinfo *file_data;
+ unsigned int item_length;
+ size_t item_offset;
+ struct {
+ size_t filename;
+ size_t user;
+ size_t group;
+ size_t time;
+ size_t perm;
+ size_t symlink_target;
+ } offsets;
+};
+
+CURL_STATIC struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
+{
+ return calloc(1, sizeof(struct ftp_parselist_data));
+}
+
+
+CURL_STATIC void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
+{
+ free(*pl_data);
+ *pl_data = NULL;
+}
+
+
+CURL_STATIC CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
+{
+ return pl_data->error;
+}
+
+
+#define FTP_LP_MALFORMATED_PERM 0x01000000
+
+static int ftp_pl_get_permission(const char *str)
+{
+ int permissions = 0;
+ /* USER */
+ if(str[0] == 'r')
+ permissions |= 1 << 8;
+ else if(str[0] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[1] == 'w')
+ permissions |= 1 << 7;
+ else if(str[1] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+
+ if(str[2] == 'x')
+ permissions |= 1 << 6;
+ else if(str[2] == 's') {
+ permissions |= 1 << 6;
+ permissions |= 1 << 11;
+ }
+ else if(str[2] == 'S')
+ permissions |= 1 << 11;
+ else if(str[2] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ /* GROUP */
+ if(str[3] == 'r')
+ permissions |= 1 << 5;
+ else if(str[3] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[4] == 'w')
+ permissions |= 1 << 4;
+ else if(str[4] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[5] == 'x')
+ permissions |= 1 << 3;
+ else if(str[5] == 's') {
+ permissions |= 1 << 3;
+ permissions |= 1 << 10;
+ }
+ else if(str[5] == 'S')
+ permissions |= 1 << 10;
+ else if(str[5] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ /* others */
+ if(str[6] == 'r')
+ permissions |= 1 << 2;
+ else if(str[6] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[7] == 'w')
+ permissions |= 1 << 1;
+ else if(str[7] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[8] == 'x')
+ permissions |= 1;
+ else if(str[8] == 't') {
+ permissions |= 1;
+ permissions |= 1 << 9;
+ }
+ else if(str[8] == 'T')
+ permissions |= 1 << 9;
+ else if(str[8] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+
+ return permissions;
+}
+
+static void PL_ERROR(struct connectdata *conn, CURLcode err)
+{
+ struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
+ struct ftp_parselist_data *parser = tmpdata->parser;
+ if(parser->file_data)
+ Curl_fileinfo_dtor(NULL, parser->file_data);
+ parser->file_data = NULL;
+ parser->error = err;
+}
+
+static bool ftp_pl_gettime(struct ftp_parselist_data *parser, char *string)
+{
+ (void)parser;
+ (void)string;
+ /* TODO
+ * There could be possible parse timestamp from server. Leaving unimplemented
+ * for now.
+ * If you want implement this, please add CURLFINFOFLAG_KNOWN_TIME flag to
+ * parser->file_data->flags
+ *
+ * Ftp servers are giving usually these formats:
+ * Apr 11 1998 (unknown time.. set it to 00:00:00?)
+ * Apr 11 12:21 (unknown year -> set it to NOW() time?)
+ * 08-05-09 02:49PM (ms-dos format)
+ * 20100421092538 -> for MLST/MLSD response
+ */
+
+ return FALSE;
+}
+
+static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
+ struct curl_fileinfo *finfo)
+{
+ curl_fnmatch_callback compare;
+ struct WildcardData *wc = &conn->data->wildcard;
+ struct ftp_wc_tmpdata *tmpdata = wc->tmp;
+ struct curl_llist *llist = wc->filelist;
+ struct ftp_parselist_data *parser = tmpdata->parser;
+ bool add = TRUE;
+
+ /* move finfo pointers to b_data */
+ char *str = finfo->b_data;
+ finfo->filename = str + parser->offsets.filename;
+ finfo->strings.group = parser->offsets.group ?
+ str + parser->offsets.group : NULL;
+ finfo->strings.perm = parser->offsets.perm ?
+ str + parser->offsets.perm : NULL;
+ finfo->strings.target = parser->offsets.symlink_target ?
+ str + parser->offsets.symlink_target : NULL;
+ finfo->strings.time = str + parser->offsets.time;
+ finfo->strings.user = parser->offsets.user ?
+ str + parser->offsets.user : NULL;
+
+ /* get correct fnmatch callback */
+ compare = conn->data->set.fnmatch;
+ if(!compare)
+ compare = Curl_fnmatch;
+
+ /* filter pattern-corresponding filenames */
+ if(compare(conn->data->set.fnmatch_data, wc->pattern,
+ finfo->filename) == 0) {
+ /* discard symlink which is containing multiple " -> " */
+ if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
+ (strstr(finfo->strings.target, " -> "))) {
+ add = FALSE;
+ }
+ }
+ else {
+ add = FALSE;
+ }
+
+ if(add) {
+ if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
+ Curl_fileinfo_dtor(NULL, finfo);
+ tmpdata->parser->file_data = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ Curl_fileinfo_dtor(NULL, finfo);
+ }
+
+ tmpdata->parser->file_data = NULL;
+ return CURLE_OK;
+}
+
+CURL_STATIC size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
+ void *connptr)
+{
+ size_t bufflen = size*nmemb;
+ struct connectdata *conn = (struct connectdata *)connptr;
+ struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
+ struct ftp_parselist_data *parser = tmpdata->parser;
+ struct curl_fileinfo *finfo;
+ unsigned long i = 0;
+ CURLcode result;
+
+ if(parser->error) { /* error in previous call */
+ /* scenario:
+ * 1. call => OK..
+ * 2. call => OUT_OF_MEMORY (or other error)
+ * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
+ * in wc_statemach()
+ */
+ return bufflen;
+ }
+
+ if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
+ /* considering info about FILE response format */
+ parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
+ OS_TYPE_WIN_NT : OS_TYPE_UNIX;
+ }
+
+ while(i < bufflen) { /* FSM */
+
+ char c = buffer[i];
+ if(!parser->file_data) { /* tmp file data is not allocated yet */
+ parser->file_data = Curl_fileinfo_alloc();
+ if(!parser->file_data) {
+ parser->error = CURLE_OUT_OF_MEMORY;
+ return bufflen;
+ }
+ parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
+ if(!parser->file_data->b_data) {
+ PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
+ return bufflen;
+ }
+ parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+
+ finfo = parser->file_data;
+ finfo->b_data[finfo->b_used++] = c;
+
+ if(finfo->b_used >= finfo->b_size - 1) {
+ /* if it is important, extend buffer space for file data */
+ char *tmp = realloc(finfo->b_data,
+ finfo->b_size + FTP_BUFFER_ALLOCSIZE);
+ if(tmp) {
+ finfo->b_size += FTP_BUFFER_ALLOCSIZE;
+ finfo->b_data = tmp;
+ }
+ else {
+ Curl_fileinfo_dtor(NULL, parser->file_data);
+ parser->file_data = NULL;
+ parser->error = CURLE_OUT_OF_MEMORY;
+ PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
+ return bufflen;
+ }
+ }
+
+ switch (parser->os_type) {
+ case OS_TYPE_UNIX:
+ switch (parser->state.UNIX.main) {
+ case PL_UNIX_TOTALSIZE:
+ switch(parser->state.UNIX.sub.total_dirsize) {
+ case PL_UNIX_TOTALSIZE_INIT:
+ if(c == 't') {
+ parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
+ parser->item_length++;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ /* start FSM again not considering size of directory */
+ finfo->b_used = 0;
+ i--;
+ }
+ break;
+ case PL_UNIX_TOTALSIZE_READING:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->item_length--;
+ finfo->b_used--;
+ }
+ else if(c == '\n') {
+ finfo->b_data[parser->item_length - 1] = 0;
+ if(strncmp("total ", finfo->b_data, 6) == 0) {
+ char *endptr = finfo->b_data+6;
+ /* here we can deal with directory size, pass the leading white
+ spaces and then the digits */
+ while(ISSPACE(*endptr))
+ endptr++;
+ while(ISDIGIT(*endptr))
+ endptr++;
+ if(*endptr != 0) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ finfo->b_used = 0;
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_FILETYPE:
+ switch (c) {
+ case '-':
+ finfo->filetype = CURLFILETYPE_FILE;
+ break;
+ case 'd':
+ finfo->filetype = CURLFILETYPE_DIRECTORY;
+ break;
+ case 'l':
+ finfo->filetype = CURLFILETYPE_SYMLINK;
+ break;
+ case 'p':
+ finfo->filetype = CURLFILETYPE_NAMEDPIPE;
+ break;
+ case 's':
+ finfo->filetype = CURLFILETYPE_SOCKET;
+ break;
+ case 'c':
+ finfo->filetype = CURLFILETYPE_DEVICE_CHAR;
+ break;
+ case 'b':
+ finfo->filetype = CURLFILETYPE_DEVICE_BLOCK;
+ break;
+ case 'D':
+ finfo->filetype = CURLFILETYPE_DOOR;
+ break;
+ default:
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ parser->state.UNIX.main = PL_UNIX_PERMISSION;
+ parser->item_length = 0;
+ parser->item_offset = 1;
+ break;
+ case PL_UNIX_PERMISSION:
+ parser->item_length++;
+ if(parser->item_length <= 9) {
+ if(!strchr("rwx-tTsS", c)) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ else if(parser->item_length == 10) {
+ unsigned int perm;
+ if(c != ' ') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ finfo->b_data[10] = 0; /* terminate permissions */
+ perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
+ if(perm & FTP_LP_MALFORMATED_PERM) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
+ parser->file_data->perm = perm;
+ parser->offsets.perm = parser->item_offset;
+
+ parser->item_length = 0;
+ parser->state.UNIX.main = PL_UNIX_HLINKS;
+ parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
+ }
+ break;
+ case PL_UNIX_HLINKS:
+ switch(parser->state.UNIX.sub.hlinks) {
+ case PL_UNIX_HLINKS_PRESPACE:
+ if(c != ' ') {
+ if(c >= '0' && c <= '9') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_HLINKS_NUMBER:
+ parser->item_length ++;
+ if(c == ' ') {
+ char *p;
+ long int hlinks;
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
+ if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
+ parser->file_data->hardlinks = hlinks;
+ }
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ parser->state.UNIX.main = PL_UNIX_USER;
+ parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
+ }
+ else if(c < '0' || c > '9') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_USER:
+ switch(parser->state.UNIX.sub.user) {
+ case PL_UNIX_USER_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
+ }
+ break;
+ case PL_UNIX_USER_PARSING:
+ parser->item_length++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.user = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_GROUP;
+ parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_GROUP:
+ switch(parser->state.UNIX.sub.group) {
+ case PL_UNIX_GROUP_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
+ }
+ break;
+ case PL_UNIX_GROUP_NAME:
+ parser->item_length++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.group = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_SIZE;
+ parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_SIZE:
+ switch(parser->state.UNIX.sub.size) {
+ case PL_UNIX_SIZE_PRESPACE:
+ if(c != ' ') {
+ if(c >= '0' && c <= '9') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_SIZE_NUMBER:
+ parser->item_length++;
+ if(c == ' ') {
+ char *p;
+ curl_off_t fsize;
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
+ if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
+ fsize != CURL_OFF_T_MIN) {
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->file_data->size = fsize;
+ }
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ parser->state.UNIX.main = PL_UNIX_TIME;
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
+ }
+ else if(!ISDIGIT(c)) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_TIME:
+ switch(parser->state.UNIX.sub.time) {
+ case PL_UNIX_TIME_PREPART1:
+ if(c != ' ') {
+ if(ISALNUM(c)) {
+ parser->item_offset = finfo->b_used -1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_TIME_PART1:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
+ }
+ else if(!ISALNUM(c) && c != '.') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_TIME_PREPART2:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c)) {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_TIME_PART2:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
+ }
+ else if(!ISALNUM(c) && c != '.') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_TIME_PREPART3:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c)) {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_TIME_PART3:
+ parser->item_length++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
+ parser->offsets.time = parser->item_offset;
+ if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
+ }
+ if(finfo->filetype == CURLFILETYPE_SYMLINK) {
+ parser->state.UNIX.main = PL_UNIX_SYMLINK;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILENAME;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
+ }
+ }
+ else if(!ISALNUM(c) && c != '.' && c != ':') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_FILENAME:
+ switch(parser->state.UNIX.sub.filename) {
+ case PL_UNIX_FILENAME_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
+ }
+ break;
+ case PL_UNIX_FILENAME_NAME:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->item_length--;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
+ }
+ else if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_FILENAME_WINDOWSEOL:
+ if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
+ return bufflen;
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_SYMLINK:
+ switch(parser->state.UNIX.sub.symlink) {
+ case PL_UNIX_SYMLINK_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_NAME:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET1:
+ parser->item_length++;
+ if(c == '-') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET2:
+ parser->item_length++;
+ if(c == '>') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET3:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
+ /* now place where is symlink following */
+ finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET4:
+ if(c != '\r' && c != '\n') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_SYMLINK_TARGET:
+ parser->item_length ++;
+ if(c == '\r') {
+ parser->item_length --;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
+ }
+ else if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
+ return bufflen;
+ }
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ break;
+ case PL_UNIX_SYMLINK_WINDOWSEOL:
+ if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
+ return bufflen;
+ }
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case OS_TYPE_WIN_NT:
+ switch(parser->state.NT.main) {
+ case PL_WINNT_DATE:
+ parser->item_length++;
+ if(parser->item_length < 9) {
+ if(!strchr("0123456789-", c)) { /* only simple control */
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ else if(parser->item_length == 9) {
+ if(c == ' ') {
+ parser->state.NT.main = PL_WINNT_TIME;
+ parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_WINNT_TIME:
+ parser->item_length++;
+ switch(parser->state.NT.sub.time) {
+ case PL_WINNT_TIME_PRESPACE:
+ if(!ISSPACE(c)) {
+ parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
+ }
+ break;
+ case PL_WINNT_TIME_TIME:
+ if(c == ' ') {
+ parser->offsets.time = parser->item_offset;
+ finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
+ parser->state.NT.main = PL_WINNT_DIRORSIZE;
+ parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
+ parser->item_length = 0;
+ }
+ else if(!strchr("APM0123456789:", c)) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_WINNT_DIRORSIZE:
+ switch(parser->state.NT.sub.dirorsize) {
+ case PL_WINNT_DIRORSIZE_PRESPACE:
+ if(c == ' ') {
+
+ }
+ else {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
+ }
+ break;
+ case PL_WINNT_DIRORSIZE_CONTENT:
+ parser->item_length ++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
+ finfo->filetype = CURLFILETYPE_DIRECTORY;
+ finfo->size = 0;
+ }
+ else {
+ char *endptr;
+ finfo->size = curlx_strtoofft(finfo->b_data +
+ parser->item_offset,
+ &endptr, 10);
+ if(!*endptr) {
+ if(finfo->size == CURL_OFF_T_MAX ||
+ finfo->size == CURL_OFF_T_MIN) {
+ if(errno == ERANGE) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ /* correct file type */
+ parser->file_data->filetype = CURLFILETYPE_FILE;
+ }
+
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->item_length = 0;
+ parser->state.NT.main = PL_WINNT_FILENAME;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ break;
+ }
+ break;
+ case PL_WINNT_FILENAME:
+ switch (parser->state.NT.sub.filename) {
+ case PL_WINNT_FILENAME_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used -1;
+ parser->item_length = 1;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
+ }
+ break;
+ case PL_WINNT_FILENAME_CONTENT:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
+ finfo->b_data[finfo->b_used - 1] = 0;
+ }
+ else if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ finfo->b_data[finfo->b_used - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
+ return bufflen;
+ }
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ break;
+ case PL_WINNT_FILENAME_WINEOL:
+ if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
+ return bufflen;
+ }
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ default:
+ return bufflen + 1;
+ }
+
+ i++;
+ }
+
+ return bufflen;
+}
+
+#endif /* CURL_DISABLE_FTP */
diff --git a/libcurl/src/lib/ftplistparser.h b/libcurl/src/lib/ftplistparser.h
new file mode 100644
index 0000000..be3afdb
--- /dev/null
+++ b/libcurl/src/lib/ftplistparser.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_FTPLISTPARSER_H
+#define HEADER_CURL_FTPLISTPARSER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+
+/* WRITEFUNCTION callback for parsing LIST responses */
+CURL_STATIC size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
+ void *connptr);
+
+struct ftp_parselist_data; /* defined inside ftplibparser.c */
+
+CURL_STATIC CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data);
+
+CURL_STATIC struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void);
+
+CURL_STATIC void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data);
+
+#endif /* CURL_DISABLE_FTP */
+#endif /* HEADER_CURL_FTPLISTPARSER_H */
diff --git a/libcurl/src/lib/getenv.c b/libcurl/src/lib/getenv.c
new file mode 100644
index 0000000..2e31d6f
--- /dev/null
+++ b/libcurl/src/lib/getenv.c
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "curl_memory.h"
+
+#include "memdebug.h"
+
+static
+char *GetEnv(const char *variable)
+{
+#if defined(_WIN32_WCE) || defined(_DURANGO) || defined(CURL_WINRT)
+ return NULL;
+#else
+#ifdef WIN32
+ char env[MAX_PATH]; /* MAX_PATH is from windef.h */
+ char *temp = getenv(variable);
+ env[0] = '\0';
+ if(temp != NULL)
+ ExpandEnvironmentStringsA(temp, env, sizeof(env));
+ return (env[0] != '\0')?strdup(env):NULL;
+#else
+ char *env = getenv(variable);
+ return (env && env[0])?strdup(env):NULL;
+#endif
+#endif
+}
+
+char *curl_getenv(const char *v)
+{
+ return GetEnv(v);
+}
diff --git a/libcurl/src/lib/getinfo.c b/libcurl/src/lib/getinfo.c
new file mode 100644
index 0000000..577247b
--- /dev/null
+++ b/libcurl/src/lib/getinfo.c
@@ -0,0 +1,382 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "getinfo.h"
+
+#include "vtls/vtls.h"
+#include "connect.h" /* Curl_getconnectinfo() */
+#include "progress.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * This is supposed to be called in the beginning of a perform() session
+ * and should reset all session-info variables
+ */
+CURL_STATIC CURLcode Curl_initinfo(struct SessionHandle *data)
+{
+ struct Progress *pro = &data->progress;
+ struct PureInfo *info = &data->info;
+
+ pro->t_nslookup = 0;
+ pro->t_connect = 0;
+ pro->t_appconnect = 0;
+ pro->t_pretransfer = 0;
+ pro->t_starttransfer = 0;
+ pro->timespent = 0;
+ pro->t_redirect = 0;
+
+ info->httpcode = 0;
+ info->httpproxycode = 0;
+ info->httpversion = 0;
+ info->filetime = -1; /* -1 is an illegal time and thus means unknown */
+ info->timecond = FALSE;
+
+ free(info->contenttype);
+ info->contenttype = NULL;
+
+ info->header_size = 0;
+ info->request_size = 0;
+ info->numconnects = 0;
+
+ info->conn_primary_ip[0] = '\0';
+ info->conn_local_ip[0] = '\0';
+ info->conn_primary_port = 0;
+ info->conn_local_port = 0;
+
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_char(struct SessionHandle *data, CURLINFO info,
+ char **param_charp)
+{
+ switch(info) {
+ case CURLINFO_EFFECTIVE_URL:
+ *param_charp = data->change.url?data->change.url:(char *)"";
+ break;
+ case CURLINFO_CONTENT_TYPE:
+ *param_charp = data->info.contenttype;
+ break;
+ case CURLINFO_PRIVATE:
+ *param_charp = (char *) data->set.private_data;
+ break;
+ case CURLINFO_FTP_ENTRY_PATH:
+ /* Return the entrypath string from the most recent connection.
+ This pointer was copied from the connectdata structure by FTP.
+ The actual string may be free()ed by subsequent libcurl calls so
+ it must be copied to a safer area before the next libcurl call.
+ Callers must never free it themselves. */
+ *param_charp = data->state.most_recent_ftp_entrypath;
+ break;
+ case CURLINFO_REDIRECT_URL:
+ /* Return the URL this request would have been redirected to if that
+ option had been enabled! */
+ *param_charp = data->info.wouldredirect;
+ break;
+ case CURLINFO_PRIMARY_IP:
+ /* Return the ip address of the most recent (primary) connection */
+ *param_charp = data->info.conn_primary_ip;
+ break;
+ case CURLINFO_LOCAL_IP:
+ /* Return the source/local ip address of the most recent (primary)
+ connection */
+ *param_charp = data->info.conn_local_ip;
+ break;
+ case CURLINFO_RTSP_SESSION_ID:
+ *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
+ break;
+
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
+ long *param_longp)
+{
+ curl_socket_t sockfd;
+
+ union {
+ unsigned long *to_ulong;
+ long *to_long;
+ } lptr;
+
+ switch(info) {
+ case CURLINFO_RESPONSE_CODE:
+ *param_longp = data->info.httpcode;
+ break;
+ case CURLINFO_HTTP_CONNECTCODE:
+ *param_longp = data->info.httpproxycode;
+ break;
+ case CURLINFO_FILETIME:
+ *param_longp = data->info.filetime;
+ break;
+ case CURLINFO_HEADER_SIZE:
+ *param_longp = data->info.header_size;
+ break;
+ case CURLINFO_REQUEST_SIZE:
+ *param_longp = data->info.request_size;
+ break;
+ case CURLINFO_SSL_VERIFYRESULT:
+ *param_longp = data->set.ssl.certverifyresult;
+ break;
+ case CURLINFO_REDIRECT_COUNT:
+ *param_longp = data->set.followlocation;
+ break;
+ case CURLINFO_HTTPAUTH_AVAIL:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.httpauthavail;
+ break;
+ case CURLINFO_PROXYAUTH_AVAIL:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.proxyauthavail;
+ break;
+ case CURLINFO_OS_ERRNO:
+ *param_longp = data->state.os_errno;
+ break;
+ case CURLINFO_NUM_CONNECTS:
+ *param_longp = data->info.numconnects;
+ break;
+ case CURLINFO_LASTSOCKET:
+ sockfd = Curl_getconnectinfo(data, NULL);
+
+ /* note: this is not a good conversion for systems with 64 bit sockets and
+ 32 bit longs */
+ if(sockfd != CURL_SOCKET_BAD)
+ *param_longp = (long)sockfd;
+ else
+ /* this interface is documented to return -1 in case of badness, which
+ may not be the same as the CURL_SOCKET_BAD value */
+ *param_longp = -1;
+ break;
+ case CURLINFO_PRIMARY_PORT:
+ /* Return the (remote) port of the most recent (primary) connection */
+ *param_longp = data->info.conn_primary_port;
+ break;
+ case CURLINFO_LOCAL_PORT:
+ /* Return the local port of the most recent (primary) connection */
+ *param_longp = data->info.conn_local_port;
+ break;
+ case CURLINFO_CONDITION_UNMET:
+ /* return if the condition prevented the document to get transferred */
+ *param_longp = data->info.timecond ? 1L : 0L;
+ break;
+ case CURLINFO_RTSP_CLIENT_CSEQ:
+ *param_longp = data->state.rtsp_next_client_CSeq;
+ break;
+ case CURLINFO_RTSP_SERVER_CSEQ:
+ *param_longp = data->state.rtsp_next_server_CSeq;
+ break;
+ case CURLINFO_RTSP_CSEQ_RECV:
+ *param_longp = data->state.rtsp_CSeq_recv;
+ break;
+
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_double(struct SessionHandle *data, CURLINFO info,
+ double *param_doublep)
+{
+ switch(info) {
+ case CURLINFO_TOTAL_TIME:
+ *param_doublep = data->progress.timespent;
+ break;
+ case CURLINFO_NAMELOOKUP_TIME:
+ *param_doublep = data->progress.t_nslookup;
+ break;
+ case CURLINFO_CONNECT_TIME:
+ *param_doublep = data->progress.t_connect;
+ break;
+ case CURLINFO_APPCONNECT_TIME:
+ *param_doublep = data->progress.t_appconnect;
+ break;
+ case CURLINFO_PRETRANSFER_TIME:
+ *param_doublep = data->progress.t_pretransfer;
+ break;
+ case CURLINFO_STARTTRANSFER_TIME:
+ *param_doublep = data->progress.t_starttransfer;
+ break;
+ case CURLINFO_SIZE_UPLOAD:
+ *param_doublep = (double)data->progress.uploaded;
+ break;
+ case CURLINFO_SIZE_DOWNLOAD:
+ *param_doublep = (double)data->progress.downloaded;
+ break;
+ case CURLINFO_SPEED_DOWNLOAD:
+ *param_doublep = (double)data->progress.dlspeed;
+ break;
+ case CURLINFO_SPEED_UPLOAD:
+ *param_doublep = (double)data->progress.ulspeed;
+ break;
+ case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
+ *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
+ (double)data->progress.size_dl:-1;
+ break;
+ case CURLINFO_CONTENT_LENGTH_UPLOAD:
+ *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
+ (double)data->progress.size_ul:-1;
+ break;
+ case CURLINFO_REDIRECT_TIME:
+ *param_doublep = data->progress.t_redirect;
+ break;
+
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
+ struct curl_slist **param_slistp)
+{
+ union {
+ struct curl_certinfo *to_certinfo;
+ struct curl_slist *to_slist;
+ } ptr;
+
+ switch(info) {
+ case CURLINFO_SSL_ENGINES:
+ *param_slistp = Curl_ssl_engines_list(data);
+ break;
+ case CURLINFO_COOKIELIST:
+ *param_slistp = Curl_cookie_list(data);
+ break;
+ case CURLINFO_CERTINFO:
+ /* Return the a pointer to the certinfo struct. Not really an slist
+ pointer but we can pretend it is here */
+ ptr.to_certinfo = &data->info.certs;
+ *param_slistp = ptr.to_slist;
+ break;
+ case CURLINFO_TLS_SESSION:
+ {
+ struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
+ param_slistp;
+ struct curl_tlssessioninfo *tsi = &data->tsi;
+ struct connectdata *conn = data->easy_conn;
+ unsigned int sockindex = 0;
+ void *internals = NULL;
+
+ *tsip = tsi;
+ tsi->backend = CURLSSLBACKEND_NONE;
+ tsi->internals = NULL;
+
+ if(!conn)
+ break;
+
+ /* Find the active ("in use") SSL connection, if any */
+ while((sockindex < sizeof(conn->ssl) / sizeof(conn->ssl[0])) &&
+ (!conn->ssl[sockindex].use))
+ sockindex++;
+
+ if(sockindex == sizeof(conn->ssl) / sizeof(conn->ssl[0]))
+ break; /* no SSL session found */
+
+ /* Return the TLS session information from the relevant backend */
+#ifdef USE_OPENSSL
+ internals = conn->ssl[sockindex].ctx;
+#endif
+#ifdef USE_GNUTLS
+ internals = conn->ssl[sockindex].session;
+#endif
+#ifdef USE_NSS
+ internals = conn->ssl[sockindex].handle;
+#endif
+#ifdef USE_GSKIT
+ internals = conn->ssl[sockindex].handle;
+#endif
+ if(internals) {
+ tsi->backend = Curl_ssl_backend();
+ tsi->internals = internals;
+ }
+ /* NOTE: For other SSL backends, it is not immediately clear what data
+ to return from 'struct ssl_connect_data'; thus, for now we keep the
+ backend as CURLSSLBACKEND_NONE in those cases, which should be
+ interpreted as "not supported" */
+ }
+ break;
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
+{
+ va_list arg;
+ long *param_longp = NULL;
+ double *param_doublep = NULL;
+ char **param_charp = NULL;
+ struct curl_slist **param_slistp = NULL;
+ int type;
+ /* default return code is to error out! */
+ CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(!data)
+ return result;
+
+ va_start(arg, info);
+
+ type = CURLINFO_TYPEMASK & (int)info;
+ switch(type) {
+ case CURLINFO_STRING:
+ param_charp = va_arg(arg, char **);
+ if(param_charp)
+ result = getinfo_char(data, info, param_charp);
+ break;
+ case CURLINFO_LONG:
+ param_longp = va_arg(arg, long *);
+ if(param_longp)
+ result = getinfo_long(data, info, param_longp);
+ break;
+ case CURLINFO_DOUBLE:
+ param_doublep = va_arg(arg, double *);
+ if(param_doublep)
+ result = getinfo_double(data, info, param_doublep);
+ break;
+ case CURLINFO_SLIST:
+ param_slistp = va_arg(arg, struct curl_slist **);
+ if(param_slistp)
+ result = getinfo_slist(data, info, param_slistp);
+ break;
+ default:
+ break;
+ }
+
+ va_end(arg);
+
+ return result;
+}
diff --git a/libcurl/src/lib/getinfo.h b/libcurl/src/lib/getinfo.h
new file mode 100644
index 0000000..1cecdf3
--- /dev/null
+++ b/libcurl/src/lib/getinfo.h
@@ -0,0 +1,27 @@
+#ifndef HEADER_CURL_GETINFO_H
+#define HEADER_CURL_GETINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+CURL_STATIC CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...);
+CURL_STATIC CURLcode Curl_initinfo(struct SessionHandle *data);
+
+#endif /* HEADER_CURL_GETINFO_H */
diff --git a/libcurl/src/lib/gopher.c b/libcurl/src/lib/gopher.c
new file mode 100644
index 0000000..954cad8
--- /dev/null
+++ b/libcurl/src/lib/gopher.c
@@ -0,0 +1,165 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_GOPHER
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+
+#include "progress.h"
+#include "strequal.h"
+#include "gopher.h"
+#include "rawstr.h"
+#include "select.h"
+#include "url.h"
+#include "warnless.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode gopher_do(struct connectdata *conn, bool *done);
+
+/*
+ * Gopher protocol handler.
+ * This is also a nice simple template to build off for simple
+ * connect-command-download protocols.
+ */
+
+const struct Curl_handler Curl_handler_gopher = {
+ "GOPHER", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ gopher_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_GOPHER, /* defport */
+ CURLPROTO_GOPHER, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+static CURLcode gopher_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result=CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+
+ curl_off_t *bytecount = &data->req.bytecount;
+ char *path = data->state.path;
+ char *sel;
+ char *sel_org = NULL;
+ ssize_t amount, k;
+
+ *done = TRUE; /* unconditionally */
+
+ /* Create selector. Degenerate cases: / and /1 => convert to "" */
+ if(strlen(path) <= 2)
+ sel = (char *)"";
+ else {
+ char *newp;
+ size_t j, i;
+ int len;
+
+ /* Otherwise, drop / and the first character (i.e., item type) ... */
+ newp = path;
+ newp+=2;
+
+ /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
+ j = strlen(newp);
+ for(i=0; i<j; i++)
+ if(newp[i] == '?')
+ newp[i] = '\x09';
+
+ /* ... and finally unescape */
+ sel = curl_easy_unescape(data, newp, 0, &len);
+ if(!sel)
+ return CURLE_OUT_OF_MEMORY;
+ sel_org = sel;
+ }
+
+ /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is
+ sent, which could be sizeable with long selectors. */
+ k = curlx_uztosz(strlen(sel));
+
+ for(;;) {
+ result = Curl_write(conn, sockfd, sel, k, &amount);
+ if(!result) { /* Which may not have written it all! */
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
+ if(result) {
+ free(sel_org);
+ return result;
+ }
+ k -= amount;
+ sel += amount;
+ if(k < 1)
+ break; /* but it did write it all */
+ }
+ else {
+ failf(data, "Failed sending Gopher request");
+ free(sel_org);
+ return result;
+ }
+ /* Don't busyloop. The entire loop thing is a work-around as it causes a
+ BLOCKING behavior which is a NO-NO. This function should rather be
+ split up in a do and a doing piece where the pieces that aren't
+ possible to send now will be sent in the doing function repeatedly
+ until the entire request is sent.
+
+ Wait a while for the socket to be writable. Note that this doesn't
+ acknowledge the timeout.
+ */
+ Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 100);
+ }
+
+ free(sel_org);
+
+ /* We can use Curl_sendf to send the terminal \r\n relatively safely and
+ save allocing another string/doing another _write loop. */
+ result = Curl_sendf(sockfd, conn, "\r\n");
+ if(result) {
+ failf(data, "Failed sending Gopher request");
+ return result;
+ }
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
+ if(result)
+ return result;
+
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
+ -1, NULL); /* no upload */
+ return CURLE_OK;
+}
+#endif /*CURL_DISABLE_GOPHER*/
diff --git a/libcurl/src/lib/gopher.h b/libcurl/src/lib/gopher.h
new file mode 100644
index 0000000..38bbc4b
--- /dev/null
+++ b/libcurl/src/lib/gopher.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_GOPHER_H
+#define HEADER_CURL_GOPHER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_GOPHER
+extern const struct Curl_handler Curl_handler_gopher;
+#endif
+
+#endif /* HEADER_CURL_GOPHER_H */
diff --git a/libcurl/src/lib/hash.c b/libcurl/src/lib/hash.c
new file mode 100644
index 0000000..6218cdb
--- /dev/null
+++ b/libcurl/src/lib/hash.c
@@ -0,0 +1,396 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "hash.h"
+#include "llist.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void
+hash_element_dtor(void *user, void *element)
+{
+ struct curl_hash *h = (struct curl_hash *) user;
+ struct curl_hash_element *e = (struct curl_hash_element *) element;
+
+ Curl_safefree(e->key);
+
+ if(e->ptr) {
+ h->dtor(e->ptr);
+ e->ptr = NULL;
+ }
+
+ e->key_len = 0;
+
+ free(e);
+}
+
+/* return 1 on error, 0 is fine */
+CURL_STATIC int
+Curl_hash_init(struct curl_hash *h,
+ int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor)
+{
+ int i;
+
+ if(!slots || !hfunc || !comparator ||!dtor) {
+ return 1; /* failure */
+ }
+
+ h->hash_func = hfunc;
+ h->comp_func = comparator;
+ h->dtor = dtor;
+ h->size = 0;
+ h->slots = slots;
+
+ h->table = malloc(slots * sizeof(struct curl_llist *));
+ if(h->table) {
+ for(i = 0; i < slots; ++i) {
+ h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
+ if(!h->table[i]) {
+ while(i--) {
+ Curl_llist_destroy(h->table[i], NULL);
+ h->table[i] = NULL;
+ }
+ free(h->table);
+ h->table = NULL;
+ h->slots = 0;
+ return 1; /* failure */
+ }
+ }
+ return 0; /* fine */
+ }
+ else {
+ h->slots = 0;
+ return 1; /* failure */
+ }
+}
+
+CURL_STATIC struct curl_hash *
+Curl_hash_alloc(int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor)
+{
+ struct curl_hash *h;
+
+ if(!slots || !hfunc || !comparator ||!dtor) {
+ return NULL; /* failure */
+ }
+
+ h = malloc(sizeof(struct curl_hash));
+ if(h) {
+ if(Curl_hash_init(h, slots, hfunc, comparator, dtor)) {
+ /* failure */
+ free(h);
+ h = NULL;
+ }
+ }
+
+ return h;
+}
+
+
+
+static struct curl_hash_element *
+mk_hash_element(const void *key, size_t key_len, const void *p)
+{
+ struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element));
+
+ if(he) {
+ void *dupkey = malloc(key_len);
+ if(dupkey) {
+ /* copy the key */
+ memcpy(dupkey, key, key_len);
+
+ he->key = dupkey;
+ he->key_len = key_len;
+ he->ptr = (void *) p;
+ }
+ else {
+ /* failed to duplicate the key, free memory and fail */
+ free(he);
+ he = NULL;
+ }
+ }
+ return he;
+}
+
+#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
+
+/* Insert the data in the hash. If there already was a match in the hash,
+ * that data is replaced.
+ *
+ * @unittest: 1305
+ */
+CURL_STATIC void *
+Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
+{
+ struct curl_hash_element *he;
+ struct curl_llist_element *le;
+ struct curl_llist *l = FETCH_LIST (h, key, key_len);
+
+ for(le = l->head; le; le = le->next) {
+ he = (struct curl_hash_element *) le->ptr;
+ if(h->comp_func(he->key, he->key_len, key, key_len)) {
+ Curl_llist_remove(l, le, (void *)h);
+ --h->size;
+ break;
+ }
+ }
+
+ he = mk_hash_element(key, key_len, p);
+ if(he) {
+ if(Curl_llist_insert_next(l, l->tail, he)) {
+ ++h->size;
+ return p; /* return the new entry */
+ }
+ /*
+ * Couldn't insert it, destroy the 'he' element and the key again. We
+ * don't call hash_element_dtor() since that would also call the
+ * "destructor" for the actual data 'p'. When we fail, we shall not touch
+ * that data.
+ */
+ free(he->key);
+ free(he);
+ }
+
+ return NULL; /* failure */
+}
+
+/* remove the identified hash entry, returns non-zero on failure */
+CURL_STATIC int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
+{
+ struct curl_llist_element *le;
+ struct curl_hash_element *he;
+ struct curl_llist *l = FETCH_LIST(h, key, key_len);
+
+ for(le = l->head; le; le = le->next) {
+ he = le->ptr;
+ if(h->comp_func(he->key, he->key_len, key, key_len)) {
+ Curl_llist_remove(l, le, (void *) h);
+ --h->size;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+CURL_STATIC void *
+Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
+{
+ struct curl_llist_element *le;
+ struct curl_hash_element *he;
+ struct curl_llist *l;
+
+ if(h) {
+ l = FETCH_LIST(h, key, key_len);
+ for(le = l->head; le; le = le->next) {
+ he = le->ptr;
+ if(h->comp_func(he->key, he->key_len, key, key_len)) {
+ return he->ptr;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST)
+CURL_STATIC void
+Curl_hash_apply(curl_hash *h, void *user,
+ void (*cb)(void *user, void *ptr))
+{
+ struct curl_llist_element *le;
+ int i;
+
+ for(i = 0; i < h->slots; ++i) {
+ for(le = (h->table[i])->head;
+ le;
+ le = le->next) {
+ curl_hash_element *el = le->ptr;
+ cb(user, el->ptr);
+ }
+ }
+}
+#endif
+
+CURL_STATIC void
+Curl_hash_clean(struct curl_hash *h)
+{
+ int i;
+
+ for(i = 0; i < h->slots; ++i) {
+ Curl_llist_destroy(h->table[i], (void *) h);
+ h->table[i] = NULL;
+ }
+
+ Curl_safefree(h->table);
+ h->size = 0;
+ h->slots = 0;
+}
+
+CURL_STATIC void
+Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+ int (*comp)(void *, void *))
+{
+ struct curl_llist_element *le;
+ struct curl_llist_element *lnext;
+ struct curl_llist *list;
+ int i;
+
+ if(!h)
+ return;
+
+ for(i = 0; i < h->slots; ++i) {
+ list = h->table[i];
+ le = list->head; /* get first list entry */
+ while(le) {
+ struct curl_hash_element *he = le->ptr;
+ lnext = le->next;
+ /* ask the callback function if we shall remove this entry or not */
+ if(comp(user, he->ptr)) {
+ Curl_llist_remove(list, le, (void *) h);
+ --h->size; /* one less entry in the hash now */
+ }
+ le = lnext;
+ }
+ }
+}
+
+CURL_STATIC void
+Curl_hash_destroy(struct curl_hash *h)
+{
+ if(!h)
+ return;
+
+ Curl_hash_clean(h);
+
+ free(h);
+}
+
+CURL_STATIC size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num)
+{
+ const char* key_str = (const char *) key;
+ const char *end = key_str + key_length;
+ unsigned long h = 5381;
+
+ while(key_str < end) {
+ h += h << 5;
+ h ^= (unsigned long) *key_str++;
+ }
+
+ return (h % slots_num);
+}
+
+CURL_STATIC size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len)
+{
+ char *key1 = (char *)k1;
+ char *key2 = (char *)k2;
+
+ if(key1_len == key2_len &&
+ *key1 == *key2 &&
+ memcmp(key1, key2, key1_len) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+CURL_STATIC void Curl_hash_start_iterate(struct curl_hash *hash,
+ struct curl_hash_iterator *iter)
+{
+ iter->hash = hash;
+ iter->slot_index = 0;
+ iter->current_element = NULL;
+}
+
+CURL_STATIC struct curl_hash_element *
+Curl_hash_next_element(struct curl_hash_iterator *iter)
+{
+ int i;
+ struct curl_hash *h = iter->hash;
+
+ /* Get the next element in the current list, if any */
+ if(iter->current_element)
+ iter->current_element = iter->current_element->next;
+
+ /* If we have reached the end of the list, find the next one */
+ if(!iter->current_element) {
+ for(i = iter->slot_index;i < h->slots;i++) {
+ if(h->table[i]->head) {
+ iter->current_element = h->table[i]->head;
+ iter->slot_index = i+1;
+ break;
+ }
+ }
+ }
+
+ if(iter->current_element) {
+ struct curl_hash_element *he = iter->current_element->ptr;
+ return he;
+ }
+ else {
+ iter->current_element = NULL;
+ return NULL;
+ }
+}
+
+#if 0 /* useful function for debugging hashes and their contents */
+CURL_STATIC void Curl_hash_print(struct curl_hash *h,
+ void (*func)(void *))
+{
+ struct curl_hash_iterator iter;
+ struct curl_hash_element *he;
+ int last_index = -1;
+
+ if(!h)
+ return;
+
+ fprintf(stderr, "=Hash dump=\n");
+
+ Curl_hash_start_iterate(h, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ if(iter.slot_index != last_index) {
+ fprintf(stderr, "index %d:", iter.slot_index);
+ if(last_index >= 0) {
+ fprintf(stderr, "\n");
+ }
+ last_index = iter.slot_index;
+ }
+
+ if(func)
+ func(he->ptr);
+ else
+ fprintf(stderr, " [%p]", (void *)he->ptr);
+
+ he = Curl_hash_next_element(&iter);
+ }
+ fprintf(stderr, "\n");
+}
+#endif
diff --git a/libcurl/src/lib/hash.h b/libcurl/src/lib/hash.h
new file mode 100644
index 0000000..02c304a
--- /dev/null
+++ b/libcurl/src/lib/hash.h
@@ -0,0 +1,106 @@
+#ifndef HEADER_CURL_HASH_H
+#define HEADER_CURL_HASH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <stddef.h>
+
+#include "llist.h"
+
+/* Hash function prototype */
+typedef size_t (*hash_function) (void* key,
+ size_t key_length,
+ size_t slots_num);
+
+/*
+ Comparator function prototype. Compares two keys.
+*/
+typedef size_t (*comp_function) (void* key1,
+ size_t key1_len,
+ void*key2,
+ size_t key2_len);
+
+typedef void (*curl_hash_dtor)(void *);
+
+struct curl_hash {
+ struct curl_llist **table;
+
+ /* Hash function to be used for this hash table */
+ hash_function hash_func;
+
+ /* Comparator function to compare keys */
+ comp_function comp_func;
+ curl_hash_dtor dtor;
+ int slots;
+ size_t size;
+};
+
+struct curl_hash_element {
+ void *ptr;
+ char *key;
+ size_t key_len;
+};
+
+struct curl_hash_iterator {
+ struct curl_hash *hash;
+ int slot_index;
+ struct curl_llist_element *current_element;
+};
+
+CURL_STATIC int Curl_hash_init(struct curl_hash *h,
+ int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor);
+
+CURL_STATIC struct curl_hash *Curl_hash_alloc(int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor);
+
+CURL_STATIC void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p);
+CURL_STATIC int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
+CURL_STATIC void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len);
+CURL_STATIC void Curl_hash_apply(struct curl_hash *h, void *user,
+ void (*cb)(void *user, void *ptr));
+CURL_STATIC int Curl_hash_count(struct curl_hash *h);
+CURL_STATIC void Curl_hash_clean(struct curl_hash *h);
+CURL_STATIC void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+ int (*comp)(void *, void *));
+CURL_STATIC void Curl_hash_destroy(struct curl_hash *h);
+
+CURL_STATIC size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num);
+CURL_STATIC size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2,
+ size_t key2_len);
+
+CURL_STATIC void Curl_hash_start_iterate(struct curl_hash *hash,
+ struct curl_hash_iterator *iter);
+CURL_STATIC struct curl_hash_element *
+Curl_hash_next_element(struct curl_hash_iterator *iter);
+
+CURL_STATIC void Curl_hash_print(struct curl_hash *h,
+ void (*func)(void *));
+
+
+#endif /* HEADER_CURL_HASH_H */
diff --git a/libcurl/src/lib/hmac.c b/libcurl/src/lib/hmac.c
new file mode 100644
index 0000000..4aa2e23
--- /dev/null
+++ b/libcurl/src/lib/hmac.c
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2104 Keyed-Hashing for Message Authentication
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+#include "curl_hmac.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Generic HMAC algorithm.
+ *
+ * This module computes HMAC digests based on any hash function. Parameters
+ * and computing procedures are set-up dynamically at HMAC computation
+ * context initialisation.
+ */
+
+static const unsigned char hmac_ipad = 0x36;
+static const unsigned char hmac_opad = 0x5C;
+
+
+
+CURL_STATIC HMAC_context *
+Curl_HMAC_init(const HMAC_params * hashparams,
+ const unsigned char * key,
+ unsigned int keylen)
+{
+ size_t i;
+ HMAC_context * ctxt;
+ unsigned char * hkey;
+ unsigned char b;
+
+ /* Create HMAC context. */
+ i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize +
+ hashparams->hmac_resultlen;
+ ctxt = malloc(i);
+
+ if(!ctxt)
+ return ctxt;
+
+ ctxt->hmac_hash = hashparams;
+ ctxt->hmac_hashctxt1 = (void *) (ctxt + 1);
+ ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 +
+ hashparams->hmac_ctxtsize);
+
+ /* If the key is too long, replace it by its hash digest. */
+ if(keylen > hashparams->hmac_maxkeylen) {
+ (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen);
+ hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize;
+ (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1);
+ key = hkey;
+ keylen = hashparams->hmac_resultlen;
+ }
+
+ /* Prime the two hash contexts with the modified key. */
+ (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
+ (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2);
+
+ for(i = 0; i < keylen; i++) {
+ b = (unsigned char)(*key ^ hmac_ipad);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1);
+ b = (unsigned char)(*key++ ^ hmac_opad);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1);
+ }
+
+ for(; i < hashparams->hmac_maxkeylen; i++) {
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1);
+ }
+
+ /* Done, return pointer to HMAC context. */
+ return ctxt;
+}
+
+CURL_STATIC int Curl_HMAC_update(HMAC_context * ctxt,
+ const unsigned char * data,
+ unsigned int len)
+{
+ /* Update first hash calculation. */
+ (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len);
+ return 0;
+}
+
+
+CURL_STATIC int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result)
+{
+ const HMAC_params * hashparams = ctxt->hmac_hash;
+
+ /* Do not get result if called with a null parameter: only release
+ storage. */
+
+ if(!result)
+ result = (unsigned char *) ctxt->hmac_hashctxt2 +
+ ctxt->hmac_hash->hmac_ctxtsize;
+
+ (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2,
+ result, hashparams->hmac_resultlen);
+ (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2);
+ free((char *) ctxt);
+ return 0;
+}
+
+#endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/libcurl/src/lib/hostasyn.c b/libcurl/src/lib/hostasyn.c
new file mode 100644
index 0000000..92a8296
--- /dev/null
+++ b/libcurl/src/lib/hostasyn.c
@@ -0,0 +1,153 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for builds using asynchronous name resolves
+ **********************************************************************/
+#ifdef CURLRES_ASYNCH
+
+/*
+ * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
+ * or getaddrinfo_thread() when we got the name resolved (or not!).
+ *
+ * If the status argument is CURL_ASYNC_SUCCESS, this function takes
+ * ownership of the Curl_addrinfo passed, storing the resolved data
+ * in the DNS cache.
+ *
+ * The storage operation locks and unlocks the DNS cache.
+ */
+CURL_STATIC CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+ int status,
+ struct Curl_addrinfo *ai)
+{
+ struct Curl_dns_entry *dns = NULL;
+ CURLcode result = CURLE_OK;
+
+ conn->async.status = status;
+
+ if(CURL_ASYNC_SUCCESS == status) {
+ if(ai) {
+ struct SessionHandle *data = conn->data;
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ dns = Curl_cache_addr(data, ai,
+ conn->async.hostname,
+ conn->async.port);
+ if(!dns) {
+ /* failed to store, cleanup and return error */
+ Curl_freeaddrinfo(ai);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ }
+ else {
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ conn->async.dns = dns;
+
+ /* Set async.done TRUE last in this function since it may be used multi-
+ threaded and once this is TRUE the other thread may read fields from the
+ async struct */
+ conn->async.done = TRUE;
+
+ /* IPv4: The input hostent struct will be freed by ares when we return from
+ this function */
+ return result;
+}
+
+/* Call this function after Curl_connect() has returned async=TRUE and
+ then a successful name resolve has been received.
+
+ Note: this function disconnects and frees the conn data in case of
+ resolve failure */
+CURL_STATIC CURLcode Curl_async_resolved(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode result;
+
+ if(conn->async.dns) {
+ conn->dns_entry = conn->async.dns;
+ conn->async.dns = NULL;
+ }
+
+ result = Curl_setup_conn(conn, protocol_done);
+
+ if(result)
+ /* We're not allowed to return failure with memory left allocated
+ in the connectdata struct, free those here */
+ Curl_disconnect(conn, FALSE); /* close the connection */
+
+ return result;
+}
+
+/*
+ * Curl_getaddrinfo() is the generic low-level name resolve API within this
+ * source file. There are several versions of this function - for different
+ * name resolve layers (selected at build-time). They all take this same set
+ * of arguments
+ */
+CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
+}
+
+#endif /* CURLRES_ASYNCH */
diff --git a/libcurl/src/lib/hostcheck.c b/libcurl/src/lib/hostcheck.c
new file mode 100644
index 0000000..1bc330d
--- /dev/null
+++ b/libcurl/src/lib/hostcheck.c
@@ -0,0 +1,147 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT)
+/* these backends use functions from this file */
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "hostcheck.h"
+#include "rawstr.h"
+#include "inet_pton.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Match a hostname against a wildcard pattern.
+ * E.g.
+ * "foo.host.com" matches "*.host.com".
+ *
+ * We use the matching rule described in RFC6125, section 6.4.3.
+ * http://tools.ietf.org/html/rfc6125#section-6.4.3
+ *
+ * In addition: ignore trailing dots in the host names and wildcards, so that
+ * the names are used normalized. This is what the browsers do.
+ *
+ * Do not allow wildcard matching on IP numbers. There are apparently
+ * certificates being used with an IP address in the CN field, thus making no
+ * apparent distinction between a name and an IP. We need to detect the use of
+ * an IP address and not wildcard match on such names.
+ *
+ * NOTE: hostmatch() gets called with copied buffers so that it can modify the
+ * contents at will.
+ */
+
+static int hostmatch(char *hostname, char *pattern)
+{
+ const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
+ int wildcard_enabled;
+ size_t prefixlen, suffixlen;
+ struct in_addr ignored;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 si6;
+#endif
+
+ /* normalize pattern and hostname by stripping off trailing dots */
+ size_t len = strlen(hostname);
+ if(hostname[len-1]=='.')
+ hostname[len-1]=0;
+ len = strlen(pattern);
+ if(pattern[len-1]=='.')
+ pattern[len-1]=0;
+
+ pattern_wildcard = strchr(pattern, '*');
+ if(pattern_wildcard == NULL)
+ return Curl_raw_equal(pattern, hostname) ?
+ CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+
+ /* detect IP address as hostname and fail the match if so */
+ if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
+ return CURL_HOST_NOMATCH;
+#ifdef ENABLE_IPV6
+ else if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
+ return CURL_HOST_NOMATCH;
+#endif
+
+ /* We require at least 2 dots in pattern to avoid too wide wildcard
+ match. */
+ wildcard_enabled = 1;
+ pattern_label_end = strchr(pattern, '.');
+ if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
+ pattern_wildcard > pattern_label_end ||
+ Curl_raw_nequal(pattern, "xn--", 4)) {
+ wildcard_enabled = 0;
+ }
+ if(!wildcard_enabled)
+ return Curl_raw_equal(pattern, hostname) ?
+ CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+
+ hostname_label_end = strchr(hostname, '.');
+ if(hostname_label_end == NULL ||
+ !Curl_raw_equal(pattern_label_end, hostname_label_end))
+ return CURL_HOST_NOMATCH;
+
+ /* The wildcard must match at least one character, so the left-most
+ label of the hostname is at least as large as the left-most label
+ of the pattern. */
+ if(hostname_label_end - hostname < pattern_label_end - pattern)
+ return CURL_HOST_NOMATCH;
+
+ prefixlen = pattern_wildcard - pattern;
+ suffixlen = pattern_label_end - (pattern_wildcard+1);
+ return Curl_raw_nequal(pattern, hostname, prefixlen) &&
+ Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen,
+ suffixlen) ?
+ CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+}
+
+CURL_STATIC int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
+{
+ char *matchp;
+ char *hostp;
+ int res = 0;
+ if(!match_pattern || !*match_pattern ||
+ !hostname || !*hostname) /* sanity check */
+ ;
+ else {
+ matchp = strdup(match_pattern);
+ if(matchp) {
+ hostp = strdup(hostname);
+ if(hostp) {
+ if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
+ res= 1;
+ free(hostp);
+ }
+ free(matchp);
+ }
+ }
+
+ return res;
+}
+
+#endif /* OPENSSL or AXTLS or GSKIT */
diff --git a/libcurl/src/lib/hostcheck.h b/libcurl/src/lib/hostcheck.h
new file mode 100644
index 0000000..596ca4d
--- /dev/null
+++ b/libcurl/src/lib/hostcheck.h
@@ -0,0 +1,32 @@
+#ifndef HEADER_CURL_HOSTCHECK_H
+#define HEADER_CURL_HOSTCHECK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+#define CURL_HOST_NOMATCH 0
+#define CURL_HOST_MATCH 1
+CURL_STATIC int Curl_cert_hostcheck(const char *match_pattern, const char *hostname);
+
+#endif /* HEADER_CURL_HOSTCHECK_H */
+
diff --git a/libcurl/src/lib/hostip.c b/libcurl/src/lib/hostip.c
new file mode 100644
index 0000000..b58eedd
--- /dev/null
+++ b/libcurl/src/lib/hostip.c
@@ -0,0 +1,879 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "inet_ntop.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if defined(CURLRES_SYNCH) && \
+ defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
+/* alarm-based timeouts can only be used with all the dependencies satisfied */
+#define USE_ALARM_TIMEOUT
+#endif
+
+/*
+ * hostip.c explained
+ * ==================
+ *
+ * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c
+ * source file are these:
+ *
+ * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use
+ * that. The host may not be able to resolve IPv6, but we don't really have to
+ * take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4
+ * defined.
+ *
+ * CURLRES_ARES - is defined if libcurl is built to use c-ares for
+ * asynchronous name resolves. This can be Windows or *nix.
+ *
+ * CURLRES_THREADED - is defined if libcurl is built to run under (native)
+ * Windows, and then the name resolve will be done in a new thread, and the
+ * supported API will be the same as for ares-builds.
+ *
+ * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If
+ * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is
+ * defined.
+ *
+ * The host*.c sources files are split up like this:
+ *
+ * hostip.c - method-independent resolver functions and utility functions
+ * hostasyn.c - functions for asynchronous name resolves
+ * hostsyn.c - functions for synchronous name resolves
+ * hostip4.c - IPv4 specific functions
+ * hostip6.c - IPv6 specific functions
+ *
+ * The two asynchronous name resolver backends are implemented in:
+ * asyn-ares.c - functions for ares-using name resolves
+ * asyn-thread.c - functions for threaded name resolves
+
+ * The hostip.h is the united header file for all this. It defines the
+ * CURLRES_* defines based on the config*.h and curl_setup.h defines.
+ */
+
+/* These two symbols are for the global DNS cache */
+static struct curl_hash hostname_cache;
+static int host_cache_initialized;
+
+static void freednsentry(void *freethis);
+
+/*
+ * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
+ * Global DNS cache is general badness. Do not use. This will be removed in
+ * a future version. Use the share interface instead!
+ *
+ * Returns a struct curl_hash pointer on success, NULL on failure.
+ */
+CURL_STATIC struct curl_hash *Curl_global_host_cache_init(void)
+{
+ int rc = 0;
+ if(!host_cache_initialized) {
+ rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str,
+ Curl_str_key_compare, freednsentry);
+ if(!rc)
+ host_cache_initialized = 1;
+ }
+ return rc?NULL:&hostname_cache;
+}
+
+/*
+ * Destroy and cleanup the global DNS cache
+ */
+CURL_STATIC void Curl_global_host_cache_dtor(void)
+{
+ if(host_cache_initialized) {
+ Curl_hash_clean(&hostname_cache);
+ host_cache_initialized = 0;
+ }
+}
+
+/*
+ * Return # of adresses in a Curl_addrinfo struct
+ */
+CURL_STATIC int Curl_num_addresses(const Curl_addrinfo *addr)
+{
+ int i = 0;
+ while(addr) {
+ addr = addr->ai_next;
+ i++;
+ }
+ return i;
+}
+
+/*
+ * Curl_printable_address() returns a printable version of the 1st address
+ * given in the 'ai' argument. The result will be stored in the buf that is
+ * bufsize bytes big.
+ *
+ * If the conversion fails, it returns NULL.
+ */
+CURL_STATIC const char *
+Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
+{
+ const struct sockaddr_in *sa4;
+ const struct in_addr *ipaddr4;
+#ifdef ENABLE_IPV6
+ const struct sockaddr_in6 *sa6;
+ const struct in6_addr *ipaddr6;
+#endif
+
+ switch (ai->ai_family) {
+ case AF_INET:
+ sa4 = (const void *)ai->ai_addr;
+ ipaddr4 = &sa4->sin_addr;
+ return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf,
+ bufsize);
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ sa6 = (const void *)ai->ai_addr;
+ ipaddr6 = &sa6->sin6_addr;
+ return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf,
+ bufsize);
+#endif
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Return a hostcache id string for the provided host + port, to be used by
+ * the DNS caching.
+ */
+static char *
+create_hostcache_id(const char *name, int port)
+{
+ /* create and return the new allocated entry */
+ char *id = aprintf("%s:%d", name, port);
+ char *ptr = id;
+ if(ptr) {
+ /* lower case the name part */
+ while(*ptr && (*ptr != ':')) {
+ *ptr = (char)TOLOWER(*ptr);
+ ptr++;
+ }
+ }
+ return id;
+}
+
+struct hostcache_prune_data {
+ long cache_timeout;
+ time_t now;
+};
+
+/*
+ * This function is set as a callback to be called for every entry in the DNS
+ * cache when we want to prune old unused entries.
+ *
+ * Returning non-zero means remove the entry, return 0 to keep it in the
+ * cache.
+ */
+static int
+hostcache_timestamp_remove(void *datap, void *hc)
+{
+ struct hostcache_prune_data *data =
+ (struct hostcache_prune_data *) datap;
+ struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
+
+ return (0 != c->timestamp)
+ && (data->now - c->timestamp >= data->cache_timeout);
+}
+
+/*
+ * Prune the DNS cache. This assumes that a lock has already been taken.
+ */
+static void
+hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now)
+{
+ struct hostcache_prune_data user;
+
+ user.cache_timeout = cache_timeout;
+ user.now = now;
+
+ Curl_hash_clean_with_criterium(hostcache,
+ (void *) &user,
+ hostcache_timestamp_remove);
+}
+
+/*
+ * Library-wide function for pruning the DNS cache. This function takes and
+ * returns the appropriate locks.
+ */
+CURL_STATIC void Curl_hostcache_prune(struct SessionHandle *data)
+{
+ time_t now;
+
+ if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
+ /* cache forever means never prune, and NULL hostcache means
+ we can't do it */
+ return;
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ time(&now);
+
+ /* Remove outdated and unused entries from the hostcache */
+ hostcache_prune(data->dns.hostcache,
+ data->set.dns_cache_timeout,
+ now);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+}
+
+#ifdef HAVE_SIGSETJMP
+/* Beware this is a global and unique instance. This is used to store the
+ return address that we can jump back to from inside a signal handler. This
+ is not thread-safe stuff. */
+sigjmp_buf curl_jmpenv;
+#endif
+
+/* lookup address, returns entry if found and not stale */
+static struct Curl_dns_entry *
+fetch_addr(struct connectdata *conn,
+ const char *hostname,
+ int port)
+{
+ char *entry_id = NULL;
+ struct Curl_dns_entry *dns = NULL;
+ size_t entry_len;
+ struct SessionHandle *data = conn->data;
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_id = create_hostcache_id(hostname, port);
+ /* If we can't create the entry id, fail */
+ if(!entry_id)
+ return dns;
+
+ entry_len = strlen(entry_id);
+
+ /* See if its already in our dns cache */
+ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
+
+ if(dns && (data->set.dns_cache_timeout != -1)) {
+ /* See whether the returned entry is stale. Done before we release lock */
+ struct hostcache_prune_data user;
+
+ time(&user.now);
+ user.cache_timeout = data->set.dns_cache_timeout;
+
+ if(hostcache_timestamp_remove(&user, dns)) {
+ infof(data, "Hostname in DNS cache was stale, zapped\n");
+ dns = NULL; /* the memory deallocation is being handled by the hash */
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1);
+ }
+ }
+
+ /* free the allocated entry_id again */
+ free(entry_id);
+
+ return dns;
+}
+
+/*
+ * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ *
+ * Curl_resolv() checks initially and multi_runsingle() checks each time
+ * it discovers the handle in the state WAITRESOLVE whether the hostname
+ * has already been resolved and the address has already been stored in
+ * the DNS cache. This short circuits waiting for a lot of pending
+ * lookups for the same hostname requested by different handles.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ *
+ * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
+ * use, or we'll leak memory!
+ */
+CURL_STATIC struct Curl_dns_entry *
+Curl_fetch_addr(struct connectdata *conn,
+ const char *hostname,
+ int port)
+{
+ struct SessionHandle *data = conn->data;
+ struct Curl_dns_entry *dns = NULL;
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ dns = fetch_addr(conn, hostname, port);
+
+ if(dns) dns->inuse++; /* we use it! */
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ return dns;
+}
+
+/*
+ * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
+ *
+ * When calling Curl_resolv() has resulted in a response with a returned
+ * address, we call this function to store the information in the dns
+ * cache etc
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
+ */
+CURL_STATIC struct Curl_dns_entry *
+Curl_cache_addr(struct SessionHandle *data,
+ Curl_addrinfo *addr,
+ const char *hostname,
+ int port)
+{
+ char *entry_id;
+ size_t entry_len;
+ struct Curl_dns_entry *dns;
+ struct Curl_dns_entry *dns2;
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_id = create_hostcache_id(hostname, port);
+ /* If we can't create the entry id, fail */
+ if(!entry_id)
+ return NULL;
+ entry_len = strlen(entry_id);
+
+ /* Create a new cache entry */
+ dns = calloc(1, sizeof(struct Curl_dns_entry));
+ if(!dns) {
+ free(entry_id);
+ return NULL;
+ }
+
+ dns->inuse = 1; /* the cache has the first reference */
+ dns->addr = addr; /* this is the address(es) */
+ time(&dns->timestamp);
+ if(dns->timestamp == 0)
+ dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */
+
+ /* Store the resolved data in our DNS cache. */
+ dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
+ (void *)dns);
+ if(!dns2) {
+ free(dns);
+ free(entry_id);
+ return NULL;
+ }
+
+ dns = dns2;
+ dns->inuse++; /* mark entry as in-use */
+
+ /* free the allocated entry_id */
+ free(entry_id);
+
+ return dns;
+}
+
+/*
+ * Curl_resolv() is the main name resolve function within libcurl. It resolves
+ * a name and returns a pointer to the entry in the 'entry' argument (if one
+ * is provided). This function might return immediately if we're using asynch
+ * resolves. See the return codes.
+ *
+ * The cache entry we return will get its 'inuse' counter increased when this
+ * function is used. You MUST call Curl_resolv_unlock() later (when you're
+ * done using this struct) to decrease the counter again.
+ *
+ * In debug mode, we specifically test for an interface name "LocalHost"
+ * and resolve "localhost" instead as a means to permit test cases
+ * to connect to a local test server with any host name.
+ *
+ * Return codes:
+ *
+ * CURLRESOLV_ERROR (-1) = error, no pointer
+ * CURLRESOLV_RESOLVED (0) = OK, pointer provided
+ * CURLRESOLV_PENDING (1) = waiting for response, no pointer
+ */
+
+CURL_STATIC int Curl_resolv(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ struct Curl_dns_entry **entry)
+{
+ struct Curl_dns_entry *dns = NULL;
+ struct SessionHandle *data = conn->data;
+ CURLcode result;
+ int rc = CURLRESOLV_ERROR; /* default to failure */
+
+ *entry = NULL;
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ dns = fetch_addr(conn, hostname, port);
+
+ if(dns) {
+ infof(data, "Hostname %s was found in DNS cache\n", hostname);
+ dns->inuse++; /* we use it! */
+ rc = CURLRESOLV_RESOLVED;
+ }
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ if(!dns) {
+ /* The entry was not in the cache. Resolve it to IP address */
+
+ Curl_addrinfo *addr;
+ int respwait;
+
+ /* Check what IP specifics the app has requested and if we can provide it.
+ * If not, bail out. */
+ if(!Curl_ipvalid(conn))
+ return CURLRESOLV_ERROR;
+
+ /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
+ non-zero value indicating that we need to wait for the response to the
+ resolve call */
+ addr = Curl_getaddrinfo(conn,
+#ifdef DEBUGBUILD
+ (data->set.str[STRING_DEVICE]
+ && !strcmp(data->set.str[STRING_DEVICE],
+ "LocalHost"))?"localhost":
+#endif
+ hostname, port, &respwait);
+
+ if(!addr) {
+ if(respwait) {
+ /* the response to our resolve call will come asynchronously at
+ a later time, good or bad */
+ /* First, check that we haven't received the info by now */
+ result = Curl_resolver_is_resolved(conn, &dns);
+ if(result) /* error detected */
+ return CURLRESOLV_ERROR;
+ if(dns)
+ rc = CURLRESOLV_RESOLVED; /* pointer provided */
+ else
+ rc = CURLRESOLV_PENDING; /* no info yet */
+ }
+ }
+ else {
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ /* we got a response, store it in the cache */
+ dns = Curl_cache_addr(data, addr, hostname, port);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ if(!dns)
+ /* returned failure, bail out nicely */
+ Curl_freeaddrinfo(addr);
+ else
+ rc = CURLRESOLV_RESOLVED;
+ }
+ }
+
+ *entry = dns;
+
+ return rc;
+}
+
+#ifdef USE_ALARM_TIMEOUT
+/*
+ * This signal handler jumps back into the main libcurl code and continues
+ * execution. This effectively causes the remainder of the application to run
+ * within a signal handler which is nonportable and could lead to problems.
+ */
+static
+RETSIGTYPE alarmfunc(int sig)
+{
+ /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
+ (void)sig;
+ siglongjmp(curl_jmpenv, 1);
+ return;
+}
+#endif /* USE_ALARM_TIMEOUT */
+
+/*
+ * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a
+ * timeout. This function might return immediately if we're using asynch
+ * resolves. See the return codes.
+ *
+ * The cache entry we return will get its 'inuse' counter increased when this
+ * function is used. You MUST call Curl_resolv_unlock() later (when you're
+ * done using this struct) to decrease the counter again.
+ *
+ * If built with a synchronous resolver and use of signals is not
+ * disabled by the application, then a nonzero timeout will cause a
+ * timeout after the specified number of milliseconds. Otherwise, timeout
+ * is ignored.
+ *
+ * Return codes:
+ *
+ * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired
+ * CURLRESOLV_ERROR (-1) = error, no pointer
+ * CURLRESOLV_RESOLVED (0) = OK, pointer provided
+ * CURLRESOLV_PENDING (1) = waiting for response, no pointer
+ */
+
+CURL_STATIC int Curl_resolv_timeout(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ struct Curl_dns_entry **entry,
+ long timeoutms)
+{
+#ifdef USE_ALARM_TIMEOUT
+#ifdef HAVE_SIGACTION
+ struct sigaction keep_sigact; /* store the old struct here */
+ volatile bool keep_copysig = FALSE; /* wether old sigact has been saved */
+ struct sigaction sigact;
+#else
+#ifdef HAVE_SIGNAL
+ void (*keep_sigact)(int); /* store the old handler here */
+#endif /* HAVE_SIGNAL */
+#endif /* HAVE_SIGACTION */
+ volatile long timeout;
+ volatile unsigned int prev_alarm = 0;
+ struct SessionHandle *data = conn->data;
+#endif /* USE_ALARM_TIMEOUT */
+ int rc;
+
+ *entry = NULL;
+
+ if(timeoutms < 0)
+ /* got an already expired timeout */
+ return CURLRESOLV_TIMEDOUT;
+
+#ifdef USE_ALARM_TIMEOUT
+ if(data->set.no_signal)
+ /* Ignore the timeout when signals are disabled */
+ timeout = 0;
+ else
+ timeout = timeoutms;
+
+ if(!timeout)
+ /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
+ return Curl_resolv(conn, hostname, port, entry);
+
+ if(timeout < 1000)
+ /* The alarm() function only provides integer second resolution, so if
+ we want to wait less than one second we must bail out already now. */
+ return CURLRESOLV_TIMEDOUT;
+
+ /* This allows us to time-out from the name resolver, as the timeout
+ will generate a signal and we will siglongjmp() from that here.
+ This technique has problems (see alarmfunc).
+ This should be the last thing we do before calling Curl_resolv(),
+ as otherwise we'd have to worry about variables that get modified
+ before we invoke Curl_resolv() (and thus use "volatile"). */
+ if(sigsetjmp(curl_jmpenv, 1)) {
+ /* this is coming from a siglongjmp() after an alarm signal */
+ failf(data, "name lookup timed out");
+ rc = CURLRESOLV_ERROR;
+ goto clean_up;
+ }
+ else {
+ /*************************************************************
+ * Set signal handler to catch SIGALRM
+ * Store the old value to be able to set it back later!
+ *************************************************************/
+#ifdef HAVE_SIGACTION
+ sigaction(SIGALRM, NULL, &sigact);
+ keep_sigact = sigact;
+ keep_copysig = TRUE; /* yes, we have a copy */
+ sigact.sa_handler = alarmfunc;
+#ifdef SA_RESTART
+ /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
+ sigact.sa_flags &= ~SA_RESTART;
+#endif
+ /* now set the new struct */
+ sigaction(SIGALRM, &sigact, NULL);
+#else /* HAVE_SIGACTION */
+ /* no sigaction(), revert to the much lamer signal() */
+#ifdef HAVE_SIGNAL
+ keep_sigact = signal(SIGALRM, alarmfunc);
+#endif
+#endif /* HAVE_SIGACTION */
+
+ /* alarm() makes a signal get sent when the timeout fires off, and that
+ will abort system calls */
+ prev_alarm = alarm(curlx_sltoui(timeout/1000L));
+ }
+
+#else
+#ifndef CURLRES_ASYNCH
+ if(timeoutms)
+ infof(conn->data, "timeout on name lookup is not supported\n");
+#else
+ (void)timeoutms; /* timeoutms not used with an async resolver */
+#endif
+#endif /* USE_ALARM_TIMEOUT */
+
+ /* Perform the actual name resolution. This might be interrupted by an
+ * alarm if it takes too long.
+ */
+ rc = Curl_resolv(conn, hostname, port, entry);
+
+#ifdef USE_ALARM_TIMEOUT
+clean_up:
+
+ if(!prev_alarm)
+ /* deactivate a possibly active alarm before uninstalling the handler */
+ alarm(0);
+
+#ifdef HAVE_SIGACTION
+ if(keep_copysig) {
+ /* we got a struct as it looked before, now put that one back nice
+ and clean */
+ sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
+ }
+#else
+#ifdef HAVE_SIGNAL
+ /* restore the previous SIGALRM handler */
+ signal(SIGALRM, keep_sigact);
+#endif
+#endif /* HAVE_SIGACTION */
+
+ /* switch back the alarm() to either zero or to what it was before minus
+ the time we spent until now! */
+ if(prev_alarm) {
+ /* there was an alarm() set before us, now put it back */
+ unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
+
+ /* the alarm period is counted in even number of seconds */
+ unsigned long alarm_set = prev_alarm - elapsed_ms/1000;
+
+ if(!alarm_set ||
+ ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
+ /* if the alarm time-left reached zero or turned "negative" (counted
+ with unsigned values), we should fire off a SIGALRM here, but we
+ won't, and zero would be to switch it off so we never set it to
+ less than 1! */
+ alarm(1);
+ rc = CURLRESOLV_TIMEDOUT;
+ failf(data, "Previous alarm fired off!");
+ }
+ else
+ alarm((unsigned int)alarm_set);
+ }
+#endif /* USE_ALARM_TIMEOUT */
+
+ return rc;
+}
+
+/*
+ * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
+ * made, the struct may be destroyed due to pruning. It is important that only
+ * one unlock is made for each Curl_resolv() call.
+ *
+ * May be called with 'data' == NULL for global cache.
+ */
+CURL_STATIC void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
+{
+ if(data && data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ freednsentry(dns);
+
+ if(data && data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+}
+
+/*
+ * File-internal: release cache dns entry reference, free if inuse drops to 0
+ */
+static void freednsentry(void *freethis)
+{
+ struct Curl_dns_entry *dns = (struct Curl_dns_entry *) freethis;
+ DEBUGASSERT(dns && (dns->inuse>0));
+
+ dns->inuse--;
+ if(dns->inuse == 0) {
+ Curl_freeaddrinfo(dns->addr);
+ free(dns);
+ }
+}
+
+/*
+ * Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
+ */
+CURL_STATIC struct curl_hash *Curl_mk_dnscache(void)
+{
+ return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry);
+}
+
+/*
+ * Curl_hostcache_clean()
+ *
+ * This _can_ be called with 'data' == NULL but then of course no locking
+ * can be done!
+ */
+
+CURL_STATIC void Curl_hostcache_clean(struct SessionHandle *data,
+ struct curl_hash *hash)
+{
+ if(data && data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ Curl_hash_clean(hash);
+
+ if(data && data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+}
+
+
+CURL_STATIC CURLcode Curl_loadhostpairs(struct SessionHandle *data)
+{
+ struct curl_slist *hostp;
+ char hostname[256];
+ char address[256];
+ int port;
+
+ for(hostp = data->change.resolve; hostp; hostp = hostp->next ) {
+ if(!hostp->data)
+ continue;
+ if(hostp->data[0] == '-') {
+ char *entry_id;
+ size_t entry_len;
+
+ if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
+ infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n",
+ hostp->data);
+ continue;
+ }
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_id = create_hostcache_id(hostname, port);
+ /* If we can't create the entry id, fail */
+ if(!entry_id) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ entry_len = strlen(entry_id);
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ /* delete entry, ignore if it didn't exist */
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ /* free the allocated entry_id again */
+ free(entry_id);
+ }
+ else {
+ struct Curl_dns_entry *dns;
+ Curl_addrinfo *addr;
+ char *entry_id;
+ size_t entry_len;
+
+ if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
+ address)) {
+ infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
+ hostp->data);
+ continue;
+ }
+
+ addr = Curl_str2addr(address, port);
+ if(!addr) {
+ infof(data, "Address in '%s' found illegal!\n", hostp->data);
+ continue;
+ }
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_id = create_hostcache_id(hostname, port);
+ /* If we can't create the entry id, fail */
+ if(!entry_id) {
+ Curl_freeaddrinfo(addr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ entry_len = strlen(entry_id);
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ /* See if its already in our dns cache */
+ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
+
+ /* free the allocated entry_id again */
+ free(entry_id);
+
+ if(!dns) {
+ /* if not in the cache already, put this host in the cache */
+ dns = Curl_cache_addr(data, addr, hostname, port);
+ if(dns) {
+ dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
+ /* release the returned reference; the cache itself will keep the
+ * entry alive: */
+ dns->inuse--;
+ }
+ }
+ else
+ /* this is a duplicate, free it again */
+ Curl_freeaddrinfo(addr);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ if(!dns) {
+ Curl_freeaddrinfo(addr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ infof(data, "Added %s:%d:%s to DNS cache\n",
+ hostname, port, address);
+ }
+ }
+ data->change.resolve = NULL; /* dealt with now */
+
+ return CURLE_OK;
+}
diff --git a/libcurl/src/lib/hostip.h b/libcurl/src/lib/hostip.h
new file mode 100644
index 0000000..2102c18
--- /dev/null
+++ b/libcurl/src/lib/hostip.h
@@ -0,0 +1,250 @@
+#ifndef HEADER_CURL_HOSTIP_H
+#define HEADER_CURL_HOSTIP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "hash.h"
+#include "curl_addrinfo.h"
+#include "asyn.h"
+
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#ifdef NETWARE
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+/* Allocate enough memory to hold the full name information structs and
+ * everything. OSF1 is known to require at least 8872 bytes. The buffer
+ * required for storing all possible aliases and IP numbers is according to
+ * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes!
+ */
+#define CURL_HOSTENT_SIZE 9000
+
+#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this
+ many seconds for a name resolve */
+
+#define CURL_ASYNC_SUCCESS CURLE_OK
+
+struct addrinfo;
+struct hostent;
+struct SessionHandle;
+struct connectdata;
+
+/*
+ * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
+ * Global DNS cache is general badness. Do not use. This will be removed in
+ * a future version. Use the share interface instead!
+ *
+ * Returns a struct curl_hash pointer on success, NULL on failure.
+ */
+CURL_STATIC struct curl_hash *Curl_global_host_cache_init(void);
+CURL_STATIC void Curl_global_host_cache_dtor(void);
+
+struct Curl_dns_entry {
+ Curl_addrinfo *addr;
+ /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */
+ time_t timestamp;
+ /* use-counter, use Curl_resolv_unlock to release reference */
+ long inuse;
+};
+
+/*
+ * Curl_resolv() returns an entry with the info for the specified host
+ * and port.
+ *
+ * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
+ * use, or we'll leak memory!
+ */
+/* return codes */
+#define CURLRESOLV_TIMEDOUT -2
+#define CURLRESOLV_ERROR -1
+#define CURLRESOLV_RESOLVED 0
+#define CURLRESOLV_PENDING 1
+CURL_STATIC int Curl_resolv(struct connectdata *conn, const char *hostname,
+ int port, struct Curl_dns_entry **dnsentry);
+CURL_STATIC int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
+ int port, struct Curl_dns_entry **dnsentry,
+ long timeoutms);
+
+#ifdef CURLRES_IPV6
+/*
+ * Curl_ipv6works() returns TRUE if IPv6 seems to work.
+ */
+CURL_STATIC bool Curl_ipv6works(void);
+#else
+#define Curl_ipv6works() FALSE
+#endif
+
+/*
+ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
+ * been set and returns TRUE if they are OK.
+ */
+CURL_STATIC bool Curl_ipvalid(struct connectdata *conn);
+
+
+/*
+ * Curl_getaddrinfo() is the generic low-level name resolve API within this
+ * source file. There are several versions of this function - for different
+ * name resolve layers (selected at build-time). They all take this same set
+ * of arguments
+ */
+CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
+
+
+/* unlock a previously resolved dns entry */
+CURL_STATIC void Curl_resolv_unlock(struct SessionHandle *data,
+ struct Curl_dns_entry *dns);
+
+/* for debugging purposes only: */
+CURL_STATIC void Curl_scan_cache_used(void *user, void *ptr);
+
+/* make a new dns cache and return the handle */
+CURL_STATIC struct curl_hash *Curl_mk_dnscache(void);
+
+/* prune old entries from the DNS cache */
+CURL_STATIC void Curl_hostcache_prune(struct SessionHandle *data);
+
+/* Return # of adresses in a Curl_addrinfo struct */
+CURL_STATIC int Curl_num_addresses (const Curl_addrinfo *addr);
+
+#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
+int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
+ GETNAMEINFO_TYPE_ARG2 salen,
+ char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
+ char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
+ GETNAMEINFO_TYPE_ARG7 flags,
+ int line, const char *source);
+#endif
+
+/* IPv4 threadsafe resolve function used for synch and asynch builds */
+CURL_STATIC Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port);
+
+CURL_STATIC CURLcode Curl_async_resolved(struct connectdata *conn,
+ bool *protocol_connect);
+
+#ifndef CURLRES_ASYNCH
+#define Curl_async_resolved(x,y) CURLE_OK
+#endif
+
+/*
+ * Curl_addrinfo_callback() is used when we build with any asynch specialty.
+ * Handles end of async request processing. Inserts ai into hostcache when
+ * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
+ * request completed whether successful or failed.
+ */
+CURL_STATIC CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+ int status,
+ Curl_addrinfo *ai);
+
+/*
+ * Curl_printable_address() returns a printable version of the 1st address
+ * given in the 'ip' argument. The result will be stored in the buf that is
+ * bufsize bytes big.
+ */
+CURL_STATIC const char *Curl_printable_address(const Curl_addrinfo *ip,
+ char *buf, size_t bufsize);
+
+/*
+ * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ *
+ * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
+ * use, or we'll leak memory!
+ */
+CURL_STATIC struct Curl_dns_entry *
+Curl_fetch_addr(struct connectdata *conn,
+ const char *hostname,
+ int port);
+/*
+ * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
+ */
+CURL_STATIC struct Curl_dns_entry *
+Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
+ const char *hostname, int port);
+
+#ifndef INADDR_NONE
+#define CURL_INADDR_NONE (in_addr_t) ~0
+#else
+#define CURL_INADDR_NONE INADDR_NONE
+#endif
+
+#ifdef HAVE_SIGSETJMP
+/* Forward-declaration of variable defined in hostip.c. Beware this
+ * is a global and unique instance. This is used to store the return
+ * address that we can jump back to from inside a signal handler.
+ * This is not thread-safe stuff.
+ */
+extern sigjmp_buf curl_jmpenv;
+#endif
+
+/*
+ * Function provided by the resolver backend to set DNS servers to use.
+ */
+CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
+
+/*
+ * Function provided by the resolver backend to set
+ * outgoing interface to use for DNS requests
+ */
+CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf);
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv4 address to use as source address for DNS requests
+ */
+CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4);
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv6 address to use as source address for DNS requests
+ */
+CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6);
+
+/*
+ * Clean off entries from the cache
+ */
+CURL_STATIC void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash);
+
+/*
+ * Destroy the hostcache of this handle.
+ */
+CURL_STATIC void Curl_hostcache_destroy(struct SessionHandle *data);
+
+/*
+ * Populate the cache with specified entries from CURLOPT_RESOLVE.
+ */
+CURL_STATIC CURLcode Curl_loadhostpairs(struct SessionHandle *data);
+
+#endif /* HEADER_CURL_HOSTIP_H */
diff --git a/libcurl/src/lib/hostip4.c b/libcurl/src/lib/hostip4.c
new file mode 100644
index 0000000..fe6d749
--- /dev/null
+++ b/libcurl/src/lib/hostip4.c
@@ -0,0 +1,307 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "inet_pton.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for plain IPv4 builds
+ **********************************************************************/
+#ifdef CURLRES_IPV4 /* plain IPv4 code coming up */
+/*
+ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
+ * been set and returns TRUE if they are OK.
+ */
+CURL_STATIC bool Curl_ipvalid(struct connectdata *conn)
+{
+ if(conn->ip_version == CURL_IPRESOLVE_V6)
+ /* An IPv6 address was requested and we can't get/use one */
+ return FALSE;
+
+ return TRUE; /* OK, proceed */
+}
+
+#ifdef CURLRES_SYNCH
+
+/*
+ * Curl_getaddrinfo() - the IPv4 synchronous version.
+ *
+ * The original code to this function was from the Dancer source code, written
+ * by Bjorn Reese, it has since been patched and modified considerably.
+ *
+ * gethostbyname_r() is the thread-safe version of the gethostbyname()
+ * function. When we build for plain IPv4, we attempt to use this
+ * function. There are _three_ different gethostbyname_r() versions, and we
+ * detect which one this platform supports in the configure script and set up
+ * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or
+ * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME
+ * has the corresponding rules. This is primarily on *nix. Note that some unix
+ * flavours have thread-safe versions of the plain gethostbyname() etc.
+ *
+ */
+CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ Curl_addrinfo *ai = NULL;
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)conn;
+#endif
+
+ *waitp = 0; /* synchronous response only */
+
+ ai = Curl_ipv4_resolve_r(hostname, port);
+ if(!ai)
+ infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
+
+ return ai;
+}
+#endif /* CURLRES_SYNCH */
+#endif /* CURLRES_IPV4 */
+
+#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES)
+
+/*
+ * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function.
+ *
+ * This is used for both synchronous and asynchronous resolver builds,
+ * implying that only threadsafe code and function calls may be used.
+ *
+ */
+Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
+ int port)
+{
+#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
+ int res;
+#endif
+ Curl_addrinfo *ai = NULL;
+ struct hostent *h = NULL;
+ struct in_addr in;
+ struct hostent *buf = NULL;
+
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+
+#if defined(HAVE_GETADDRINFO_THREADSAFE)
+ else {
+ struct addrinfo hints;
+ char sbuf[12];
+ char *sbufptr = NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ if(port) {
+ snprintf(sbuf, sizeof(sbuf), "%d", port);
+ sbufptr = sbuf;
+ }
+
+ (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
+
+#elif defined(HAVE_GETHOSTBYNAME_R)
+ /*
+ * gethostbyname_r() is the preferred resolve function for many platforms.
+ * Since there are three different versions of it, the following code is
+ * somewhat #ifdef-ridden.
+ */
+ else {
+ int h_errnop;
+
+ buf = calloc(1, CURL_HOSTENT_SIZE);
+ if(!buf)
+ return NULL; /* major failure */
+ /*
+ * The clearing of the buffer is a workaround for a gethostbyname_r bug in
+ * qnx nto and it is also _required_ for some of these functions on some
+ * platforms.
+ */
+
+#if defined(HAVE_GETHOSTBYNAME_R_5)
+ /* Solaris, IRIX and more */
+ h = gethostbyname_r(hostname,
+ (struct hostent *)buf,
+ (char *)buf + sizeof(struct hostent),
+ CURL_HOSTENT_SIZE - sizeof(struct hostent),
+ &h_errnop);
+
+ /* If the buffer is too small, it returns NULL and sets errno to
+ * ERANGE. The errno is thread safe if this is compiled with
+ * -D_REENTRANT as then the 'errno' variable is a macro defined to get
+ * used properly for threads.
+ */
+
+ if(h) {
+ ;
+ }
+ else
+#elif defined(HAVE_GETHOSTBYNAME_R_6)
+ /* Linux */
+
+ (void)gethostbyname_r(hostname,
+ (struct hostent *)buf,
+ (char *)buf + sizeof(struct hostent),
+ CURL_HOSTENT_SIZE - sizeof(struct hostent),
+ &h, /* DIFFERENCE */
+ &h_errnop);
+ /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
+ * sudden this function returns EAGAIN if the given buffer size is too
+ * small. Previous versions are known to return ERANGE for the same
+ * problem.
+ *
+ * This wouldn't be such a big problem if older versions wouldn't
+ * sometimes return EAGAIN on a common failure case. Alas, we can't
+ * assume that EAGAIN *or* ERANGE means ERANGE for any given version of
+ * glibc.
+ *
+ * For now, we do that and thus we may call the function repeatedly and
+ * fail for older glibc versions that return EAGAIN, until we run out of
+ * buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
+ *
+ * If anyone has a better fix, please tell us!
+ *
+ * -------------------------------------------------------------------
+ *
+ * On October 23rd 2003, Dan C dug up more details on the mysteries of
+ * gethostbyname_r() in glibc:
+ *
+ * In glibc 2.2.5 the interface is different (this has also been
+ * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
+ * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
+ * (shipped/upgraded by Redhat 7.2) don't show this behavior!
+ *
+ * In this "buggy" version, the return code is -1 on error and 'errno'
+ * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
+ * thread-safe variable.
+ */
+
+ if(!h) /* failure */
+#elif defined(HAVE_GETHOSTBYNAME_R_3)
+ /* AIX, Digital Unix/Tru64, HPUX 10, more? */
+
+ /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
+ * the plain fact that it does not return unique full buffers on each
+ * call, but instead several of the pointers in the hostent structs will
+ * point to the same actual data! This have the unfortunate down-side that
+ * our caching system breaks down horribly. Luckily for us though, AIX 4.3
+ * and more recent versions have a "completely thread-safe"[*] libc where
+ * all the data is stored in thread-specific memory areas making calls to
+ * the plain old gethostbyname() work fine even for multi-threaded
+ * programs.
+ *
+ * This AIX 4.3 or later detection is all made in the configure script.
+ *
+ * Troels Walsted Hansen helped us work this out on March 3rd, 2003.
+ *
+ * [*] = much later we've found out that it isn't at all "completely
+ * thread-safe", but at least the gethostbyname() function is.
+ */
+
+ if(CURL_HOSTENT_SIZE >=
+ (sizeof(struct hostent)+sizeof(struct hostent_data))) {
+
+ /* August 22nd, 2000: Albert Chin-A-Young brought an updated version
+ * that should work! September 20: Richard Prescott worked on the buffer
+ * size dilemma.
+ */
+
+ res = gethostbyname_r(hostname,
+ (struct hostent *)buf,
+ (struct hostent_data *)((char *)buf +
+ sizeof(struct hostent)));
+ h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */
+ }
+ else
+ res = -1; /* failure, too smallish buffer size */
+
+ if(!res) { /* success */
+
+ h = buf; /* result expected in h */
+
+ /* This is the worst kind of the different gethostbyname_r() interfaces.
+ * Since we don't know how big buffer this particular lookup required,
+ * we can't realloc down the huge alloc without doing closer analysis of
+ * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
+ * name lookup. Fixing this would require an extra malloc() and then
+ * calling Curl_addrinfo_copy() that subsequent realloc()s down the new
+ * memory area to the actually used amount.
+ */
+ }
+ else
+#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */
+ {
+ h = NULL; /* set return code to NULL */
+ free(buf);
+ }
+#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
+ /*
+ * Here is code for platforms that don't have a thread safe
+ * getaddrinfo() nor gethostbyname_r() function or for which
+ * gethostbyname() is the preferred one.
+ */
+ else {
+ h = gethostbyname((void*)hostname);
+#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
+ }
+
+ if(h) {
+ ai = Curl_he2ai(h, port);
+
+ if(buf) /* used a *_r() function */
+ free(buf);
+ }
+
+ return ai;
+}
+#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */
diff --git a/libcurl/src/lib/hostip6.c b/libcurl/src/lib/hostip6.c
new file mode 100644
index 0000000..862bfae
--- /dev/null
+++ b/libcurl/src/lib/hostip6.c
@@ -0,0 +1,221 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "inet_pton.h"
+#include "connect.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for IPv6-enabled builds
+ **********************************************************************/
+#ifdef CURLRES_IPV6
+
+
+#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
+/* These are strictly for memory tracing and are using the same style as the
+ * family otherwise present in memdebug.c. I put these ones here since they
+ * require a bunch of structs I didn't want to include in memdebug.c
+ */
+
+/*
+ * For CURLRES_ARS, this should be written using ares_gethostbyaddr()
+ * (ignoring the fact c-ares doesn't return 'serv').
+ */
+
+int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
+ GETNAMEINFO_TYPE_ARG2 salen,
+ char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
+ char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
+ GETNAMEINFO_TYPE_ARG7 flags,
+ int line, const char *source)
+{
+ int res = (getnameinfo)(sa, salen,
+ host, hostlen,
+ serv, servlen,
+ flags);
+ if(0 == res)
+ /* success */
+ curl_memlog("GETNAME %s:%d getnameinfo()\n",
+ source, line);
+ else
+ curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n",
+ source, line, res);
+ return res;
+}
+#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
+
+/*
+ * Curl_ipv6works() returns TRUE if IPv6 seems to work.
+ */
+CURL_STATIC bool Curl_ipv6works(void)
+{
+ /* the nature of most system is that IPv6 status doesn't come and go
+ during a program's lifetime so we only probe the first time and then we
+ have the info kept for fast re-use */
+ static int ipv6_works = -1;
+ if(-1 == ipv6_works) {
+ /* probe to see if we have a working IPv6 stack */
+ curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if(s == CURL_SOCKET_BAD)
+ /* an IPv6 address was requested but we can't get/use one */
+ ipv6_works = 0;
+ else {
+ ipv6_works = 1;
+ Curl_closesocket(NULL, s);
+ }
+ }
+ return (ipv6_works>0)?TRUE:FALSE;
+}
+
+/*
+ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
+ * been set and returns TRUE if they are OK.
+ */
+CURL_STATIC bool Curl_ipvalid(struct connectdata *conn)
+{
+ if(conn->ip_version == CURL_IPRESOLVE_V6)
+ return Curl_ipv6works();
+ return TRUE;
+}
+
+#if defined(CURLRES_SYNCH)
+
+#ifdef DEBUG_ADDRINFO
+static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
+{
+ printf("dump_addrinfo:\n");
+ for(; ai; ai = ai->ai_next) {
+ char buf[INET6_ADDRSTRLEN];
+
+ printf(" fam %2d, CNAME %s, ",
+ ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
+ if(Curl_printable_address(ai, buf, sizeof(buf)))
+ printf("%s\n", buf);
+ else
+ printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
+ }
+}
+#else
+#define dump_addrinfo(x,y) Curl_nop_stmt
+#endif
+
+/*
+ * Curl_getaddrinfo() when built IPv6-enabled (non-threading and
+ * non-ares version).
+ *
+ * Returns name information about the given hostname and port number. If
+ * successful, the 'addrinfo' is returned and the forth argument will point to
+ * memory we need to free after use. That memory *MUST* be freed with
+ * Curl_freeaddrinfo(), nothing else.
+ */
+CURL_STATIC Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct addrinfo hints;
+ Curl_addrinfo *res;
+ int error;
+ char sbuf[12];
+ char *sbufptr = NULL;
+ char addrbuf[128];
+ int pf;
+ struct SessionHandle *data = conn->data;
+
+ *waitp = 0; /* synchronous response only */
+
+ /*
+ * Check if a limited name resolve has been requested.
+ */
+ switch(conn->ip_version) {
+ case CURL_IPRESOLVE_V4:
+ pf = PF_INET;
+ break;
+ case CURL_IPRESOLVE_V6:
+ pf = PF_INET6;
+ break;
+ default:
+ pf = PF_UNSPEC;
+ break;
+ }
+
+ if((pf != PF_INET) && !Curl_ipv6works())
+ /* The stack seems to be a non-IPv6 one */
+ pf = PF_INET;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pf;
+ hints.ai_socktype = conn->socktype;
+
+ if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
+ (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {
+ /* the given address is numerical only, prevent a reverse lookup */
+ hints.ai_flags = AI_NUMERICHOST;
+ }
+
+ if(port) {
+ snprintf(sbuf, sizeof(sbuf), "%d", port);
+ sbufptr=sbuf;
+ }
+ error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
+ if(error) {
+ infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
+ return NULL;
+ }
+
+ dump_addrinfo(conn, res);
+
+ return res;
+}
+#endif /* CURLRES_SYNCH */
+#endif /* CURLRES_IPV6 */
+
diff --git a/libcurl/src/lib/hostsyn.c b/libcurl/src/lib/hostsyn.c
new file mode 100644
index 0000000..ecf4c0a
--- /dev/null
+++ b/libcurl/src/lib/hostsyn.c
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for builds using synchronous name resolves
+ **********************************************************************/
+#ifdef CURLRES_SYNCH
+
+/*
+ * Function provided by the resolver backend to set DNS servers to use.
+ */
+CURL_STATIC CURLcode Curl_set_dns_servers(struct SessionHandle *data,
+ char *servers)
+{
+ (void)data;
+ (void)servers;
+ return CURLE_NOT_BUILT_IN;
+
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * outgoing interface to use for DNS requests
+ */
+CURL_STATIC CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf)
+{
+ (void)data;
+ (void)interf;
+ return CURLE_NOT_BUILT_IN;
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv4 address to use as source address for DNS requests
+ */
+CURL_STATIC CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4)
+{
+ (void)data;
+ (void)local_ip4;
+ return CURLE_NOT_BUILT_IN;
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv6 address to use as source address for DNS requests
+ */
+CURL_STATIC CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6)
+{
+ (void)data;
+ (void)local_ip6;
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* truly sync */
diff --git a/libcurl/src/lib/http.c b/libcurl/src/lib/http.c
new file mode 100644
index 0000000..753949c
--- /dev/null
+++ b/libcurl/src/lib/http.c
@@ -0,0 +1,3717 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_HTTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "formdata.h"
+#include "progress.h"
+#include "curl_base64.h"
+#include "cookie.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "http_digest.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_wb.h"
+#include "http_negotiate.h"
+#include "url.h"
+#include "share.h"
+#include "hostip.h"
+#include "http.h"
+#include "select.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "strtoofft.h"
+#include "multiif.h"
+#include "rawstr.h"
+#include "content_encoding.h"
+#include "http_proxy.h"
+#include "warnless.h"
+#include "non-ascii.h"
+#include "bundles.h"
+#include "pipeline.h"
+#include "http2.h"
+#include "connect.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * Forward declarations.
+ */
+
+static int http_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+static int http_should_fail(struct connectdata *conn);
+
+#ifdef USE_SSL
+static CURLcode https_connecting(struct connectdata *conn, bool *done);
+static int https_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+#else
+#define https_connecting(x,y) CURLE_COULDNT_CONNECT
+#endif
+
+/*
+ * HTTP handler interface.
+ */
+CURL_STATIC_VAR const struct Curl_handler Curl_handler_http = {
+ "HTTP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_CREDSPERREQUEST /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTPS handler interface.
+ */
+const struct Curl_handler Curl_handler_https = {
+ "HTTPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ https_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ https_getsock, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTPS, /* defport */
+ CURLPROTO_HTTPS, /* protocol */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */
+};
+#endif
+
+
+CURL_STATIC CURLcode Curl_http_setup_conn(struct connectdata *conn)
+{
+ /* allocate the HTTP-specific struct for the SessionHandle, only to survive
+ during this request */
+ DEBUGASSERT(conn->data->req.protop == NULL);
+
+ conn->data->req.protop = calloc(1, sizeof(struct HTTP));
+ if(!conn->data->req.protop)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+/*
+ * checkheaders() checks the linked list of custom HTTP headers for a
+ * particular header (prefix).
+ *
+ * Returns a pointer to the first matching header or NULL if none matched.
+ */
+CURL_STATIC char *Curl_checkheaders(const struct connectdata *conn,
+ const char *thisheader)
+{
+ struct curl_slist *head;
+ size_t thislen = strlen(thisheader);
+ struct SessionHandle *data = conn->data;
+
+ for(head = data->set.headers;head; head=head->next) {
+ if(Curl_raw_nequal(head->data, thisheader, thislen))
+ return head->data;
+ }
+ return NULL;
+}
+
+/*
+ * checkProxyHeaders() checks the linked list of custom proxy headers
+ * if proxy headers are not available, then it will lookup into http header
+ * link list
+ *
+ * It takes a connectdata struct as input instead of the SessionHandle simply
+ * to know if this is a proxy request or not, as it then might check a
+ * different header list.
+ *
+ */
+CURL_STATIC char *Curl_checkProxyheaders(const struct connectdata *conn,
+ const char *thisheader)
+{
+ struct curl_slist *head;
+ size_t thislen = strlen(thisheader);
+ struct SessionHandle *data = conn->data;
+
+ for(head = (conn->bits.proxy && data->set.sep_headers)?
+ data->set.proxyheaders:data->set.headers;
+ head; head=head->next) {
+ if(Curl_raw_nequal(head->data, thisheader, thislen))
+ return head->data;
+ }
+ return NULL;
+}
+
+/*
+ * Strip off leading and trailing whitespace from the value in the
+ * given HTTP header line and return a strdupped copy. Returns NULL in
+ * case of allocation failure. Returns an empty string if the header value
+ * consists entirely of whitespace.
+ */
+CURL_STATIC char *Curl_copy_header_value(const char *header)
+{
+ const char *start;
+ const char *end;
+ char *value;
+ size_t len;
+
+ DEBUGASSERT(header);
+
+ /* Find the end of the header name */
+ while(*header && (*header != ':'))
+ ++header;
+
+ if(*header)
+ /* Skip over colon */
+ ++header;
+
+ /* Find the first non-space letter */
+ start = header;
+ while(*start && ISSPACE(*start))
+ start++;
+
+ /* data is in the host encoding so
+ use '\r' and '\n' instead of 0x0d and 0x0a */
+ end = strchr(start, '\r');
+ if(!end)
+ end = strchr(start, '\n');
+ if(!end)
+ end = strchr(start, '\0');
+ if(!end)
+ return NULL;
+
+ /* skip all trailing space letters */
+ while((end > start) && ISSPACE(*end))
+ end--;
+
+ /* get length of the type */
+ len = end - start + 1;
+
+ value = malloc(len + 1);
+ if(!value)
+ return NULL;
+
+ memcpy(value, start, len);
+ value[len] = 0; /* zero terminate */
+
+ return value;
+}
+
+/*
+ * http_output_basic() sets up an Authorization: header (or the proxy version)
+ * for HTTP Basic authentication.
+ *
+ * Returns CURLcode.
+ */
+static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
+{
+ size_t size = 0;
+ char *authorization = NULL;
+ struct SessionHandle *data = conn->data;
+ char **userp;
+ const char *user;
+ const char *pwd;
+ CURLcode result;
+
+ if(proxy) {
+ userp = &conn->allocptr.proxyuserpwd;
+ user = conn->proxyuser;
+ pwd = conn->proxypasswd;
+ }
+ else {
+ userp = &conn->allocptr.userpwd;
+ user = conn->user;
+ pwd = conn->passwd;
+ }
+
+ snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
+
+ result = Curl_base64_encode(data,
+ data->state.buffer, strlen(data->state.buffer),
+ &authorization, &size);
+ if(result)
+ return result;
+
+ if(!authorization)
+ return CURLE_REMOTE_ACCESS_DENIED;
+
+ free(*userp);
+ *userp = aprintf("%sAuthorization: Basic %s\r\n",
+ proxy?"Proxy-":"",
+ authorization);
+ free(authorization);
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+/* pickoneauth() selects the most favourable authentication method from the
+ * ones available and the ones we want.
+ *
+ * return TRUE if one was picked
+ */
+static bool pickoneauth(struct auth *pick)
+{
+ bool picked;
+ /* only deal with authentication we want */
+ unsigned long avail = pick->avail & pick->want;
+ picked = TRUE;
+
+ /* The order of these checks is highly relevant, as this will be the order
+ of preference in case of the existence of multiple accepted types. */
+ if(avail & CURLAUTH_NEGOTIATE)
+ pick->picked = CURLAUTH_NEGOTIATE;
+ else if(avail & CURLAUTH_DIGEST)
+ pick->picked = CURLAUTH_DIGEST;
+ else if(avail & CURLAUTH_NTLM)
+ pick->picked = CURLAUTH_NTLM;
+ else if(avail & CURLAUTH_NTLM_WB)
+ pick->picked = CURLAUTH_NTLM_WB;
+ else if(avail & CURLAUTH_BASIC)
+ pick->picked = CURLAUTH_BASIC;
+ else {
+ pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
+ picked = FALSE;
+ }
+ pick->avail = CURLAUTH_NONE; /* clear it here */
+
+ return picked;
+}
+
+/*
+ * Curl_http_perhapsrewind()
+ *
+ * If we are doing POST or PUT {
+ * If we have more data to send {
+ * If we are doing NTLM {
+ * Keep sending since we must not disconnect
+ * }
+ * else {
+ * If there is more than just a little data left to send, close
+ * the current connection by force.
+ * }
+ * }
+ * If we have sent any data {
+ * If we don't have track of all the data {
+ * call app to tell it to rewind
+ * }
+ * else {
+ * rewind internally so that the operation can restart fine
+ * }
+ * }
+ * }
+ */
+static CURLcode http_perhapsrewind(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct HTTP *http = data->req.protop;
+ curl_off_t bytessent;
+ curl_off_t expectsend = -1; /* default is unknown */
+
+ if(!http)
+ /* If this is still NULL, we have not reach very far and we can safely
+ skip this rewinding stuff */
+ return CURLE_OK;
+
+ switch(data->set.httpreq) {
+ case HTTPREQ_GET:
+ case HTTPREQ_HEAD:
+ return CURLE_OK;
+ default:
+ break;
+ }
+
+ bytessent = http->writebytecount;
+
+ if(conn->bits.authneg) {
+ /* This is a state where we are known to be negotiating and we don't send
+ any data then. */
+ expectsend = 0;
+ }
+ else if(!conn->bits.protoconnstart) {
+ /* HTTP CONNECT in progress: there is no body */
+ expectsend = 0;
+ }
+ else {
+ /* figure out how much data we are expected to send */
+ switch(data->set.httpreq) {
+ case HTTPREQ_POST:
+ if(data->set.postfieldsize != -1)
+ expectsend = data->set.postfieldsize;
+ else if(data->set.postfields)
+ expectsend = (curl_off_t)strlen(data->set.postfields);
+ break;
+ case HTTPREQ_PUT:
+ if(data->state.infilesize != -1)
+ expectsend = data->state.infilesize;
+ break;
+ case HTTPREQ_POST_FORM:
+ expectsend = http->postsize;
+ break;
+ default:
+ break;
+ }
+ }
+
+ conn->bits.rewindaftersend = FALSE; /* default */
+
+ if((expectsend == -1) || (expectsend > bytessent)) {
+#if defined(USE_NTLM)
+ /* There is still data left to send */
+ if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
+ (data->state.authhost.picked == CURLAUTH_NTLM) ||
+ (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
+ (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
+ if(((expectsend - bytessent) < 2000) ||
+ (conn->ntlm.state != NTLMSTATE_NONE) ||
+ (conn->proxyntlm.state != NTLMSTATE_NONE)) {
+ /* The NTLM-negotiation has started *OR* there is just a little (<2K)
+ data left to send, keep on sending. */
+
+ /* rewind data when completely done sending! */
+ if(!conn->bits.authneg) {
+ conn->bits.rewindaftersend = TRUE;
+ infof(data, "Rewind stream after send\n");
+ }
+
+ return CURLE_OK;
+ }
+
+ if(conn->bits.close)
+ /* this is already marked to get closed */
+ return CURLE_OK;
+
+ infof(data, "NTLM send, close instead of sending %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ (curl_off_t)(expectsend - bytessent));
+ }
+#endif
+
+ /* This is not NTLM or many bytes left to send: close */
+ connclose(conn, "Mid-auth HTTP and much data left to send");
+ data->req.size = 0; /* don't download any more than 0 bytes */
+
+ /* There still is data left to send, but this connection is marked for
+ closure so we can safely do the rewind right now */
+ }
+
+ if(bytessent)
+ /* we rewind now at once since if we already sent something */
+ return Curl_readrewind(conn);
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_http_auth_act() gets called when all HTTP headers have been received
+ * and it checks what authentication methods that are available and decides
+ * which one (if any) to use. It will set 'newurl' if an auth method was
+ * picked.
+ */
+
+CURL_STATIC CURLcode Curl_http_auth_act(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ bool pickhost = FALSE;
+ bool pickproxy = FALSE;
+ CURLcode result = CURLE_OK;
+
+ if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
+ /* this is a transient response code, ignore */
+ return CURLE_OK;
+
+ if(data->state.authproblem)
+ return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
+
+ if(conn->bits.user_passwd &&
+ ((data->req.httpcode == 401) ||
+ (conn->bits.authneg && data->req.httpcode < 300))) {
+ pickhost = pickoneauth(&data->state.authhost);
+ if(!pickhost)
+ data->state.authproblem = TRUE;
+ }
+ if(conn->bits.proxy_user_passwd &&
+ ((data->req.httpcode == 407) ||
+ (conn->bits.authneg && data->req.httpcode < 300))) {
+ pickproxy = pickoneauth(&data->state.authproxy);
+ if(!pickproxy)
+ data->state.authproblem = TRUE;
+ }
+
+ if(pickhost || pickproxy) {
+ /* In case this is GSS auth, the newurl field is already allocated so
+ we must make sure to free it before allocating a new one. As figured
+ out in bug #2284386 */
+ Curl_safefree(data->req.newurl);
+ data->req.newurl = strdup(data->change.url); /* clone URL */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+
+ if((data->set.httpreq != HTTPREQ_GET) &&
+ (data->set.httpreq != HTTPREQ_HEAD) &&
+ !conn->bits.rewindaftersend) {
+ result = http_perhapsrewind(conn);
+ if(result)
+ return result;
+ }
+ }
+
+ else if((data->req.httpcode < 300) &&
+ (!data->state.authhost.done) &&
+ conn->bits.authneg) {
+ /* no (known) authentication available,
+ authentication is not "done" yet and
+ no authentication seems to be required and
+ we didn't try HEAD or GET */
+ if((data->set.httpreq != HTTPREQ_GET) &&
+ (data->set.httpreq != HTTPREQ_HEAD)) {
+ data->req.newurl = strdup(data->change.url); /* clone URL */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+ data->state.authhost.done = TRUE;
+ }
+ }
+ if(http_should_fail(conn)) {
+ failf (data, "The requested URL returned error: %d",
+ data->req.httpcode);
+ result = CURLE_HTTP_RETURNED_ERROR;
+ }
+
+ return result;
+}
+
+
+/*
+ * Output the correct authentication header depending on the auth type
+ * and whether or not it is to a proxy.
+ */
+static CURLcode
+output_auth_headers(struct connectdata *conn,
+ struct auth *authstatus,
+ const char *request,
+ const char *path,
+ bool proxy)
+{
+ const char *auth = NULL;
+ CURLcode result = CURLE_OK;
+#if defined(USE_SPNEGO) || !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ struct SessionHandle *data = conn->data;
+#endif
+#ifdef USE_SPNEGO
+ struct negotiatedata *negdata = proxy?
+ &data->state.proxyneg:&data->state.negotiate;
+#endif
+
+#ifdef CURL_DISABLE_CRYPTO_AUTH
+ (void)request;
+ (void)path;
+#endif
+
+#ifdef USE_SPNEGO
+ negdata->state = GSS_AUTHNONE;
+ if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
+ negdata->context && !GSS_ERROR(negdata->status)) {
+ auth="Negotiate";
+ result = Curl_output_negotiate(conn, proxy);
+ if(result)
+ return result;
+ authstatus->done = TRUE;
+ negdata->state = GSS_AUTHSENT;
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ if(authstatus->picked == CURLAUTH_NTLM) {
+ auth="NTLM";
+ result = Curl_output_ntlm(conn, proxy);
+ if(result)
+ return result;
+ }
+ else
+#endif
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ if(authstatus->picked == CURLAUTH_NTLM_WB) {
+ auth="NTLM_WB";
+ result = Curl_output_ntlm_wb(conn, proxy);
+ if(result)
+ return result;
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(authstatus->picked == CURLAUTH_DIGEST) {
+ auth="Digest";
+ result = Curl_output_digest(conn,
+ proxy,
+ (const unsigned char *)request,
+ (const unsigned char *)path);
+ if(result)
+ return result;
+ }
+ else
+#endif
+ if(authstatus->picked == CURLAUTH_BASIC) {
+ /* Basic */
+ if((proxy && conn->bits.proxy_user_passwd &&
+ !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
+ (!proxy && conn->bits.user_passwd &&
+ !Curl_checkheaders(conn, "Authorization:"))) {
+ auth="Basic";
+ result = http_output_basic(conn, proxy);
+ if(result)
+ return result;
+ }
+ /* NOTE: this function should set 'done' TRUE, as the other auth
+ functions work that way */
+ authstatus->done = TRUE;
+ }
+
+ if(auth) {
+ infof(data, "%s auth using %s with user '%s'\n",
+ proxy?"Proxy":"Server", auth,
+ proxy?(conn->proxyuser?conn->proxyuser:""):
+ (conn->user?conn->user:""));
+ authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
+ }
+ else
+ authstatus->multi = FALSE;
+
+ return CURLE_OK;
+}
+
+/**
+ * Curl_http_output_auth() setups the authentication headers for the
+ * host/proxy and the correct authentication
+ * method. conn->data->state.authdone is set to TRUE when authentication is
+ * done.
+ *
+ * @param conn all information about the current connection
+ * @param request pointer to the request keyword
+ * @param path pointer to the requested path
+ * @param proxytunnel boolean if this is the request setting up a "proxy
+ * tunnel"
+ *
+ * @returns CURLcode
+ */
+CURLcode
+Curl_http_output_auth(struct connectdata *conn,
+ const char *request,
+ const char *path,
+ bool proxytunnel) /* TRUE if this is the request setting
+ up the proxy tunnel */
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct auth *authhost;
+ struct auth *authproxy;
+
+ DEBUGASSERT(data);
+
+ authhost = &data->state.authhost;
+ authproxy = &data->state.authproxy;
+
+ if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
+ conn->bits.user_passwd)
+ /* continue please */;
+ else {
+ authhost->done = TRUE;
+ authproxy->done = TRUE;
+ return CURLE_OK; /* no authentication with no user or password */
+ }
+
+ if(authhost->want && !authhost->picked)
+ /* The app has selected one or more methods, but none has been picked
+ so far by a server round-trip. Then we set the picked one to the
+ want one, and if this is one single bit it'll be used instantly. */
+ authhost->picked = authhost->want;
+
+ if(authproxy->want && !authproxy->picked)
+ /* The app has selected one or more methods, but none has been picked so
+ far by a proxy round-trip. Then we set the picked one to the want one,
+ and if this is one single bit it'll be used instantly. */
+ authproxy->picked = authproxy->want;
+
+#ifndef CURL_DISABLE_PROXY
+ /* Send proxy authentication header if needed */
+ if(conn->bits.httpproxy &&
+ (conn->bits.tunnel_proxy == proxytunnel)) {
+ result = output_auth_headers(conn, authproxy, request, path, TRUE);
+ if(result)
+ return result;
+ }
+ else
+#else
+ (void)proxytunnel;
+#endif /* CURL_DISABLE_PROXY */
+ /* we have no proxy so let's pretend we're done authenticating
+ with it */
+ authproxy->done = TRUE;
+
+ /* To prevent the user+password to get sent to other than the original
+ host due to a location-follow, we do some weirdo checks here */
+ if(!data->state.this_is_a_follow ||
+ conn->bits.netrc ||
+ !data->state.first_host ||
+ data->set.http_disable_hostname_check_before_authentication ||
+ Curl_raw_equal(data->state.first_host, conn->host.name)) {
+ result = output_auth_headers(conn, authhost, request, path, FALSE);
+ }
+ else
+ authhost->done = TRUE;
+
+ return result;
+}
+
+
+/*
+ * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
+ * headers. They are dealt with both in the transfer.c main loop and in the
+ * proxy CONNECT loop.
+ */
+
+CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+ const char *auth) /* the first non-space */
+{
+ /*
+ * This resource requires authentication
+ */
+ struct SessionHandle *data = conn->data;
+
+#ifdef USE_SPNEGO
+ struct negotiatedata *negdata = proxy?
+ &data->state.proxyneg:&data->state.negotiate;
+#endif
+ unsigned long *availp;
+ struct auth *authp;
+
+ if(proxy) {
+ availp = &data->info.proxyauthavail;
+ authp = &data->state.authproxy;
+ }
+ else {
+ availp = &data->info.httpauthavail;
+ authp = &data->state.authhost;
+ }
+
+ /*
+ * Here we check if we want the specific single authentication (using ==) and
+ * if we do, we initiate usage of it.
+ *
+ * If the provided authentication is wanted as one out of several accepted
+ * types (using &), we OR this authentication type to the authavail
+ * variable.
+ *
+ * Note:
+ *
+ * ->picked is first set to the 'want' value (one or more bits) before the
+ * request is sent, and then it is again set _after_ all response 401/407
+ * headers have been received but then only to a single preferred method
+ * (bit).
+ *
+ */
+
+ while(*auth) {
+#ifdef USE_SPNEGO
+ if(checkprefix("Negotiate", auth)) {
+ *availp |= CURLAUTH_NEGOTIATE;
+ authp->avail |= CURLAUTH_NEGOTIATE;
+
+ if(authp->picked == CURLAUTH_NEGOTIATE) {
+ if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) {
+ CURLcode result = Curl_input_negotiate(conn, proxy, auth);
+ if(!result) {
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->change.url);
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+ data->state.authproblem = FALSE;
+ /* we received a GSS auth token and we dealt with it fine */
+ negdata->state = GSS_AUTHRECV;
+ }
+ else
+ data->state.authproblem = TRUE;
+ }
+ }
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ /* NTLM support requires the SSL crypto libs */
+ if(checkprefix("NTLM", auth)) {
+ *availp |= CURLAUTH_NTLM;
+ authp->avail |= CURLAUTH_NTLM;
+ if(authp->picked == CURLAUTH_NTLM ||
+ authp->picked == CURLAUTH_NTLM_WB) {
+ /* NTLM authentication is picked and activated */
+ CURLcode result = Curl_input_ntlm(conn, proxy, auth);
+ if(!result) {
+ data->state.authproblem = FALSE;
+#ifdef NTLM_WB_ENABLED
+ if(authp->picked == CURLAUTH_NTLM_WB) {
+ *availp &= ~CURLAUTH_NTLM;
+ authp->avail &= ~CURLAUTH_NTLM;
+ *availp |= CURLAUTH_NTLM_WB;
+ authp->avail |= CURLAUTH_NTLM_WB;
+
+ /* Get the challenge-message which will be passed to
+ * ntlm_auth for generating the type 3 message later */
+ while(*auth && ISSPACE(*auth))
+ auth++;
+ if(checkprefix("NTLM", auth)) {
+ auth += strlen("NTLM");
+ while(*auth && ISSPACE(*auth))
+ auth++;
+ if(*auth)
+ if((conn->challenge_header = strdup(auth)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ }
+ else {
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(checkprefix("Digest", auth)) {
+ if((authp->avail & CURLAUTH_DIGEST) != 0) {
+ infof(data, "Ignoring duplicate digest auth header.\n");
+ }
+ else {
+ CURLcode result;
+ *availp |= CURLAUTH_DIGEST;
+ authp->avail |= CURLAUTH_DIGEST;
+
+ /* We call this function on input Digest headers even if Digest
+ * authentication isn't activated yet, as we need to store the
+ * incoming data from this header in case we are gonna use
+ * Digest. */
+ result = Curl_input_digest(conn, proxy, auth);
+ if(result) {
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
+ }
+ else
+#endif
+ if(checkprefix("Basic", auth)) {
+ *availp |= CURLAUTH_BASIC;
+ authp->avail |= CURLAUTH_BASIC;
+ if(authp->picked == CURLAUTH_BASIC) {
+ /* We asked for Basic authentication but got a 40X back
+ anyway, which basically means our name+password isn't
+ valid. */
+ authp->avail = CURLAUTH_NONE;
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
+
+ /* there may be multiple methods on one line, so keep reading */
+ while(*auth && *auth != ',') /* read up to the next comma */
+ auth++;
+ if(*auth == ',') /* if we're on a comma, skip it */
+ auth++;
+ while(*auth && ISSPACE(*auth))
+ auth++;
+ }
+ return CURLE_OK;
+}
+
+/**
+ * http_should_fail() determines whether an HTTP response has gotten us
+ * into an error state or not.
+ *
+ * @param conn all information about the current connection
+ *
+ * @retval 0 communications should continue
+ *
+ * @retval 1 communications should not continue
+ */
+static int http_should_fail(struct connectdata *conn)
+{
+ struct SessionHandle *data;
+ int httpcode;
+
+ DEBUGASSERT(conn);
+ data = conn->data;
+ DEBUGASSERT(data);
+
+ httpcode = data->req.httpcode;
+
+ /*
+ ** If we haven't been asked to fail on error,
+ ** don't fail.
+ */
+ if(!data->set.http_fail_on_error)
+ return 0;
+
+ /*
+ ** Any code < 400 is never terminal.
+ */
+ if(httpcode < 400)
+ return 0;
+
+ /*
+ ** Any code >= 400 that's not 401 or 407 is always
+ ** a terminal error
+ */
+ if((httpcode != 401) &&
+ (httpcode != 407))
+ return 1;
+
+ /*
+ ** All we have left to deal with is 401 and 407
+ */
+ DEBUGASSERT((httpcode == 401) || (httpcode == 407));
+
+ /*
+ ** Examine the current authentication state to see if this
+ ** is an error. The idea is for this function to get
+ ** called after processing all the headers in a response
+ ** message. So, if we've been to asked to authenticate a
+ ** particular stage, and we've done it, we're OK. But, if
+ ** we're already completely authenticated, it's not OK to
+ ** get another 401 or 407.
+ **
+ ** It is possible for authentication to go stale such that
+ ** the client needs to reauthenticate. Once that info is
+ ** available, use it here.
+ */
+
+ /*
+ ** Either we're not authenticating, or we're supposed to
+ ** be authenticating something else. This is an error.
+ */
+ if((httpcode == 401) && !conn->bits.user_passwd)
+ return TRUE;
+ if((httpcode == 407) && !conn->bits.proxy_user_passwd)
+ return TRUE;
+
+ return data->state.authproblem;
+}
+
+/*
+ * readmoredata() is a "fread() emulation" to provide POST and/or request
+ * data. It is used when a huge POST is to be made and the entire chunk wasn't
+ * sent in the first send(). This function will then be called from the
+ * transfer.c loop when more data is to be sent to the peer.
+ *
+ * Returns the amount of bytes it filled the buffer with.
+ */
+static size_t readmoredata(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct HTTP *http = conn->data->req.protop;
+ size_t fullsize = size * nitems;
+
+ if(0 == http->postsize)
+ /* nothing to return */
+ return 0;
+
+ /* make sure that a HTTP request is never sent away chunked! */
+ conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
+
+ if(http->postsize <= (curl_off_t)fullsize) {
+ memcpy(buffer, http->postdata, (size_t)http->postsize);
+ fullsize = (size_t)http->postsize;
+
+ if(http->backup.postsize) {
+ /* move backup data into focus and continue on that */
+ http->postdata = http->backup.postdata;
+ http->postsize = http->backup.postsize;
+ conn->fread_func = http->backup.fread_func;
+ conn->fread_in = http->backup.fread_in;
+
+ http->sending++; /* move one step up */
+
+ http->backup.postsize=0;
+ }
+ else
+ http->postsize = 0;
+
+ return fullsize;
+ }
+
+ memcpy(buffer, http->postdata, fullsize);
+ http->postdata += fullsize;
+ http->postsize -= fullsize;
+
+ return fullsize;
+}
+
+/* ------------------------------------------------------------------------- */
+/* add_buffer functions */
+
+/*
+ * Curl_add_buffer_init() sets up and returns a fine buffer struct
+ */
+CURL_STATIC Curl_send_buffer *Curl_add_buffer_init(void)
+{
+ return calloc(1, sizeof(Curl_send_buffer));
+}
+
+/*
+ * Curl_add_buffer_send() sends a header buffer and frees all associated
+ * memory. Body data may be appended to the header data if desired.
+ *
+ * Returns CURLcode
+ */
+CURL_STATIC CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+ struct connectdata *conn,
+
+ /* add the number of sent bytes to this
+ counter */
+ long *bytes_written,
+
+ /* how much of the buffer contains body data */
+ size_t included_body_bytes,
+ int socketindex)
+
+{
+ ssize_t amount;
+ CURLcode result;
+ char *ptr;
+ size_t size;
+ struct HTTP *http = conn->data->req.protop;
+ size_t sendsize;
+ curl_socket_t sockfd;
+ size_t headersize;
+
+ DEBUGASSERT(socketindex <= SECONDARYSOCKET);
+
+ sockfd = conn->sock[socketindex];
+
+ /* The looping below is required since we use non-blocking sockets, but due
+ to the circumstances we will just loop and try again and again etc */
+
+ ptr = in->buffer;
+ size = in->size_used;
+
+ headersize = size - included_body_bytes; /* the initial part that isn't body
+ is header */
+
+ DEBUGASSERT(size > included_body_bytes);
+
+ result = Curl_convert_to_network(conn->data, ptr, headersize);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result) {
+ /* conversion failed, free memory and return to the caller */
+ free(in->buffer);
+ free(in);
+ return result;
+ }
+
+
+ if(conn->handler->flags & PROTOPT_SSL) {
+ /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
+ when we speak HTTPS, as if only a fraction of it is sent now, this data
+ needs to fit into the normal read-callback buffer later on and that
+ buffer is using this size.
+ */
+
+ sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
+
+ /* OpenSSL is very picky and we must send the SAME buffer pointer to the
+ library when we attempt to re-send this buffer. Sending the same data
+ is not enough, we must use the exact same address. For this reason, we
+ must copy the data to the uploadbuffer first, since that is the buffer
+ we will be using if this send is retried later.
+ */
+ memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
+ ptr = conn->data->state.uploadbuffer;
+ }
+ else
+ sendsize = size;
+
+ result = Curl_write(conn, sockfd, ptr, sendsize, &amount);
+
+ if(!result) {
+ /*
+ * Note that we may not send the entire chunk at once, and we have a set
+ * number of data bytes at the end of the big buffer (out of which we may
+ * only send away a part).
+ */
+ /* how much of the header that was sent */
+ size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
+ size_t bodylen = amount - headlen;
+
+ if(conn->data->set.verbose) {
+ /* this data _may_ contain binary stuff */
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
+ if(bodylen) {
+ /* there was body data sent beyond the initial header part, pass that
+ on to the debug callback too */
+ Curl_debug(conn->data, CURLINFO_DATA_OUT,
+ ptr+headlen, bodylen, conn);
+ }
+ }
+ if(bodylen)
+ /* since we sent a piece of the body here, up the byte counter for it
+ accordingly */
+ http->writebytecount += bodylen;
+
+ /* 'amount' can never be a very large value here so typecasting it so a
+ signed 31 bit value should not cause problems even if ssize_t is
+ 64bit */
+ *bytes_written += (long)amount;
+
+ if(http) {
+ if((size_t)amount != size) {
+ /* The whole request could not be sent in one system call. We must
+ queue it up and send it later when we get the chance. We must not
+ loop here and wait until it might work again. */
+
+ size -= amount;
+
+ ptr = in->buffer + amount;
+
+ /* backup the currently set pointers */
+ http->backup.fread_func = conn->fread_func;
+ http->backup.fread_in = conn->fread_in;
+ http->backup.postdata = http->postdata;
+ http->backup.postsize = http->postsize;
+
+ /* set the new pointers for the request-sending */
+ conn->fread_func = (curl_read_callback)readmoredata;
+ conn->fread_in = (void *)conn;
+ http->postdata = ptr;
+ http->postsize = (curl_off_t)size;
+
+ http->send_buffer = in;
+ http->sending = HTTPSEND_REQUEST;
+
+ return CURLE_OK;
+ }
+ http->sending = HTTPSEND_BODY;
+ /* the full buffer was sent, clean up and return */
+ }
+ else {
+ if((size_t)amount != size)
+ /* We have no continue-send mechanism now, fail. This can only happen
+ when this function is used from the CONNECT sending function. We
+ currently (stupidly) assume that the whole request is always sent
+ away in the first single chunk.
+
+ This needs FIXing.
+ */
+ return CURLE_SEND_ERROR;
+ else
+ conn->writechannel_inuse = FALSE;
+ }
+ }
+ free(in->buffer);
+ free(in);
+
+ return result;
+}
+
+
+/*
+ * add_bufferf() add the formatted input to the buffer.
+ */
+CURL_STATIC CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
+{
+ char *s;
+ va_list ap;
+ va_start(ap, fmt);
+ s = vaprintf(fmt, ap); /* this allocs a new string to append */
+ va_end(ap);
+
+ if(s) {
+ CURLcode result = Curl_add_buffer(in, s, strlen(s));
+ free(s);
+ return result;
+ }
+ /* If we failed, we cleanup the whole buffer and return error */
+ free(in->buffer);
+ free(in);
+ return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * add_buffer() appends a memory chunk to the existing buffer
+ */
+CURL_STATIC CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
+{
+ char *new_rb;
+ size_t new_size;
+
+ if(~size < in->size_used) {
+ /* If resulting used size of send buffer would wrap size_t, cleanup
+ the whole buffer and return error. Otherwise the required buffer
+ size will fit into a single allocatable memory chunk */
+ Curl_safefree(in->buffer);
+ free(in);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!in->buffer ||
+ ((in->size_used + size) > (in->size_max - 1))) {
+
+ /* If current buffer size isn't enough to hold the result, use a
+ buffer size that doubles the required size. If this new size
+ would wrap size_t, then just use the largest possible one */
+
+ if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
+ (~(size*2) < (in->size_used*2)))
+ new_size = (size_t)-1;
+ else
+ new_size = (in->size_used+size)*2;
+
+ if(in->buffer)
+ /* we have a buffer, enlarge the existing one */
+ new_rb = realloc(in->buffer, new_size);
+ else
+ /* create a new buffer */
+ new_rb = malloc(new_size);
+
+ if(!new_rb) {
+ /* If we failed, we cleanup the whole buffer and return error */
+ Curl_safefree(in->buffer);
+ free(in);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ in->buffer = new_rb;
+ in->size_max = new_size;
+ }
+ memcpy(&in->buffer[in->size_used], inptr, size);
+
+ in->size_used += size;
+
+ return CURLE_OK;
+}
+
+/* end of the add_buffer functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/*
+ * Curl_compareheader()
+ *
+ * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
+ * Pass headers WITH the colon.
+ */
+bool
+Curl_compareheader(const char *headerline, /* line to check */
+ const char *header, /* header keyword _with_ colon */
+ const char *content) /* content string to find */
+{
+ /* RFC2616, section 4.2 says: "Each header field consists of a name followed
+ * by a colon (":") and the field value. Field names are case-insensitive.
+ * The field value MAY be preceded by any amount of LWS, though a single SP
+ * is preferred." */
+
+ size_t hlen = strlen(header);
+ size_t clen;
+ size_t len;
+ const char *start;
+ const char *end;
+
+ if(!Curl_raw_nequal(headerline, header, hlen))
+ return FALSE; /* doesn't start with header */
+
+ /* pass the header */
+ start = &headerline[hlen];
+
+ /* pass all white spaces */
+ while(*start && ISSPACE(*start))
+ start++;
+
+ /* find the end of the header line */
+ end = strchr(start, '\r'); /* lines end with CRLF */
+ if(!end) {
+ /* in case there's a non-standard compliant line here */
+ end = strchr(start, '\n');
+
+ if(!end)
+ /* hm, there's no line ending here, use the zero byte! */
+ end = strchr(start, '\0');
+ }
+
+ len = end-start; /* length of the content part of the input line */
+ clen = strlen(content); /* length of the word to find */
+
+ /* find the content string in the rest of the line */
+ for(;len>=clen;len--, start++) {
+ if(Curl_raw_nequal(start, content, clen))
+ return TRUE; /* match! */
+ }
+
+ return FALSE; /* no match */
+}
+
+/*
+ * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
+ * the generic Curl_connect().
+ */
+CURL_STATIC CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result;
+
+ /* We default to persistent connections. We set this already in this connect
+ function to make the re-use checks properly be able to check this bit. */
+ connkeep(conn, "HTTP default");
+
+ /* the CONNECT procedure might not have been completed */
+ result = Curl_proxy_connect(conn);
+ if(result)
+ return result;
+
+ if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ /* nothing else to do except wait right now - we're not done here. */
+ return CURLE_OK;
+
+ if(conn->given->flags & PROTOPT_SSL) {
+ /* perform SSL initialization */
+ result = https_connecting(conn, done);
+ if(result)
+ return result;
+ }
+ else
+ *done = TRUE;
+
+ return CURLE_OK;
+}
+
+/* this returns the socket to wait for in the DO and DOING state for the multi
+ interface and then we're always _sending_ a request and thus we wait for
+ the single socket to become writable only */
+static int http_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ /* write mode */
+ (void)numsocks; /* unused, we trust it to be at least 1 */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_WRITESOCK(0);
+}
+
+#ifdef USE_SSL
+static CURLcode https_connecting(struct connectdata *conn, bool *done)
+{
+ CURLcode result;
+ DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
+
+ /* perform SSL initialization for this socket */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
+ if(result)
+ connclose(conn, "Failed HTTPS connection");
+
+ return result;
+}
+#endif
+
+#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
+ defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS)
+/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
+ It should be made to query the generic SSL layer instead. */
+static int https_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn->handler->flags & PROTOPT_SSL) {
+ struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ /* write mode */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_WRITESOCK(0);
+ }
+ else if(connssl->connecting_state == ssl_connect_2_reading) {
+ /* read mode */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0);
+ }
+ }
+ return CURLE_OK;
+}
+#else
+#ifdef USE_SSL
+static int https_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return GETSOCK_BLANK;
+}
+#endif /* USE_SSL */
+#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
+
+/*
+ * Curl_http_done() gets called from Curl_done() after a single HTTP request
+ * has been performed.
+ */
+
+CURL_STATIC CURLcode Curl_http_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct SessionHandle *data = conn->data;
+ struct HTTP *http =data->req.protop;
+
+ Curl_unencode_cleanup(conn);
+
+#ifdef USE_SPNEGO
+ if(data->state.proxyneg.state == GSS_AUTHSENT ||
+ data->state.negotiate.state == GSS_AUTHSENT) {
+ /* add forbid re-use if http-code != 401/407 as a WA only needed for
+ * 401/407 that signal auth failure (empty) otherwise state will be RECV
+ * with current code */
+ if((data->req.httpcode != 401) && (data->req.httpcode != 407))
+ connclose(conn, "Negotiate transfer completed");
+ Curl_cleanup_negotiate(data);
+ }
+#endif
+
+ /* set the proper values (possibly modified on POST) */
+ conn->fread_func = data->set.fread_func; /* restore */
+ conn->fread_in = data->set.in; /* restore */
+ conn->seek_func = data->set.seek_func; /* restore */
+ conn->seek_client = data->set.seek_client; /* restore */
+
+ if(http == NULL)
+ return CURLE_OK;
+
+ if(http->send_buffer) {
+ Curl_send_buffer *buff = http->send_buffer;
+
+ free(buff->buffer);
+ free(buff);
+ http->send_buffer = NULL; /* clear the pointer */
+ }
+
+ if(HTTPREQ_POST_FORM == data->set.httpreq) {
+ data->req.bytecount = http->readbytecount + http->writebytecount;
+
+ Curl_formclean(&http->sendit); /* Now free that whole lot */
+ if(http->form.fp) {
+ /* a file being uploaded was left opened, close it! */
+ fclose(http->form.fp);
+ http->form.fp = NULL;
+ }
+ }
+ else if(HTTPREQ_PUT == data->set.httpreq)
+ data->req.bytecount = http->readbytecount + http->writebytecount;
+
+ if(status)
+ return status;
+
+ if(!premature && /* this check is pointless when DONE is called before the
+ entire operation is complete */
+ !conn->bits.retry &&
+ !data->set.connect_only &&
+ ((http->readbytecount +
+ data->req.headerbytecount -
+ data->req.deductheadercount)) <= 0) {
+ /* If this connection isn't simply closed to be retried, AND nothing was
+ read from the HTTP server (that counts), this can't be right so we
+ return an error here */
+ failf(data, "Empty reply from server");
+ return CURLE_GOT_NOTHING;
+ }
+
+ return CURLE_OK;
+}
+
+
+/*
+ * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
+ * to avoid it include:
+ *
+ * - if the user specifically requested HTTP 1.0
+ * - if the server we are connected to only supports 1.0
+ * - if any server previously contacted to handle this request only supports
+ * 1.0.
+ */
+static bool use_http_1_1plus(const struct SessionHandle *data,
+ const struct connectdata *conn)
+{
+ return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
+ ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
+ ((conn->httpversion == 11) ||
+ ((conn->httpversion != 10) &&
+ (data->state.httpversion != 10))))) ? TRUE : FALSE;
+}
+
+/* check and possibly add an Expect: header */
+static CURLcode expect100(struct SessionHandle *data,
+ struct connectdata *conn,
+ Curl_send_buffer *req_buffer)
+{
+ CURLcode result = CURLE_OK;
+ const char *ptr;
+ data->state.expect100header = FALSE; /* default to false unless it is set
+ to TRUE below */
+ if(use_http_1_1plus(data, conn) &&
+ (conn->httpversion != 20)) {
+ /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
+ Expect: 100-continue to the headers which actually speeds up post
+ operations (as there is one packet coming back from the web server) */
+ ptr = Curl_checkheaders(conn, "Expect:");
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, "Expect:", "100-continue");
+ }
+ else {
+ result = Curl_add_bufferf(req_buffer,
+ "Expect: 100-continue\r\n");
+ if(!result)
+ data->state.expect100header = TRUE;
+ }
+ }
+ return result;
+}
+
+enum proxy_use {
+ HEADER_SERVER, /* direct to server */
+ HEADER_PROXY, /* regular request to proxy */
+ HEADER_CONNECT /* sending CONNECT to a proxy */
+};
+
+CURL_STATIC CURLcode Curl_add_custom_headers(struct connectdata *conn,
+ bool is_connect,
+ Curl_send_buffer *req_buffer)
+{
+ char *ptr;
+ struct curl_slist *h[2];
+ struct curl_slist *headers;
+ int numlists=1; /* by default */
+ struct SessionHandle *data = conn->data;
+ int i;
+
+ enum proxy_use proxy;
+
+ if(is_connect)
+ proxy = HEADER_CONNECT;
+ else
+ proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
+ HEADER_PROXY:HEADER_SERVER;
+
+ switch(proxy) {
+ case HEADER_SERVER:
+ h[0] = data->set.headers;
+ break;
+ case HEADER_PROXY:
+ h[0] = data->set.headers;
+ if(data->set.sep_headers) {
+ h[1] = data->set.proxyheaders;
+ numlists++;
+ }
+ break;
+ case HEADER_CONNECT:
+ if(data->set.sep_headers)
+ h[0] = data->set.proxyheaders;
+ else
+ h[0] = data->set.headers;
+ break;
+ }
+
+ /* loop through one or two lists */
+ for(i=0; i < numlists; i++) {
+ headers = h[i];
+
+ while(headers) {
+ ptr = strchr(headers->data, ':');
+ if(ptr) {
+ /* we require a colon for this to be a true header */
+
+ ptr++; /* pass the colon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* only send this if the contents was non-blank */
+
+ if(conn->allocptr.host &&
+ /* a Host: header was sent already, don't pass on any custom Host:
+ header as that will produce *two* in the same request! */
+ checkprefix("Host:", headers->data))
+ ;
+ else if(data->set.httpreq == HTTPREQ_POST_FORM &&
+ /* this header (extended by formdata.c) is sent later */
+ checkprefix("Content-Type:", headers->data))
+ ;
+ else if(conn->bits.authneg &&
+ /* while doing auth neg, don't allow the custom length since
+ we will force length zero then */
+ checkprefix("Content-Length", headers->data))
+ ;
+ else if(conn->allocptr.te &&
+ /* when asking for Transfer-Encoding, don't pass on a custom
+ Connection: */
+ checkprefix("Connection", headers->data))
+ ;
+ else {
+ CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
+ headers->data);
+ if(result)
+ return result;
+ }
+ }
+ }
+ else {
+ ptr = strchr(headers->data, ';');
+ if(ptr) {
+
+ ptr++; /* pass the semicolon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* this may be used for something else in the future */
+ }
+ else {
+ if(*(--ptr) == ';') {
+ CURLcode result;
+
+ /* send no-value custom header if terminated by semicolon */
+ *ptr = ':';
+ result = Curl_add_bufferf(req_buffer, "%s\r\n",
+ headers->data);
+ if(result)
+ return result;
+ }
+ }
+ }
+ }
+ headers = headers->next;
+ }
+ }
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_add_timecondition(struct SessionHandle *data,
+ Curl_send_buffer *req_buffer)
+{
+ const struct tm *tm;
+ char *buf = data->state.buffer;
+ struct tm keeptime;
+ CURLcode result = Curl_gmtime(data->set.timevalue, &keeptime);
+ if(result) {
+ failf(data, "Invalid TIMEVALUE");
+ return result;
+ }
+ tm = &keeptime;
+
+ /* The If-Modified-Since header family should have their times set in
+ * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
+ * represented in Greenwich Mean Time (GMT), without exception. For the
+ * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
+ * Time)." (see page 20 of RFC2616).
+ */
+
+ /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
+ snprintf(buf, BUFSIZE-1,
+ "%s, %02d %s %4d %02d:%02d:%02d GMT",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+
+ switch(data->set.timecondition) {
+ case CURL_TIMECOND_IFMODSINCE:
+ default:
+ result = Curl_add_bufferf(req_buffer,
+ "If-Modified-Since: %s\r\n", buf);
+ break;
+ case CURL_TIMECOND_IFUNMODSINCE:
+ result = Curl_add_bufferf(req_buffer,
+ "If-Unmodified-Since: %s\r\n", buf);
+ break;
+ case CURL_TIMECOND_LASTMOD:
+ result = Curl_add_bufferf(req_buffer,
+ "Last-Modified: %s\r\n", buf);
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * Curl_http() gets called from the generic Curl_do() function when a HTTP
+ * request is to be performed. This creates and sends a properly constructed
+ * HTTP request.
+ */
+CURL_STATIC CURLcode Curl_http(struct connectdata *conn, bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode result = CURLE_OK;
+ struct HTTP *http;
+ const char *ppath = data->state.path;
+ bool paste_ftp_userpwd = FALSE;
+ char ftp_typecode[sizeof("/;type=?")] = "";
+ const char *host = conn->host.name;
+ const char *te = ""; /* transfer-encoding */
+ const char *ptr;
+ const char *request;
+ Curl_HttpReq httpreq = data->set.httpreq;
+#if !defined(CURL_DISABLE_COOKIES)
+ char *addcookies = NULL;
+#endif
+ curl_off_t included_body = 0;
+ const char *httpstring;
+ Curl_send_buffer *req_buffer;
+ curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
+ int seekerr = CURL_SEEKFUNC_OK;
+
+ /* Always consider the DO phase done after this function call, even if there
+ may be parts of the request that is not yet sent, since we can deal with
+ the rest of the request in the PERFORM phase. */
+ *done = TRUE;
+
+ if(conn->httpversion < 20) { /* unless the connection is re-used and already
+ http2 */
+ switch(conn->negnpn) {
+ case CURL_HTTP_VERSION_2_0:
+ conn->httpversion = 20; /* we know we're on HTTP/2 now */
+ result = Curl_http2_init(conn);
+ if(result)
+ return result;
+
+ result = Curl_http2_setup(conn);
+ if(result)
+ return result;
+
+ result = Curl_http2_switched(conn, NULL, 0);
+ if(result)
+ return result;
+ break;
+ case CURL_HTTP_VERSION_1_1:
+ /* continue with HTTP/1.1 when explicitly requested */
+ break;
+ default:
+ /* and as fallback */
+ break;
+ }
+ }
+ else {
+ /* prepare for a http2 request */
+ result = Curl_http2_setup(conn);
+ if(result)
+ return result;
+ }
+
+ http = data->req.protop;
+
+ if(!data->state.this_is_a_follow) {
+ /* Free to avoid leaking memory on multiple requests*/
+ free(data->state.first_host);
+
+ data->state.first_host = strdup(conn->host.name);
+ if(!data->state.first_host)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ http->writebytecount = http->readbytecount = 0;
+
+ if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
+ data->set.upload) {
+ httpreq = HTTPREQ_PUT;
+ }
+
+ /* Now set the 'request' pointer to the proper request string */
+ if(data->set.str[STRING_CUSTOMREQUEST])
+ request = data->set.str[STRING_CUSTOMREQUEST];
+ else {
+ if(data->set.opt_no_body)
+ request = "HEAD";
+ else {
+ DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
+ switch(httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ request = "POST";
+ break;
+ case HTTPREQ_PUT:
+ request = "PUT";
+ break;
+ default: /* this should never happen */
+ case HTTPREQ_GET:
+ request = "GET";
+ break;
+ case HTTPREQ_HEAD:
+ request = "HEAD";
+ break;
+ }
+ }
+ }
+
+ /* The User-Agent string might have been allocated in url.c already, because
+ it might have been used in the proxy connect, but if we have got a header
+ with the user-agent string specified, we erase the previously made string
+ here. */
+ if(Curl_checkheaders(conn, "User-Agent:")) {
+ free(conn->allocptr.uagent);
+ conn->allocptr.uagent=NULL;
+ }
+
+ /* setup the authentication headers */
+ result = Curl_http_output_auth(conn, request, ppath, FALSE);
+ if(result)
+ return result;
+
+ if((data->state.authhost.multi || data->state.authproxy.multi) &&
+ (httpreq != HTTPREQ_GET) &&
+ (httpreq != HTTPREQ_HEAD)) {
+ /* Auth is required and we are not authenticated yet. Make a PUT or POST
+ with content-length zero as a "probe". */
+ conn->bits.authneg = TRUE;
+ }
+ else
+ conn->bits.authneg = FALSE;
+
+ Curl_safefree(conn->allocptr.ref);
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
+ conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(!conn->allocptr.ref)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else
+ conn->allocptr.ref = NULL;
+
+#if !defined(CURL_DISABLE_COOKIES)
+ if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
+ addcookies = data->set.str[STRING_COOKIE];
+#endif
+
+ if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ data->set.str[STRING_ENCODING]) {
+ Curl_safefree(conn->allocptr.accept_encoding);
+ conn->allocptr.accept_encoding =
+ aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
+ if(!conn->allocptr.accept_encoding)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifdef HAVE_LIBZ
+ /* we only consider transfer-encoding magic if libz support is built-in */
+
+ if(!Curl_checkheaders(conn, "TE:") &&
+ data->set.http_transfer_encoding) {
+ /* When we are to insert a TE: header in the request, we must also insert
+ TE in a Connection: header, so we need to merge the custom provided
+ Connection: header and prevent the original to get sent. Note that if
+ the user has inserted his/hers own TE: header we don't do this magic
+ but then assume that the user will handle it all! */
+ char *cptr = Curl_checkheaders(conn, "Connection:");
+#define TE_HEADER "TE: gzip\r\n"
+
+ Curl_safefree(conn->allocptr.te);
+
+ /* Create the (updated) Connection: header */
+ conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
+ strdup("Connection: TE\r\n" TE_HEADER);
+
+ if(!conn->allocptr.te)
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif
+
+ if(conn->httpversion == 20)
+ /* In HTTP2 forbids Transfer-Encoding: chunked */
+ ptr = NULL;
+ else {
+ ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
+ if(ptr) {
+ /* Some kind of TE is requested, check if 'chunked' is chosen */
+ data->req.upload_chunky =
+ Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
+ }
+ else {
+ if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ data->set.upload &&
+ (data->state.infilesize == -1)) {
+ if(conn->bits.authneg)
+ /* don't enable chunked during auth neg */
+ ;
+ else if(use_http_1_1plus(data, conn)) {
+ /* HTTP, upload, unknown file size and not HTTP 1.0 */
+ data->req.upload_chunky = TRUE;
+ }
+ else {
+ failf(data, "Chunky upload is not supported by HTTP 1.0");
+ return CURLE_UPLOAD_FAILED;
+ }
+ }
+ else {
+ /* else, no chunky upload */
+ data->req.upload_chunky = FALSE;
+ }
+
+ if(data->req.upload_chunky)
+ te = "Transfer-Encoding: chunked\r\n";
+ }
+ }
+
+ Curl_safefree(conn->allocptr.host);
+
+ ptr = Curl_checkheaders(conn, "Host:");
+ if(ptr && (!data->state.this_is_a_follow ||
+ Curl_raw_equal(data->state.first_host, conn->host.name))) {
+#if !defined(CURL_DISABLE_COOKIES)
+ /* If we have a given custom Host: header, we extract the host name in
+ order to possibly use it for cookie reasons later on. We only allow the
+ custom Host: header if this is NOT a redirect, as setting Host: in the
+ redirected request is being out on thin ice. Except if the host name
+ is the same as the first one! */
+ char *cookiehost = Curl_copy_header_value(ptr);
+ if(!cookiehost)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*cookiehost)
+ /* ignore empty data */
+ free(cookiehost);
+ else {
+ /* If the host begins with '[', we start searching for the port after
+ the bracket has been closed */
+ int startsearch = 0;
+ if(*cookiehost == '[') {
+ char *closingbracket;
+ /* since the 'cookiehost' is an allocated memory area that will be
+ freed later we cannot simply increment the pointer */
+ memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
+ closingbracket = strchr(cookiehost, ']');
+ if(closingbracket)
+ *closingbracket = 0;
+ }
+ else {
+ char *colon = strchr(cookiehost + startsearch, ':');
+ if(colon)
+ *colon = 0; /* The host must not include an embedded port number */
+ }
+ Curl_safefree(conn->allocptr.cookiehost);
+ conn->allocptr.cookiehost = cookiehost;
+ }
+#endif
+
+ if(strcmp("Host:", ptr)) {
+ conn->allocptr.host = aprintf("%s\r\n", ptr);
+ if(!conn->allocptr.host)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else
+ /* when clearing the header */
+ conn->allocptr.host = NULL;
+ }
+ else {
+ /* When building Host: headers, we must put the host name within
+ [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
+
+ if(((conn->given->protocol&CURLPROTO_HTTPS) &&
+ (conn->remote_port == PORT_HTTPS)) ||
+ ((conn->given->protocol&CURLPROTO_HTTP) &&
+ (conn->remote_port == PORT_HTTP)) )
+ /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
+ the port number in the host string */
+ conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
+ conn->bits.ipv6_ip?"[":"",
+ host,
+ conn->bits.ipv6_ip?"]":"");
+ else
+ conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
+ conn->bits.ipv6_ip?"[":"",
+ host,
+ conn->bits.ipv6_ip?"]":"",
+ conn->remote_port);
+
+ if(!conn->allocptr.host)
+ /* without Host: we can't make a nice request */
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ /* Using a proxy but does not tunnel through it */
+
+ /* The path sent to the proxy is in fact the entire URL. But if the remote
+ host is a IDN-name, we must make sure that the request we produce only
+ uses the encoded host name! */
+ if(conn->host.dispname != conn->host.name) {
+ char *url = data->change.url;
+ ptr = strstr(url, conn->host.dispname);
+ if(ptr) {
+ /* This is where the display name starts in the URL, now replace this
+ part with the encoded name. TODO: This method of replacing the host
+ name is rather crude as I believe there's a slight risk that the
+ user has entered a user name or password that contain the host name
+ string. */
+ size_t currlen = strlen(conn->host.dispname);
+ size_t newlen = strlen(conn->host.name);
+ size_t urllen = strlen(url);
+
+ char *newurl;
+
+ newurl = malloc(urllen + newlen - currlen + 1);
+ if(newurl) {
+ /* copy the part before the host name */
+ memcpy(newurl, url, ptr - url);
+ /* append the new host name instead of the old */
+ memcpy(newurl + (ptr - url), conn->host.name, newlen);
+ /* append the piece after the host name */
+ memcpy(newurl + newlen + (ptr - url),
+ ptr + currlen, /* copy the trailing zero byte too */
+ urllen - (ptr-url) - currlen + 1);
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ data->change.url = newurl;
+ data->change.url_alloc = TRUE;
+ }
+ else
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ ppath = data->change.url;
+ if(checkprefix("ftp://", ppath)) {
+ if(data->set.proxy_transfer_mode) {
+ /* when doing ftp, append ;type=<a|i> if not present */
+ char *type = strstr(ppath, ";type=");
+ if(type && type[6] && type[7] == 0) {
+ switch (Curl_raw_toupper(type[6])) {
+ case 'A':
+ case 'D':
+ case 'I':
+ break;
+ default:
+ type = NULL;
+ }
+ }
+ if(!type) {
+ char *p = ftp_typecode;
+ /* avoid sending invalid URLs like ftp://example.com;type=i if the
+ * user specified ftp://example.com without the slash */
+ if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
+ *p++ = '/';
+ }
+ snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
+ data->set.prefer_ascii ? 'a' : 'i');
+ }
+ }
+ if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
+ paste_ftp_userpwd = TRUE;
+ }
+ }
+#endif /* CURL_DISABLE_PROXY */
+
+ if(HTTPREQ_POST_FORM == httpreq) {
+ /* we must build the whole post sequence first, so that we have a size of
+ the whole transfer before we start to send it */
+ result = Curl_getformdata(data, &http->sendit, data->set.httppost,
+ Curl_checkheaders(conn, "Content-Type:"),
+ &http->postsize);
+ if(result)
+ return result;
+ }
+
+ http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
+
+ if(( (HTTPREQ_POST == httpreq) ||
+ (HTTPREQ_POST_FORM == httpreq) ||
+ (HTTPREQ_PUT == httpreq) ) &&
+ data->state.resume_from) {
+ /**********************************************************************
+ * Resuming upload in HTTP means that we PUT or POST and that we have
+ * got a resume_from value set. The resume value has already created
+ * a Range: header that will be passed along. We need to "fast forward"
+ * the file the given number of bytes and decrease the assume upload
+ * file size before we continue this venture in the dark lands of HTTP.
+ *********************************************************************/
+
+ if(data->state.resume_from < 0 ) {
+ /*
+ * This is meant to get the size of the present remote-file by itself.
+ * We don't support this now. Bail out!
+ */
+ data->state.resume_from = 0;
+ }
+
+ if(data->state.resume_from && !data->state.this_is_a_follow) {
+ /* do we still game? */
+
+ /* Now, let's read off the proper amount of bytes from the
+ input. */
+ if(conn->seek_func) {
+ seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+ SEEK_SET);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_READ_ERROR;
+ }
+ /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
+ BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ data->set.fread_func(data->state.buffer, 1, readthisamountnow,
+ data->set.in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
+ " bytes from the input", passed);
+ return CURLE_READ_ERROR;
+ }
+ } while(passed < data->state.resume_from);
+ }
+ }
+
+ /* now, decrease the size of the read */
+ if(data->state.infilesize>0) {
+ data->state.infilesize -= data->state.resume_from;
+
+ if(data->state.infilesize <= 0) {
+ failf(data, "File already completely uploaded");
+ return CURLE_PARTIAL_FILE;
+ }
+ }
+ /* we've passed, proceed as normal */
+ }
+ }
+ if(data->state.use_range) {
+ /*
+ * A range is selected. We use different headers whether we're downloading
+ * or uploading and we always let customized headers override our internal
+ * ones if any such are specified.
+ */
+ if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
+ !Curl_checkheaders(conn, "Range:")) {
+ /* if a line like this was already allocated, free the previous one */
+ free(conn->allocptr.rangeline);
+ conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
+ data->state.range);
+ }
+ else if((httpreq != HTTPREQ_GET) &&
+ !Curl_checkheaders(conn, "Content-Range:")) {
+
+ /* if a line like this was already allocated, free the previous one */
+ free(conn->allocptr.rangeline);
+
+ if(data->set.set_resume_from < 0) {
+ /* Upload resume was asked for, but we don't know the size of the
+ remote part so we tell the server (and act accordingly) that we
+ upload the whole file (again) */
+ conn->allocptr.rangeline =
+ aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.infilesize - 1, data->state.infilesize);
+
+ }
+ else if(data->state.resume_from) {
+ /* This is because "resume" was selected */
+ curl_off_t total_expected_size=
+ data->state.resume_from + data->state.infilesize;
+ conn->allocptr.rangeline =
+ aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, total_expected_size-1,
+ total_expected_size);
+ }
+ else {
+ /* Range was selected and then we just pass the incoming range and
+ append total size */
+ conn->allocptr.rangeline =
+ aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, data->state.infilesize);
+ }
+ if(!conn->allocptr.rangeline)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Use 1.1 unless the user specifically asked for 1.0 or the server only
+ supports 1.0 */
+ httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
+
+ /* initialize a dynamic send-buffer */
+ req_buffer = Curl_add_buffer_init();
+
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* add the main request stuff */
+ /* GET/HEAD/POST/PUT */
+ result = Curl_add_bufferf(req_buffer, "%s ", request);
+ if(result)
+ return result;
+
+ /* url */
+ if(paste_ftp_userpwd)
+ result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
+ conn->user, conn->passwd,
+ ppath + sizeof("ftp://") - 1);
+ else
+ result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
+ if(result)
+ return result;
+
+ result =
+ Curl_add_bufferf(req_buffer,
+ "%s" /* ftp typecode (;type=x) */
+ " HTTP/%s\r\n" /* HTTP version */
+ "%s" /* host */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* accept */
+ "%s" /* TE: */
+ "%s" /* accept-encoding */
+ "%s" /* referer */
+ "%s" /* Proxy-Connection */
+ "%s",/* transfer-encoding */
+
+ ftp_typecode,
+ httpstring,
+ (conn->allocptr.host?conn->allocptr.host:""),
+ conn->allocptr.proxyuserpwd?
+ conn->allocptr.proxyuserpwd:"",
+ conn->allocptr.userpwd?conn->allocptr.userpwd:"",
+ (data->state.use_range && conn->allocptr.rangeline)?
+ conn->allocptr.rangeline:"",
+ (data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ conn->allocptr.uagent)?
+ conn->allocptr.uagent:"",
+ http->p_accept?http->p_accept:"",
+ conn->allocptr.te?conn->allocptr.te:"",
+ (data->set.str[STRING_ENCODING] &&
+ *data->set.str[STRING_ENCODING] &&
+ conn->allocptr.accept_encoding)?
+ conn->allocptr.accept_encoding:"",
+ (data->change.referer && conn->allocptr.ref)?
+ conn->allocptr.ref:"" /* Referer: <data> */,
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
+ "Proxy-Connection: Keep-Alive\r\n":"",
+ te
+ );
+
+ /*
+ * Free userpwd for Negotiate/NTLM. Cannot reuse as it is associated with
+ * the connection and shouldn't be repeated over it either.
+ */
+ switch (data->state.authhost.picked) {
+ case CURLAUTH_NEGOTIATE:
+ case CURLAUTH_NTLM:
+ case CURLAUTH_NTLM_WB:
+ Curl_safefree(conn->allocptr.userpwd);
+ break;
+ }
+
+ /*
+ * Same for proxyuserpwd
+ */
+ switch (data->state.authproxy.picked) {
+ case CURLAUTH_NEGOTIATE:
+ case CURLAUTH_NTLM:
+ case CURLAUTH_NTLM_WB:
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ break;
+ }
+
+ if(result)
+ return result;
+
+ if(!(conn->handler->flags&PROTOPT_SSL) &&
+ conn->httpversion != 20 &&
+ (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
+ /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
+ over SSL */
+ result = Curl_http2_request_upgrade(req_buffer, conn);
+ if(result)
+ return result;
+ }
+
+#if !defined(CURL_DISABLE_COOKIES)
+ if(data->cookies || addcookies) {
+ struct Cookie *co=NULL; /* no cookies from start */
+ int count=0;
+
+ if(data->cookies) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ co = Curl_cookie_getlist(data->cookies,
+ conn->allocptr.cookiehost?
+ conn->allocptr.cookiehost:host,
+ data->state.path,
+ (conn->handler->protocol&CURLPROTO_HTTPS)?
+ TRUE:FALSE);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ if(co) {
+ struct Cookie *store=co;
+ /* now loop through all cookies that matched */
+ while(co) {
+ if(co->value) {
+ if(0 == count) {
+ result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ if(result)
+ break;
+ }
+ result = Curl_add_bufferf(req_buffer,
+ "%s%s=%s", count?"; ":"",
+ co->name, co->value);
+ if(result)
+ break;
+ count++;
+ }
+ co = co->next; /* next cookie please */
+ }
+ Curl_cookie_freelist(store, FALSE); /* free the cookie list */
+ }
+ if(addcookies && !result) {
+ if(!count)
+ result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ if(!result) {
+ result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"",
+ addcookies);
+ count++;
+ }
+ }
+ if(count && !result)
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+
+ if(result)
+ return result;
+ }
+#endif
+
+ if(data->set.timecondition) {
+ result = Curl_add_timecondition(data, req_buffer);
+ if(result)
+ return result;
+ }
+
+ result = Curl_add_custom_headers(conn, FALSE, req_buffer);
+ if(result)
+ return result;
+
+ http->postdata = NULL; /* nothing to post at this point */
+ Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */
+
+ /* If 'authdone' is FALSE, we must not set the write socket index to the
+ Curl_transfer() call below, as we're not ready to actually upload any
+ data yet. */
+
+ switch(httpreq) {
+
+ case HTTPREQ_POST_FORM:
+ if(!http->sendit || conn->bits.authneg) {
+ /* nothing to post! */
+ result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
+ if(result)
+ return result;
+
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result)
+ failf(data, "Failed sending POST request");
+ else
+ /* setup variables for the upcoming transfer */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
+ -1, NULL);
+ break;
+ }
+
+ if(Curl_FormInit(&http->form, http->sendit)) {
+ failf(data, "Internal HTTP POST error!");
+ return CURLE_HTTP_POST_ERROR;
+ }
+
+ /* Get the currently set callback function pointer and store that in the
+ form struct since we might want the actual user-provided callback later
+ on. The conn->fread_func pointer itself will be changed for the
+ multipart case to the function that returns a multipart formatted
+ stream. */
+ http->form.fread_func = conn->fread_func;
+
+ /* Set the read function to read from the generated form data */
+ conn->fread_func = (curl_read_callback)Curl_FormReader;
+ conn->fread_in = &http->form;
+
+ http->sending = HTTPSEND_BODY;
+
+ if(!data->req.upload_chunky &&
+ !Curl_checkheaders(conn, "Content-Length:")) {
+ /* only add Content-Length if not uploading chunked */
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", http->postsize);
+ if(result)
+ return result;
+ }
+
+ result = expect100(data, conn, req_buffer);
+ if(result)
+ return result;
+
+ {
+
+ /* Get Content-Type: line from Curl_formpostheader.
+ */
+ char *contentType;
+ size_t linelength=0;
+ contentType = Curl_formpostheader((void *)&http->form,
+ &linelength);
+ if(!contentType) {
+ failf(data, "Could not get Content-Type header line!");
+ return CURLE_HTTP_POST_ERROR;
+ }
+
+ result = Curl_add_buffer(req_buffer, contentType, linelength);
+ if(result)
+ return result;
+ }
+
+ /* make the request end in a true CRLF */
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ if(result)
+ return result;
+
+ /* set upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, http->postsize);
+
+ /* fire away the whole request to the server */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result)
+ failf(data, "Failed sending POST request");
+ else
+ /* setup variables for the upcoming transfer */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, FIRSTSOCKET,
+ &http->writebytecount);
+
+ if(result) {
+ Curl_formclean(&http->sendit); /* free that whole lot */
+ return result;
+ }
+
+ /* convert the form data */
+ result = Curl_convert_form(data, http->sendit);
+ if(result) {
+ Curl_formclean(&http->sendit); /* free that whole lot */
+ return result;
+ }
+
+ break;
+
+ case HTTPREQ_PUT: /* Let's PUT the data to the server! */
+
+ if(conn->bits.authneg)
+ postsize = 0;
+ else
+ postsize = data->state.infilesize;
+
+ if((postsize != -1) && !data->req.upload_chunky &&
+ !Curl_checkheaders(conn, "Content-Length:")) {
+ /* only add Content-Length if not uploading chunked */
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", postsize);
+ if(result)
+ return result;
+ }
+
+ if(postsize != 0) {
+ result = expect100(data, conn, req_buffer);
+ if(result)
+ return result;
+ }
+
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
+ if(result)
+ return result;
+
+ /* set the upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, postsize);
+
+ /* this sends the buffer and frees all the buffer resources */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result)
+ failf(data, "Failed sending PUT request");
+ else
+ /* prepare for transfer */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, postsize?FIRSTSOCKET:-1,
+ postsize?&http->writebytecount:NULL);
+ if(result)
+ return result;
+ break;
+
+ case HTTPREQ_POST:
+ /* this is the simple POST, using x-www-form-urlencoded style */
+
+ if(conn->bits.authneg)
+ postsize = 0;
+ else {
+ /* figure out the size of the postfields */
+ postsize = (data->set.postfieldsize != -1)?
+ data->set.postfieldsize:
+ (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
+ }
+
+ /* We only set Content-Length and allow a custom Content-Length if
+ we don't upload data chunked, as RFC2616 forbids us to set both
+ kinds of headers (Transfer-Encoding: chunked and Content-Length) */
+ if((postsize != -1) && !data->req.upload_chunky &&
+ !Curl_checkheaders(conn, "Content-Length:")) {
+ /* we allow replacing this header if not during auth negotiation,
+ although it isn't very wise to actually set your own */
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", postsize);
+ if(result)
+ return result;
+ }
+
+ if(!Curl_checkheaders(conn, "Content-Type:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Type: application/"
+ "x-www-form-urlencoded\r\n");
+ if(result)
+ return result;
+ }
+
+ /* For really small posts we don't use Expect: headers at all, and for
+ the somewhat bigger ones we allow the app to disable it. Just make
+ sure that the expect100header is always set to the preferred value
+ here. */
+ ptr = Curl_checkheaders(conn, "Expect:");
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, "Expect:", "100-continue");
+ }
+ else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
+ result = expect100(data, conn, req_buffer);
+ if(result)
+ return result;
+ }
+ else
+ data->state.expect100header = FALSE;
+
+ if(data->set.postfields) {
+
+ /* In HTTP2, we send request body in DATA frame regardless of
+ its size. */
+ if(conn->httpversion != 20 &&
+ !data->state.expect100header &&
+ (postsize < MAX_INITIAL_POST_SIZE)) {
+ /* if we don't use expect: 100 AND
+ postsize is less than MAX_INITIAL_POST_SIZE
+
+ then append the post data to the HTTP request header. This limit
+ is no magic limit but only set to prevent really huge POSTs to
+ get the data duplicated with malloc() and family. */
+
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ if(result)
+ return result;
+
+ if(!data->req.upload_chunky) {
+ /* We're not sending it 'chunked', append it to the request
+ already now to reduce the number if send() calls */
+ result = Curl_add_buffer(req_buffer, data->set.postfields,
+ (size_t)postsize);
+ included_body = postsize;
+ }
+ else {
+ if(postsize) {
+ /* Append the POST data chunky-style */
+ result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
+ if(!result) {
+ result = Curl_add_buffer(req_buffer, data->set.postfields,
+ (size_t)postsize);
+ if(!result)
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ included_body = postsize + 2;
+ }
+ }
+ if(!result)
+ result = Curl_add_buffer(req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
+ /* 0 CR LF CR LF */
+ included_body += 5;
+ }
+ if(result)
+ return result;
+ /* Make sure the progress information is accurate */
+ Curl_pgrsSetUploadSize(data, postsize);
+ }
+ else {
+ /* A huge POST coming up, do data separate from the request */
+ http->postsize = postsize;
+ http->postdata = data->set.postfields;
+
+ http->sending = HTTPSEND_BODY;
+
+ conn->fread_func = (curl_read_callback)readmoredata;
+ conn->fread_in = (void *)conn;
+
+ /* set the upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, http->postsize);
+
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ if(result)
+ return result;
+ }
+ }
+ else {
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ if(result)
+ return result;
+
+ if(data->req.upload_chunky && conn->bits.authneg) {
+ /* Chunky upload is selected and we're negotiating auth still, send
+ end-of-data only */
+ result = Curl_add_buffer(req_buffer,
+ "\x30\x0d\x0a\x0d\x0a", 5);
+ /* 0 CR LF CR LF */
+ if(result)
+ return result;
+ }
+
+ else if(data->set.postfieldsize) {
+ /* set the upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
+
+ /* set the pointer to mark that we will send the post body using the
+ read callback, but only if we're not in authenticate
+ negotiation */
+ if(!conn->bits.authneg) {
+ http->postdata = (char *)&http->postdata;
+ http->postsize = postsize;
+ }
+ }
+ }
+ /* issue the request */
+ result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
+ (size_t)included_body, FIRSTSOCKET);
+
+ if(result)
+ failf(data, "Failed sending HTTP POST request");
+ else
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
+ http->postdata?&http->writebytecount:NULL);
+ break;
+
+ default:
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ if(result)
+ return result;
+
+ /* issue the request */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+
+ if(result)
+ failf(data, "Failed sending HTTP request");
+ else
+ /* HTTP GET/HEAD download: */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
+ http->postdata?FIRSTSOCKET:-1,
+ http->postdata?&http->writebytecount:NULL);
+ }
+ if(result)
+ return result;
+
+ if(http->writebytecount) {
+ /* if a request-body has been sent off, we make sure this progress is noted
+ properly */
+ Curl_pgrsSetUploadCounter(data, http->writebytecount);
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+
+ if(http->writebytecount >= postsize) {
+ /* already sent the entire request body, mark the "upload" as
+ complete */
+ infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
+ " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ http->writebytecount, postsize);
+ data->req.upload_done = TRUE;
+ data->req.keepon &= ~KEEP_SEND; /* we're done writing */
+ data->req.exp100 = EXP100_SEND_DATA; /* already sent */
+ }
+ }
+
+ return result;
+}
+
+/*
+ * checkhttpprefix()
+ *
+ * Returns TRUE if member of the list matches prefix of string
+ */
+static bool
+checkhttpprefix(struct SessionHandle *data,
+ const char *s)
+{
+ struct curl_slist *head = data->set.http200aliases;
+ bool rc = FALSE;
+#ifdef CURL_DOES_CONVERSIONS
+ /* convert from the network encoding using a scratch area */
+ char *scratch = strdup(s);
+ if(NULL == scratch) {
+ failf (data, "Failed to allocate memory for conversion!");
+ return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
+ }
+ if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(scratch);
+ return FALSE; /* can't return CURLE_foobar so return FALSE */
+ }
+ s = scratch;
+#endif /* CURL_DOES_CONVERSIONS */
+
+ while(head) {
+ if(checkprefix(head->data, s)) {
+ rc = TRUE;
+ break;
+ }
+ head = head->next;
+ }
+
+ if(!rc && (checkprefix("HTTP/", s)))
+ rc = TRUE;
+
+#ifdef CURL_DOES_CONVERSIONS
+ free(scratch);
+#endif /* CURL_DOES_CONVERSIONS */
+ return rc;
+}
+
+#ifndef CURL_DISABLE_RTSP
+static bool
+checkrtspprefix(struct SessionHandle *data,
+ const char *s)
+{
+
+#ifdef CURL_DOES_CONVERSIONS
+ /* convert from the network encoding using a scratch area */
+ char *scratch = strdup(s);
+ if(NULL == scratch) {
+ failf (data, "Failed to allocate memory for conversion!");
+ return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
+ }
+ if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(scratch);
+ return FALSE; /* can't return CURLE_foobar so return FALSE */
+ }
+ s = scratch;
+#else
+ (void)data; /* unused */
+#endif /* CURL_DOES_CONVERSIONS */
+ if(checkprefix("RTSP/", s))
+ return TRUE;
+ else
+ return FALSE;
+}
+#endif /* CURL_DISABLE_RTSP */
+
+static bool
+checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
+ const char *s)
+{
+#ifndef CURL_DISABLE_RTSP
+ if(conn->handler->protocol & CURLPROTO_RTSP)
+ return checkrtspprefix(data, s);
+#else
+ (void)conn;
+#endif /* CURL_DISABLE_RTSP */
+
+ return checkhttpprefix(data, s);
+}
+
+/*
+ * header_append() copies a chunk of data to the end of the already received
+ * header. We make sure that the full string fit in the allocated header
+ * buffer, or else we enlarge it.
+ */
+static CURLcode header_append(struct SessionHandle *data,
+ struct SingleRequest *k,
+ size_t length)
+{
+ if(k->hbuflen + length >= data->state.headersize) {
+ /* We enlarge the header buffer as it is too small */
+ char *newbuff;
+ size_t hbufp_index;
+ size_t newsize;
+
+ if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
+ /* The reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause
+ reallocs infinitely */
+ failf (data, "Avoided giant realloc for header (max is %d)!",
+ CURL_MAX_HTTP_HEADER);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
+ hbufp_index = k->hbufp - data->state.headerbuff;
+ newbuff = realloc(data->state.headerbuff, newsize);
+ if(!newbuff) {
+ failf (data, "Failed to alloc memory for big header!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->state.headersize=newsize;
+ data->state.headerbuff = newbuff;
+ k->hbufp = data->state.headerbuff + hbufp_index;
+ }
+ memcpy(k->hbufp, k->str_start, length);
+ k->hbufp += length;
+ k->hbuflen += length;
+ *k->hbufp = 0;
+
+ return CURLE_OK;
+}
+
+static void print_http_error(struct SessionHandle *data)
+{
+ struct SingleRequest *k = &data->req;
+ char *beg = k->p;
+
+ /* make sure that data->req.p points to the HTTP status line */
+ if(!strncmp(beg, "HTTP", 4)) {
+
+ /* skip to HTTP status code */
+ beg = strchr(beg, ' ');
+ if(beg && *++beg) {
+
+ /* find trailing CR */
+ char end_char = '\r';
+ char *end = strchr(beg, end_char);
+ if(!end) {
+ /* try to find LF (workaround for non-compliant HTTP servers) */
+ end_char = '\n';
+ end = strchr(beg, end_char);
+ }
+
+ if(end) {
+ /* temporarily replace CR or LF by NUL and print the error message */
+ *end = '\0';
+ failf(data, "The requested URL returned error: %s", beg);
+
+ /* restore the previously replaced CR or LF */
+ *end = end_char;
+ return;
+ }
+ }
+ }
+
+ /* fall-back to printing the HTTP status code only */
+ failf(data, "The requested URL returned error: %d", k->httpcode);
+}
+
+/*
+ * Read any HTTP header lines from the server and pass them to the client app.
+ */
+CURL_STATIC CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *stop_reading)
+{
+ CURLcode result;
+ struct SingleRequest *k = &data->req;
+
+ /* header line within buffer loop */
+ do {
+ size_t rest_length;
+ size_t full_length;
+ int writetype;
+
+ /* str_start is start of line within buf */
+ k->str_start = k->str;
+
+ /* data is in network encoding so use 0x0a instead of '\n' */
+ k->end_ptr = memchr(k->str_start, 0x0a, *nread);
+
+ if(!k->end_ptr) {
+ /* Not a complete header line within buffer, append the data to
+ the end of the headerbuff. */
+ result = header_append(data, k, *nread);
+ if(result)
+ return result;
+
+ if(!k->headerline && (k->hbuflen>5)) {
+ /* make a first check that this looks like a protocol header */
+ if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
+ /* this is not the beginning of a protocol first header line */
+ k->header = FALSE;
+ k->badheader = HEADER_ALLBAD;
+ break;
+ }
+ }
+
+ break; /* read more and try again */
+ }
+
+ /* decrease the size of the remaining (supposed) header line */
+ rest_length = (k->end_ptr - k->str)+1;
+ *nread -= (ssize_t)rest_length;
+
+ k->str = k->end_ptr + 1; /* move past new line */
+
+ full_length = k->str - k->str_start;
+
+ result = header_append(data, k, full_length);
+ if(result)
+ return result;
+
+ k->end_ptr = k->hbufp;
+ k->p = data->state.headerbuff;
+
+ /****
+ * We now have a FULL header line that p points to
+ *****/
+
+ if(!k->headerline) {
+ /* the first read header */
+ if((k->hbuflen>5) &&
+ !checkprotoprefix(data, conn, data->state.headerbuff)) {
+ /* this is not the beginning of a protocol first header line */
+ k->header = FALSE;
+ if(*nread)
+ /* since there's more, this is a partial bad header */
+ k->badheader = HEADER_PARTHEADER;
+ else {
+ /* this was all we read so it's all a bad header */
+ k->badheader = HEADER_ALLBAD;
+ *nread = (ssize_t)rest_length;
+ }
+ break;
+ }
+ }
+
+ /* headers are in network encoding so
+ use 0x0a and 0x0d instead of '\n' and '\r' */
+ if((0x0a == *k->p) || (0x0d == *k->p)) {
+ size_t headerlen;
+ /* Zero-length header line means end of headers! */
+
+#ifdef CURL_DOES_CONVERSIONS
+ if(0x0d == *k->p) {
+ *k->p = '\r'; /* replace with CR in host encoding */
+ k->p++; /* pass the CR byte */
+ }
+ if(0x0a == *k->p) {
+ *k->p = '\n'; /* replace with LF in host encoding */
+ k->p++; /* pass the LF byte */
+ }
+#else
+ if('\r' == *k->p)
+ k->p++; /* pass the \r byte */
+ if('\n' == *k->p)
+ k->p++; /* pass the \n byte */
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if(100 <= k->httpcode && 199 >= k->httpcode) {
+ /*
+ * We have made a HTTP PUT or POST and this is 1.1-lingo
+ * that tells us that the server is OK with this and ready
+ * to receive the data.
+ * However, we'll get more headers now so we must get
+ * back into the header-parsing state!
+ */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+
+ /* "A user agent MAY ignore unexpected 1xx status responses." */
+ switch(k->httpcode) {
+ case 100:
+ /* if we did wait for this do enable write now! */
+ if(k->exp100) {
+ k->exp100 = EXP100_SEND_DATA;
+ k->keepon |= KEEP_SEND;
+ }
+ break;
+ case 101:
+ /* Switching Protocols */
+ if(k->upgr101 == UPGR101_REQUESTED) {
+ infof(data, "Received 101\n");
+ k->upgr101 = UPGR101_RECEIVED;
+
+ /* switch to http2 now. The bytes after response headers
+ are also processed here, otherwise they are lost. */
+ result = Curl_http2_switched(conn, k->str, *nread);
+ if(result)
+ return result;
+ *nread = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ k->header = FALSE; /* no more header to parse! */
+
+ if((k->size == -1) && !k->chunk && !conn->bits.close &&
+ (conn->httpversion == 11) &&
+ !(conn->handler->protocol & CURLPROTO_RTSP) &&
+ data->set.httpreq != HTTPREQ_HEAD) {
+ /* On HTTP 1.1, when connection is not to get closed, but no
+ Content-Length nor Content-Encoding chunked have been
+ received, according to RFC2616 section 4.4 point 5, we
+ assume that the server will close the connection to
+ signal the end of the document. */
+ infof(data, "no chunk, no close, no size. Assume close to "
+ "signal end\n");
+ connclose(conn, "HTTP: No end-of-message indicator");
+ }
+ }
+
+ /*
+ * When all the headers have been parsed, see if we should give
+ * up and return an error.
+ */
+ if(http_should_fail(conn)) {
+ failf (data, "The requested URL returned error: %d",
+ k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+
+ /* now, only output this if the header AND body are requested:
+ */
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+
+ headerlen = k->p - data->state.headerbuff;
+
+ result = Curl_client_write(conn, writetype,
+ data->state.headerbuff,
+ headerlen);
+ if(result)
+ return result;
+
+ data->info.header_size += (long)headerlen;
+ data->req.headerbytecount += (long)headerlen;
+
+ data->req.deductheadercount =
+ (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
+
+ if(!*stop_reading) {
+ /* Curl_http_auth_act() checks what authentication methods
+ * that are available and decides which one (if any) to
+ * use. It will set 'newurl' if an auth method was picked. */
+ result = Curl_http_auth_act(conn);
+
+ if(result)
+ return result;
+
+ if(k->httpcode >= 300) {
+ if((!conn->bits.authneg) && !conn->bits.close &&
+ !conn->bits.rewindaftersend) {
+ /*
+ * General treatment of errors when about to send data. Including :
+ * "417 Expectation Failed", while waiting for 100-continue.
+ *
+ * The check for close above is done simply because of something
+ * else has already deemed the connection to get closed then
+ * something else should've considered the big picture and we
+ * avoid this check.
+ *
+ * rewindaftersend indicates that something has told libcurl to
+ * continue sending even if it gets discarded
+ */
+
+ switch(data->set.httpreq) {
+ case HTTPREQ_PUT:
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ /* We got an error response. If this happened before the whole
+ * request body has been sent we stop sending and mark the
+ * connection for closure after we've read the entire response.
+ */
+ if(!k->upload_done) {
+ infof(data, "HTTP error before end of send, stop sending\n");
+ connclose(conn, "Stop sending data before everything sent");
+ k->upload_done = TRUE;
+ k->keepon &= ~KEEP_SEND; /* don't send */
+ if(data->state.expect100header)
+ k->exp100 = EXP100_FAILED;
+ }
+ break;
+
+ default: /* default label present to avoid compiler warnings */
+ break;
+ }
+ }
+ }
+
+ if(conn->bits.rewindaftersend) {
+ /* We rewind after a complete send, so thus we continue
+ sending now */
+ infof(data, "Keep sending data to get tossed away!\n");
+ k->keepon |= KEEP_SEND;
+ }
+ }
+
+ if(!k->header) {
+ /*
+ * really end-of-headers.
+ *
+ * If we requested a "no body", this is a good time to get
+ * out and return home.
+ */
+ if(data->set.opt_no_body)
+ *stop_reading = TRUE;
+ else {
+ /* If we know the expected size of this document, we set the
+ maximum download size to the size of the expected
+ document or else, we won't know when to stop reading!
+
+ Note that we set the download maximum even if we read a
+ "Connection: close" header, to make sure that
+ "Content-Length: 0" still prevents us from attempting to
+ read the (missing) response-body.
+ */
+ /* According to RFC2616 section 4.4, we MUST ignore
+ Content-Length: headers if we are now receiving data
+ using chunked Transfer-Encoding.
+ */
+ if(k->chunk)
+ k->maxdownload = k->size = -1;
+ }
+ if(-1 != k->size) {
+ /* We do this operation even if no_body is true, since this
+ data might be retrieved later with curl_easy_getinfo()
+ and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
+
+ Curl_pgrsSetDownloadSize(data, k->size);
+ k->maxdownload = k->size;
+ }
+
+ /* If max download size is *zero* (nothing) we already
+ have nothing and can safely return ok now! */
+ if(0 == k->maxdownload)
+ *stop_reading = TRUE;
+
+ if(*stop_reading) {
+ /* we make sure that this socket isn't read more now */
+ k->keepon &= ~KEEP_RECV;
+ }
+
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ k->str_start, headerlen, conn);
+ break; /* exit header line loop */
+ }
+
+ /* We continue reading headers, so reset the line-based
+ header parsing variables hbufp && hbuflen */
+ k->hbufp = data->state.headerbuff;
+ k->hbuflen = 0;
+ continue;
+ }
+
+ /*
+ * Checks for special headers coming up.
+ */
+
+ if(!k->headerline++) {
+ /* This is the first header, it MUST be the error code line
+ or else we consider this to be the body right away! */
+ int httpversion_major;
+ int rtspversion_major;
+ int nc = 0;
+#ifdef CURL_DOES_CONVERSIONS
+#define HEADER1 scratch
+#define SCRATCHSIZE 21
+ CURLcode res;
+ char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
+ /* We can't really convert this yet because we
+ don't know if it's the 1st header line or the body.
+ So we do a partial conversion into a scratch area,
+ leaving the data at k->p as-is.
+ */
+ strncpy(&scratch[0], k->p, SCRATCHSIZE);
+ scratch[SCRATCHSIZE] = 0; /* null terminate */
+ res = Curl_convert_from_network(data,
+ &scratch[0],
+ SCRATCHSIZE);
+ if(res)
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ return res;
+#else
+#define HEADER1 k->p /* no conversion needed, just use k->p */
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ /*
+ * https://tools.ietf.org/html/rfc7230#section-3.1.2
+ *
+ * The reponse code is always a three-digit number in HTTP as the spec
+ * says. We try to allow any number here, but we cannot make
+ * guarantees on future behaviors since it isn't within the protocol.
+ */
+ nc = sscanf(HEADER1,
+ " HTTP/%d.%d %d",
+ &httpversion_major,
+ &conn->httpversion,
+ &k->httpcode);
+ if(nc==3) {
+ conn->httpversion += 10 * httpversion_major;
+
+ if(k->upgr101 == UPGR101_RECEIVED) {
+ /* supposedly upgraded to http2 now */
+ if(conn->httpversion != 20)
+ infof(data, "Lying server, not serving HTTP/2\n");
+ }
+ }
+ else {
+ /* this is the real world, not a Nirvana
+ NCSA 1.5.x returns this crap when asked for HTTP/1.1
+ */
+ nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
+ conn->httpversion = 10;
+
+ /* If user has set option HTTP200ALIASES,
+ compare header line against list of aliases
+ */
+ if(!nc) {
+ if(checkhttpprefix(data, k->p)) {
+ nc = 1;
+ k->httpcode = 200;
+ conn->httpversion = 10;
+ }
+ }
+ }
+ }
+ else if(conn->handler->protocol & CURLPROTO_RTSP) {
+ nc = sscanf(HEADER1,
+ " RTSP/%d.%d %3d",
+ &rtspversion_major,
+ &conn->rtspversion,
+ &k->httpcode);
+ if(nc==3) {
+ conn->rtspversion += 10 * rtspversion_major;
+ conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
+ }
+ else {
+ /* TODO: do we care about the other cases here? */
+ nc = 0;
+ }
+ }
+
+ if(nc) {
+ data->info.httpcode = k->httpcode;
+
+ data->info.httpversion = conn->httpversion;
+ if(!data->state.httpversion ||
+ data->state.httpversion > conn->httpversion)
+ /* store the lowest server version we encounter */
+ data->state.httpversion = conn->httpversion;
+
+ /*
+ * This code executes as part of processing the header. As a
+ * result, it's not totally clear how to interpret the
+ * response code yet as that depends on what other headers may
+ * be present. 401 and 407 may be errors, but may be OK
+ * depending on how authentication is working. Other codes
+ * are definitely errors, so give up here.
+ */
+ if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
+ ((k->httpcode != 401) || !conn->bits.user_passwd) &&
+ ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
+
+ if(data->state.resume_from &&
+ (data->set.httpreq==HTTPREQ_GET) &&
+ (k->httpcode == 416)) {
+ /* "Requested Range Not Satisfiable", just proceed and
+ pretend this is no error */
+ }
+ else {
+ /* serious error, go home! */
+ print_http_error(data);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+ }
+
+ if(conn->httpversion == 10) {
+ /* Default action for HTTP/1.0 must be to close, unless
+ we get one of those fancy headers that tell us the
+ server keeps it open for us! */
+ infof(data, "HTTP 1.0, assume close after body\n");
+ connclose(conn, "HTTP/1.0 close after body");
+ }
+ else if(conn->httpversion == 20 ||
+ (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
+ /* Don't enable pipelining for HTTP/2 or upgraded connection. For
+ HTTP/2, we do not support multiplexing. In general, requests
+ cannot be pipelined in upgraded connection, since it is now
+ different protocol. */
+ DEBUGF(infof(data,
+ "HTTP 2 or upgraded connection do not support "
+ "pipelining for now\n"));
+ }
+ else if(conn->httpversion >= 11 &&
+ !conn->bits.close) {
+ struct connectbundle *cb_ptr;
+
+ /* If HTTP version is >= 1.1 and connection is persistent
+ server supports pipelining. */
+ DEBUGF(infof(data,
+ "HTTP 1.1 or later with persistent connection, "
+ "pipelining supported\n"));
+ /* Activate pipelining if needed */
+ cb_ptr = conn->bundle;
+ if(cb_ptr) {
+ if(!Curl_pipeline_site_blacklisted(data, conn))
+ cb_ptr->server_supports_pipelining = TRUE;
+ }
+ }
+
+ switch(k->httpcode) {
+ case 204:
+ /* (quote from RFC2616, section 10.2.5): The server has
+ * fulfilled the request but does not need to return an
+ * entity-body ... The 204 response MUST NOT include a
+ * message-body, and thus is always terminated by the first
+ * empty line after the header fields. */
+ /* FALLTHROUGH */
+ case 304:
+ /* (quote from RFC2616, section 10.3.5): The 304 response
+ * MUST NOT contain a message-body, and thus is always
+ * terminated by the first empty line after the header
+ * fields. */
+ if(data->set.timecondition)
+ data->info.timecond = TRUE;
+ k->size=0;
+ k->maxdownload=0;
+ k->ignorecl = TRUE; /* ignore Content-Length headers */
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+ }
+ else {
+ k->header = FALSE; /* this is not a header line */
+ break;
+ }
+ }
+
+ result = Curl_convert_from_network(data, k->p, strlen(k->p));
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ /* Check for Content-Length: header lines to get size */
+ if(!k->ignorecl && !data->set.ignorecl &&
+ checkprefix("Content-Length:", k->p)) {
+ curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
+ if(data->set.max_filesize &&
+ contentlength > data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+ if(contentlength >= 0) {
+ k->size = contentlength;
+ k->maxdownload = k->size;
+ /* we set the progress download size already at this point
+ just to make it easier for apps/callbacks to extract this
+ info as soon as possible */
+ Curl_pgrsSetDownloadSize(data, k->size);
+ }
+ else {
+ /* Negative Content-Length is really odd, and we know it
+ happens for example when older Apache servers send large
+ files */
+ connclose(conn, "negative content-length");
+ infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
+ ", closing after transfer\n", contentlength);
+ }
+ }
+ /* check for Content-Type: header lines to get the MIME-type */
+ else if(checkprefix("Content-Type:", k->p)) {
+ char *contenttype = Curl_copy_header_value(k->p);
+ if(!contenttype)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*contenttype)
+ /* ignore empty data */
+ free(contenttype);
+ else {
+ Curl_safefree(data->info.contenttype);
+ data->info.contenttype = contenttype;
+ }
+ }
+ else if(checkprefix("Server:", k->p)) {
+ char *server_name = Curl_copy_header_value(k->p);
+
+ /* Turn off pipelining if the server version is blacklisted */
+ if(conn->bundle && conn->bundle->server_supports_pipelining) {
+ if(Curl_pipeline_server_blacklisted(data, server_name))
+ conn->bundle->server_supports_pipelining = FALSE;
+ }
+ free(server_name);
+ }
+ else if((conn->httpversion == 10) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(k->p,
+ "Proxy-Connection:", "keep-alive")) {
+ /*
+ * When a HTTP/1.0 reply comes when using a proxy, the
+ * 'Proxy-Connection: keep-alive' line tells us the
+ * connection will be kept alive for our pleasure.
+ * Default action for 1.0 is to close.
+ */
+ connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
+ infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
+ }
+ else if((conn->httpversion == 11) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(k->p,
+ "Proxy-Connection:", "close")) {
+ /*
+ * We get a HTTP/1.1 response from a proxy and it says it'll
+ * close down after this transfer.
+ */
+ connclose(conn, "Proxy-Connection: asked to close after done");
+ infof(data, "HTTP/1.1 proxy connection set close!\n");
+ }
+ else if((conn->httpversion == 10) &&
+ Curl_compareheader(k->p, "Connection:", "keep-alive")) {
+ /*
+ * A HTTP/1.0 reply with the 'Connection: keep-alive' line
+ * tells us the connection will be kept alive for our
+ * pleasure. Default action for 1.0 is to close.
+ *
+ * [RFC2068, section 19.7.1] */
+ connkeep(conn, "Connection keep-alive");
+ infof(data, "HTTP/1.0 connection set to keep alive!\n");
+ }
+ else if(Curl_compareheader(k->p, "Connection:", "close")) {
+ /*
+ * [RFC 2616, section 8.1.2.1]
+ * "Connection: close" is HTTP/1.1 language and means that
+ * the connection will close when this request has been
+ * served.
+ */
+ connclose(conn, "Connection: close used");
+ }
+ else if(checkprefix("Transfer-Encoding:", k->p)) {
+ /* One or more encodings. We check for chunked and/or a compression
+ algorithm. */
+ /*
+ * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
+ * means that the server will send a series of "chunks". Each
+ * chunk starts with line with info (including size of the
+ * coming block) (terminated with CRLF), then a block of data
+ * with the previously mentioned size. There can be any amount
+ * of chunks, and a chunk-data set to zero signals the
+ * end-of-chunks. */
+
+ char *start;
+
+ /* Find the first non-space letter */
+ start = k->p + 18;
+
+ for(;;) {
+ /* skip whitespaces and commas */
+ while(*start && (ISSPACE(*start) || (*start == ',')))
+ start++;
+
+ if(checkprefix("chunked", start)) {
+ k->chunk = TRUE; /* chunks coming our way */
+
+ /* init our chunky engine */
+ Curl_httpchunk_init(conn);
+
+ start += 7;
+ }
+
+ if(k->auto_decoding)
+ /* TODO: we only support the first mentioned compression for now */
+ break;
+
+ if(checkprefix("identity", start)) {
+ k->auto_decoding = IDENTITY;
+ start += 8;
+ }
+ else if(checkprefix("deflate", start)) {
+ k->auto_decoding = DEFLATE;
+ start += 7;
+ }
+ else if(checkprefix("gzip", start)) {
+ k->auto_decoding = GZIP;
+ start += 4;
+ }
+ else if(checkprefix("x-gzip", start)) {
+ k->auto_decoding = GZIP;
+ start += 6;
+ }
+ else if(checkprefix("compress", start)) {
+ k->auto_decoding = COMPRESS;
+ start += 8;
+ }
+ else if(checkprefix("x-compress", start)) {
+ k->auto_decoding = COMPRESS;
+ start += 10;
+ }
+ else
+ /* unknown! */
+ break;
+
+ }
+
+ }
+ else if(checkprefix("Content-Encoding:", k->p) &&
+ (data->set.str[STRING_ENCODING] ||
+ conn->httpversion == 20)) {
+ /*
+ * Process Content-Encoding. Look for the values: identity,
+ * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
+ * x-compress are the same as gzip and compress. (Sec 3.5 RFC
+ * 2616). zlib cannot handle compress. However, errors are
+ * handled further down when the response body is processed
+ */
+ char *start;
+
+ /* Find the first non-space letter */
+ start = k->p + 17;
+ while(*start && ISSPACE(*start))
+ start++;
+
+ /* Record the content-encoding for later use */
+ if(checkprefix("identity", start))
+ k->auto_decoding = IDENTITY;
+ else if(checkprefix("deflate", start))
+ k->auto_decoding = DEFLATE;
+ else if(checkprefix("gzip", start)
+ || checkprefix("x-gzip", start))
+ k->auto_decoding = GZIP;
+ else if(checkprefix("compress", start)
+ || checkprefix("x-compress", start))
+ k->auto_decoding = COMPRESS;
+ }
+ else if(checkprefix("Content-Range:", k->p)) {
+ /* Content-Range: bytes [num]-
+ Content-Range: bytes: [num]-
+ Content-Range: [num]-
+ Content-Range: [asterisk]/[total]
+
+ The second format was added since Sun's webserver
+ JavaWebServer/1.1.1 obviously sends the header this way!
+ The third added since some servers use that!
+ The forth means the requested range was unsatisfied.
+ */
+
+ char *ptr = k->p + 14;
+
+ /* Move forward until first digit or asterisk */
+ while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
+ ptr++;
+
+ /* if it truly stopped on a digit */
+ if(ISDIGIT(*ptr)) {
+ k->offset = curlx_strtoofft(ptr, NULL, 10);
+
+ if(data->state.resume_from == k->offset)
+ /* we asked for a resume and we got it */
+ k->content_range = TRUE;
+ }
+ else
+ data->state.resume_from = 0; /* get everything */
+ }
+#if !defined(CURL_DISABLE_COOKIES)
+ else if(data->cookies &&
+ checkprefix("Set-Cookie:", k->p)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_add(data,
+ data->cookies, TRUE, k->p+11,
+ /* If there is a custom-set Host: name, use it
+ here, or else use real peer host name. */
+ conn->allocptr.cookiehost?
+ conn->allocptr.cookiehost:conn->host.name,
+ data->state.path);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+#endif
+ else if(checkprefix("Last-Modified:", k->p) &&
+ (data->set.timecondition || data->set.get_filetime) ) {
+ time_t secs=time(NULL);
+ k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
+ &secs);
+ if(data->set.get_filetime)
+ data->info.filetime = (long)k->timeofdoc;
+ }
+ else if((checkprefix("WWW-Authenticate:", k->p) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", k->p) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(k->p);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_http_input_auth(conn, proxy, auth);
+
+ free(auth);
+
+ if(result)
+ return result;
+ }
+ else if((k->httpcode >= 300 && k->httpcode < 400) &&
+ checkprefix("Location:", k->p) &&
+ !data->req.location) {
+ /* this is the URL that the server advises us to use instead */
+ char *location = Curl_copy_header_value(k->p);
+ if(!location)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*location)
+ /* ignore empty data */
+ free(location);
+ else {
+ data->req.location = location;
+
+ if(data->set.http_follow_location) {
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->req.location); /* clone */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* some cases of POST and PUT etc needs to rewind the data
+ stream at this point */
+ result = http_perhapsrewind(conn);
+ if(result)
+ return result;
+ }
+ }
+ }
+ else if(conn->handler->protocol & CURLPROTO_RTSP) {
+ result = Curl_rtsp_parseheader(conn, k->p);
+ if(result)
+ return result;
+ }
+
+ /*
+ * End of header-checks. Write them to the client.
+ */
+
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ k->p, (size_t)k->hbuflen, conn);
+
+ result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
+ if(result)
+ return result;
+
+ data->info.header_size += (long)k->hbuflen;
+ data->req.headerbytecount += (long)k->hbuflen;
+
+ /* reset hbufp pointer && hbuflen */
+ k->hbufp = data->state.headerbuff;
+ k->hbuflen = 0;
+ }
+ while(!*stop_reading && *k->str); /* header line within buffer */
+
+ /* We might have reached the end of the header part here, but
+ there might be a non-header part left in the end of the read
+ buffer. */
+
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_HTTP */
diff --git a/libcurl/src/lib/http.h b/libcurl/src/lib/http.h
new file mode 100644
index 0000000..08e1198
--- /dev/null
+++ b/libcurl/src/lib/http.h
@@ -0,0 +1,224 @@
+#ifndef HEADER_CURL_HTTP_H
+#define HEADER_CURL_HTTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_HTTP
+
+#ifdef USE_NGHTTP2
+#include <nghttp2/nghttp2.h>
+#endif
+
+extern const struct Curl_handler Curl_handler_http;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_https;
+#endif
+
+/* Header specific functions */
+CURL_STATIC bool Curl_compareheader(const char *headerline, /* line to check */
+ const char *header, /* header keyword _with_ colon */
+ const char *content); /* content string to find */
+
+CURL_STATIC char *Curl_checkheaders(const struct connectdata *conn,
+ const char *thisheader);
+CURL_STATIC char *Curl_copy_header_value(const char *header);
+
+CURL_STATIC char *Curl_checkProxyheaders(const struct connectdata *conn,
+ const char *thisheader);
+/* ------------------------------------------------------------------------- */
+/*
+ * The add_buffer series of functions are used to build one large memory chunk
+ * from repeated function invokes. Used so that the entire HTTP request can
+ * be sent in one go.
+ */
+struct Curl_send_buffer {
+ char *buffer;
+ size_t size_max;
+ size_t size_used;
+};
+typedef struct Curl_send_buffer Curl_send_buffer;
+
+CURL_STATIC Curl_send_buffer *Curl_add_buffer_init(void);
+CURL_STATIC CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...);
+CURL_STATIC CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size);
+CURL_STATIC CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+ struct connectdata *conn,
+ long *bytes_written,
+ size_t included_body_bytes,
+ int socketindex);
+
+CURL_STATIC CURLcode Curl_add_timecondition(struct SessionHandle *data,
+ Curl_send_buffer *buf);
+CURL_STATIC CURLcode Curl_add_custom_headers(struct connectdata *conn,
+ bool is_connect,
+ Curl_send_buffer *req_buffer);
+
+/* protocol-specific functions set up to be called by the main engine */
+CURL_STATIC CURLcode Curl_http(struct connectdata *conn, bool *done);
+CURL_STATIC CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
+CURL_STATIC CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
+CURL_STATIC CURLcode Curl_http_setup_conn(struct connectdata *conn);
+
+/* The following functions are defined in http_chunks.c */
+CURL_STATIC void Curl_httpchunk_init(struct connectdata *conn);
+CURL_STATIC CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
+ ssize_t length, ssize_t *wrote);
+
+/* These functions are in http.c */
+CURL_STATIC void Curl_http_auth_stage(struct SessionHandle *data, int stage);
+CURL_STATIC CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+ const char *auth);
+CURL_STATIC CURLcode Curl_http_auth_act(struct connectdata *conn);
+CURL_STATIC CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
+
+/* If only the PICKNONE bit is set, there has been a round-trip and we
+ selected to use no auth at all. Ie, we actively select no auth, as opposed
+ to not having one selected. The other CURLAUTH_* defines are present in the
+ public curl/curl.h header. */
+#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */
+
+/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST
+ data get included in the initial data chunk sent to the server. If the
+ data is larger than this, it will automatically get split up in multiple
+ system calls.
+
+ This value used to be fairly big (100K), but we must take into account that
+ if the server rejects the POST due for authentication reasons, this data
+ will always be uncondtionally sent and thus it may not be larger than can
+ always be afforded to send twice.
+
+ It must not be greater than 64K to work on VMS.
+*/
+#ifndef MAX_INITIAL_POST_SIZE
+#define MAX_INITIAL_POST_SIZE (64*1024)
+#endif
+
+#ifndef TINY_INITIAL_POST_SIZE
+#define TINY_INITIAL_POST_SIZE 1024
+#endif
+
+#endif /* CURL_DISABLE_HTTP */
+
+/****************************************************************************
+ * HTTP unique setup
+ ***************************************************************************/
+struct HTTP {
+ struct FormData *sendit;
+ curl_off_t postsize; /* off_t to handle large file sizes */
+ const char *postdata;
+
+ const char *p_pragma; /* Pragma: string */
+ const char *p_accept; /* Accept: string */
+ curl_off_t readbytecount;
+ curl_off_t writebytecount;
+
+ /* For FORM posting */
+ struct Form form;
+
+ struct back {
+ curl_read_callback fread_func; /* backup storage for fread pointer */
+ void *fread_in; /* backup storage for fread_in pointer */
+ const char *postdata;
+ curl_off_t postsize;
+ } backup;
+
+ enum {
+ HTTPSEND_NADA, /* init */
+ HTTPSEND_REQUEST, /* sending a request */
+ HTTPSEND_BODY, /* sending body */
+ HTTPSEND_LAST /* never use this */
+ } sending;
+
+ void *send_buffer; /* used if the request couldn't be sent in one chunk,
+ points to an allocated send_buffer struct */
+};
+
+typedef int (*sending)(void); /* Curl_send */
+typedef int (*recving)(void); /* Curl_recv */
+
+struct http_conn {
+#ifdef USE_NGHTTP2
+#define H2_BINSETTINGS_LEN 80
+ nghttp2_session *h2;
+ uint8_t binsettings[H2_BINSETTINGS_LEN];
+ size_t binlen; /* length of the binsettings data */
+ char *mem; /* points to a buffer in memory to store */
+ size_t len; /* size of the buffer 'mem' points to */
+ bool bodystarted;
+ sending send_underlying; /* underlying send Curl_send callback */
+ recving recv_underlying; /* underlying recv Curl_recv callback */
+ bool closed; /* TRUE on HTTP2 stream close */
+ uint32_t error_code; /* HTTP/2 error code */
+ Curl_send_buffer *header_recvbuf; /* store response headers. We
+ store non-final and final
+ response headers into it. */
+ size_t nread_header_recvbuf; /* number of bytes in header_recvbuf
+ fed into upper layer */
+ int32_t stream_id; /* stream we are interested in */
+ const uint8_t *data; /* pointer to data chunk, received in
+ on_data_chunk */
+ size_t datalen; /* the number of bytes left in data */
+ char *inbuf; /* buffer to receive data from underlying socket */
+ /* We need separate buffer for transmission and reception because we
+ may call nghttp2_session_send() after the
+ nghttp2_session_mem_recv() but mem buffer is still not full. In
+ this case, we wrongly sends the content of mem buffer if we share
+ them for both cases. */
+ const uint8_t *upload_mem; /* points to a buffer to read from */
+ size_t upload_len; /* size of the buffer 'upload_mem' points to */
+ size_t upload_left; /* number of bytes left to upload */
+ int status_code; /* HTTP status code */
+#else
+ int unused; /* prevent a compiler warning */
+#endif
+};
+
+CURL_STATIC CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *stop_reading);
+
+/**
+ * Curl_http_output_auth() setups the authentication headers for the
+ * host/proxy and the correct authentication
+ * method. conn->data->state.authdone is set to TRUE when authentication is
+ * done.
+ *
+ * @param conn all information about the current connection
+ * @param request pointer to the request keyword
+ * @param path pointer to the requested path
+ * @param proxytunnel boolean if this is the request setting up a "proxy
+ * tunnel"
+ *
+ * @returns CURLcode
+ */
+CURL_STATIC CURLcode
+Curl_http_output_auth(struct connectdata *conn,
+ const char *request,
+ const char *path,
+ bool proxytunnel); /* TRUE if this is the request setting
+ up the proxy tunnel */
+
+#endif /* HEADER_CURL_HTTP_H */
+
diff --git a/libcurl/src/lib/http2.c b/libcurl/src/lib/http2.c
new file mode 100644
index 0000000..33fc34d
--- /dev/null
+++ b/libcurl/src/lib/http2.c
@@ -0,0 +1,1077 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NGHTTP2
+#include "curl_printf.h"
+#include <nghttp2/nghttp2.h>
+#include "urldata.h"
+#include "http2.h"
+#include "http.h"
+#include "sendf.h"
+#include "curl_base64.h"
+#include "rawstr.h"
+#include "multiif.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#if (NGHTTP2_VERSION_NUM < 0x000600)
+#error too old nghttp2 version, upgrade!
+#endif
+
+static int http2_perform_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to
+ numsocks
+ number of
+ sockets */
+ int numsocks)
+{
+ const struct http_conn *httpc = &conn->proto.httpc;
+ int bitmap = GETSOCK_BLANK;
+ (void)numsocks;
+
+ /* TODO We should check underlying socket state if it is SSL socket
+ because of renegotiation. */
+ sock[0] = conn->sock[FIRSTSOCKET];
+
+ if(nghttp2_session_want_read(httpc->h2))
+ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+
+ if(nghttp2_session_want_write(httpc->h2))
+ bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
+
+ return bitmap;
+}
+
+static int http2_getsock(struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks
+ number of sockets */
+ int numsocks)
+{
+ return http2_perform_getsock(conn, sock, numsocks);
+}
+
+static CURLcode http2_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ struct http_conn *httpc = &conn->proto.httpc;
+ (void)dead_connection;
+
+ DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
+
+ nghttp2_session_del(httpc->h2);
+
+ Curl_safefree(httpc->header_recvbuf->buffer);
+ Curl_safefree(httpc->header_recvbuf);
+
+ Curl_safefree(httpc->inbuf);
+
+ DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
+
+ return CURLE_OK;
+}
+
+/*
+ * HTTP2 handler interface. This isn't added to the general list of protocols
+ * but will be used at run-time when the protocol is dynamically switched from
+ * HTTP to HTTP2.
+ */
+const struct Curl_handler Curl_handler_http2 = {
+ "HTTP2", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ http2_getsock, /* proto_getsock */
+ http2_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ http2_perform_getsock, /* perform_getsock */
+ http2_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+const struct Curl_handler Curl_handler_http2_ssl = {
+ "HTTP2", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ http2_getsock, /* proto_getsock */
+ http2_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ http2_perform_getsock, /* perform_getsock */
+ http2_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTP, /* defport */
+ CURLPROTO_HTTPS, /* protocol */
+ PROTOPT_SSL /* flags */
+};
+
+/*
+ * Store nghttp2 version info in this buffer, Prefix with a space. Return
+ * total length written.
+ */
+CURL_STATIC int Curl_http2_ver(char *p, size_t len)
+{
+ nghttp2_info *h2 = nghttp2_version(0);
+ return snprintf(p, len, " nghttp2/%s", h2->version_str);
+}
+
+/*
+ * The implementation of nghttp2_send_callback type. Here we write |data| with
+ * size |length| to the network and return the number of bytes actually
+ * written. See the documentation of nghttp2_send_callback for the details.
+ */
+static ssize_t send_callback(nghttp2_session *h2,
+ const uint8_t *data, size_t length, int flags,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *httpc = &conn->proto.httpc;
+ ssize_t written;
+ CURLcode result = CURLE_OK;
+
+ (void)h2;
+ (void)flags;
+
+ written = ((Curl_send*)httpc->send_underlying)(conn, FIRSTSOCKET,
+ data, length, &result);
+
+ if(result == CURLE_AGAIN) {
+ return NGHTTP2_ERR_WOULDBLOCK;
+ }
+
+ if(written == -1) {
+ failf(conn->data, "Failed sending HTTP2 data");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ if(!written)
+ return NGHTTP2_ERR_WOULDBLOCK;
+
+ return written;
+}
+
+static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ int rv;
+ size_t left, ncopy;
+
+ (void)session;
+ (void)frame;
+ DEBUGF(infof(conn->data, "on_frame_recv() was called with header %x\n",
+ frame->hd.type));
+ switch(frame->hd.type) {
+ case NGHTTP2_DATA:
+ /* If body started, then receiving DATA is illegal. */
+ if(!c->bodystarted) {
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ break;
+ case NGHTTP2_HEADERS:
+ if(frame->headers.cat == NGHTTP2_HCAT_REQUEST)
+ break;
+
+ if(c->bodystarted) {
+ /* Only valid HEADERS after body started is trailer header,
+ which is not fully supported in this code. If HEADERS is not
+ trailer, then it is a PROTOCOL_ERROR. */
+ if((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ break;
+ }
+
+ if(c->status_code == -1) {
+ /* No :status header field means PROTOCOL_ERROR. */
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ break;
+ }
+
+ /* Only final status code signals the end of header */
+ if(c->status_code / 100 != 1) {
+ c->bodystarted = TRUE;
+ }
+
+ c->status_code = -1;
+
+ Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
+
+ left = c->header_recvbuf->size_used - c->nread_header_recvbuf;
+ ncopy = c->len < left ? c->len : left;
+
+ memcpy(c->mem, c->header_recvbuf->buffer + c->nread_header_recvbuf, ncopy);
+ c->nread_header_recvbuf += ncopy;
+
+ c->mem += ncopy;
+ c->len -= ncopy;
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->push_promise.promised_stream_id,
+ NGHTTP2_CANCEL);
+ if(nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int on_invalid_frame_recv(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ uint32_t error_code, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ DEBUGF(infof(conn->data,
+ "on_invalid_frame_recv() was called, error_code = %d\n",
+ error_code));
+ return 0;
+}
+
+static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const uint8_t *data, size_t len, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ size_t nread;
+ (void)session;
+ (void)flags;
+ (void)data;
+ DEBUGF(infof(conn->data, "on_data_chunk_recv() "
+ "len = %u, stream = %x\n", len, stream_id));
+
+ if(stream_id != c->stream_id) {
+ return 0;
+ }
+
+ nread = c->len < len ? c->len : len;
+ memcpy(c->mem, data, nread);
+
+ c->mem += nread;
+ c->len -= nread;
+
+ DEBUGF(infof(conn->data, "%zu data written\n", nread));
+
+ if(nread < len) {
+ c->data = data + nread;
+ c->datalen = len - nread;
+ return NGHTTP2_ERR_PAUSE;
+ }
+ return 0;
+}
+
+static int before_frame_send(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ DEBUGF(infof(conn->data, "before_frame_send() was called\n"));
+ return 0;
+}
+static int on_frame_send(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ DEBUGF(infof(conn->data, "on_frame_send() was called\n"));
+ return 0;
+}
+static int on_frame_not_send(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ int lib_error_code, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ DEBUGF(infof(conn->data,
+ "on_frame_not_send() was called, lib_error_code = %d\n",
+ lib_error_code));
+ return 0;
+}
+static int on_stream_close(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ (void)session;
+ (void)stream_id;
+ DEBUGF(infof(conn->data, "on_stream_close() was called, error_code = %d\n",
+ error_code));
+
+ if(stream_id != c->stream_id) {
+ return 0;
+ }
+
+ c->error_code = error_code;
+ c->closed = TRUE;
+
+ return 0;
+}
+
+static int on_begin_headers(nghttp2_session *session,
+ const nghttp2_frame *frame, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ DEBUGF(infof(conn->data, "on_begin_headers() was called\n"));
+ return 0;
+}
+
+/* Decode HTTP status code. Returns -1 if no valid status code was
+ decoded. */
+static int decode_status_code(const uint8_t *value, size_t len)
+{
+ int i;
+ int res;
+
+ if(len != 3) {
+ return -1;
+ }
+
+ res = 0;
+
+ for(i = 0; i < 3; ++i) {
+ char c = value[i];
+
+ if(c < '0' || c > '9') {
+ return -1;
+ }
+
+ res *= 10;
+ res += c - '0';
+ }
+
+ return res;
+}
+
+static const char STATUS[] = ":status";
+
+/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
+static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ int rv;
+ int goodname;
+ int goodheader;
+
+ (void)session;
+ (void)frame;
+ (void)flags;
+
+ /* Ignore PUSH_PROMISE for now */
+ if(frame->hd.type != NGHTTP2_HEADERS) {
+ return 0;
+ }
+
+ if(frame->hd.stream_id != c->stream_id) {
+ return 0;
+ }
+
+ if(c->bodystarted) {
+ /* Ignore trailer or HEADERS not mapped to HTTP semantics. The
+ consequence is handled in on_frame_recv(). */
+ return 0;
+ }
+
+ goodname = nghttp2_check_header_name(name, namelen);
+ goodheader = nghttp2_check_header_value(value, valuelen);
+
+ if(!goodname || !goodheader) {
+
+ infof(conn->data, "Detected bad incoming header %s%s, reset stream!\n",
+ goodname?"":"name",
+ goodheader?"":"value");
+
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ if(namelen == sizeof(":status") - 1 &&
+ memcmp(STATUS, name, namelen) == 0) {
+
+ /* :status must appear exactly once. */
+ if(c->status_code != -1 ||
+ (c->status_code = decode_status_code(value, valuelen)) == -1) {
+
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ Curl_add_buffer(c->header_recvbuf, "HTTP/2.0 ", 9);
+ Curl_add_buffer(c->header_recvbuf, value, valuelen);
+ Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
+
+ return 0;
+ }
+ else {
+ /* Here we are sure that namelen > 0 because of
+ nghttp2_check_header_name(). Pseudo header other than :status
+ is illegal. */
+ if(c->status_code == -1 || name[0] == ':') {
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ /* convert to a HTTP1-style header */
+ Curl_add_buffer(c->header_recvbuf, name, namelen);
+ Curl_add_buffer(c->header_recvbuf, ":", 1);
+ Curl_add_buffer(c->header_recvbuf, value, valuelen);
+ Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
+
+ DEBUGF(infof(conn->data, "h2 header: %.*s: %.*s\n",
+ namelen, name, valuelen, value));
+ }
+
+ return 0; /* 0 is successful */
+}
+
+static ssize_t data_source_read_callback(nghttp2_session *session,
+ int32_t stream_id,
+ uint8_t *buf, size_t length,
+ uint32_t *data_flags,
+ nghttp2_data_source *source,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ size_t nread;
+ (void)session;
+ (void)stream_id;
+ (void)source;
+
+ nread = c->upload_len < length ? c->upload_len : length;
+ if(nread > 0) {
+ memcpy(buf, c->upload_mem, nread);
+ c->upload_mem += nread;
+ c->upload_len -= nread;
+ c->upload_left -= nread;
+ }
+
+ if(c->upload_left == 0)
+ *data_flags = 1;
+ else if(nread == 0)
+ return NGHTTP2_ERR_DEFERRED;
+
+ return nread;
+}
+
+/*
+ * The HTTP2 settings we send in the Upgrade request
+ */
+static nghttp2_settings_entry settings[] = {
+ { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
+ { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
+};
+
+#define H2_BUFSIZE 4096
+
+/*
+ * Initialize nghttp2 for a Curl connection
+ */
+CURL_STATIC CURLcode Curl_http2_init(struct connectdata *conn)
+{
+ if(!conn->proto.httpc.h2) {
+ int rc;
+ nghttp2_session_callbacks *callbacks;
+
+ conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
+ if(conn->proto.httpc.inbuf == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ rc = nghttp2_session_callbacks_new(&callbacks);
+
+ if(rc) {
+ failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
+ return CURLE_OUT_OF_MEMORY; /* most likely at least */
+ }
+
+ /* nghttp2_send_callback */
+ nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
+ /* nghttp2_on_frame_recv_callback */
+ nghttp2_session_callbacks_set_on_frame_recv_callback
+ (callbacks, on_frame_recv);
+ /* nghttp2_on_invalid_frame_recv_callback */
+ nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
+ (callbacks, on_invalid_frame_recv);
+ /* nghttp2_on_data_chunk_recv_callback */
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback
+ (callbacks, on_data_chunk_recv);
+ /* nghttp2_before_frame_send_callback */
+ nghttp2_session_callbacks_set_before_frame_send_callback
+ (callbacks, before_frame_send);
+ /* nghttp2_on_frame_send_callback */
+ nghttp2_session_callbacks_set_on_frame_send_callback
+ (callbacks, on_frame_send);
+ /* nghttp2_on_frame_not_send_callback */
+ nghttp2_session_callbacks_set_on_frame_not_send_callback
+ (callbacks, on_frame_not_send);
+ /* nghttp2_on_stream_close_callback */
+ nghttp2_session_callbacks_set_on_stream_close_callback
+ (callbacks, on_stream_close);
+ /* nghttp2_on_begin_headers_callback */
+ nghttp2_session_callbacks_set_on_begin_headers_callback
+ (callbacks, on_begin_headers);
+ /* nghttp2_on_header_callback */
+ nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
+
+ /* The nghttp2 session is not yet setup, do it */
+ rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
+ callbacks, conn);
+
+ nghttp2_session_callbacks_del(callbacks);
+
+ if(rc) {
+ failf(conn->data, "Couldn't initialize nghttp2!");
+ return CURLE_OUT_OF_MEMORY; /* most likely at least */
+ }
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Send a request using http2
+ */
+CURL_STATIC CURLcode Curl_http2_send_request(struct connectdata *conn)
+{
+ (void)conn;
+ return CURLE_OK;
+}
+
+/*
+ * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
+ */
+CURL_STATIC CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ ssize_t binlen;
+ char *base64;
+ size_t blen;
+ struct SingleRequest *k = &conn->data->req;
+ uint8_t *binsettings = conn->proto.httpc.binsettings;
+
+ /* As long as we have a fixed set of settings, we don't have to dynamically
+ * figure out the base64 strings since it'll always be the same. However,
+ * the settings will likely not be fixed every time in the future.
+ */
+
+ /* this returns number of bytes it wrote */
+ binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
+ settings,
+ sizeof(settings)/sizeof(settings[0]));
+ if(!binlen) {
+ failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
+ return CURLE_FAILED_INIT;
+ }
+ conn->proto.httpc.binlen = binlen;
+
+ result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
+ &base64, &blen);
+ if(result)
+ return result;
+
+ result = Curl_add_bufferf(req,
+ "Connection: Upgrade, HTTP2-Settings\r\n"
+ "Upgrade: %s\r\n"
+ "HTTP2-Settings: %s\r\n",
+ NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
+ free(base64);
+
+ k->upgr101 = UPGR101_REQUESTED;
+
+ return result;
+}
+
+/*
+ * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
+ * a regular CURLcode value.
+ */
+static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err)
+{
+ CURLcode result = CURLE_OK;
+ ssize_t rv;
+ ssize_t nread;
+ struct http_conn *httpc = &conn->proto.httpc;
+
+ (void)sockindex; /* we always do HTTP2 on sockindex 0 */
+
+ if(httpc->closed) {
+ /* Reset to FALSE to prevent infinite loop in readwrite_data
+ function. */
+ httpc->closed = FALSE;
+ return 0;
+ }
+
+ /* Nullify here because we call nghttp2_session_send() and they
+ might refer to the old buffer. */
+ httpc->upload_mem = NULL;
+ httpc->upload_len = 0;
+
+ if(httpc->bodystarted &&
+ httpc->nread_header_recvbuf < httpc->header_recvbuf->size_used) {
+ size_t left =
+ httpc->header_recvbuf->size_used - httpc->nread_header_recvbuf;
+ size_t ncopy = len < left ? len : left;
+ memcpy(mem, httpc->header_recvbuf->buffer + httpc->nread_header_recvbuf,
+ ncopy);
+ httpc->nread_header_recvbuf += ncopy;
+ return ncopy;
+ }
+
+ if(httpc->data) {
+ nread = len < httpc->datalen ? len : httpc->datalen;
+ memcpy(mem, httpc->data, nread);
+
+ httpc->data += nread;
+ httpc->datalen -= nread;
+
+ infof(conn->data, "%zu data bytes written\n", nread);
+ if(httpc->datalen == 0) {
+ httpc->data = NULL;
+ httpc->datalen = 0;
+ }
+ return nread;
+ }
+
+ conn->proto.httpc.mem = mem;
+ conn->proto.httpc.len = len;
+
+ infof(conn->data, "http2_recv: %d bytes buffer\n",
+ conn->proto.httpc.len);
+
+ nread = ((Curl_recv*)httpc->recv_underlying)(conn, FIRSTSOCKET,
+ httpc->inbuf, H2_BUFSIZE,
+ &result);
+ if(result == CURLE_AGAIN) {
+ *err = result;
+ return -1;
+ }
+
+ if(nread == -1) {
+ failf(conn->data, "Failed receiving HTTP2 data");
+ *err = result;
+ return 0;
+ }
+
+ if(nread == 0) {
+ failf(conn->data, "Unexpected EOF");
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ DEBUGF(infof(conn->data, "nread=%zd\n", nread));
+
+ rv = nghttp2_session_mem_recv(httpc->h2,
+ (const uint8_t *)httpc->inbuf, nread);
+
+ if(nghttp2_is_fatal((int)rv)) {
+ failf(conn->data, "nghttp2_session_mem_recv() returned %d:%s\n",
+ rv, nghttp2_strerror((int)rv));
+ *err = CURLE_RECV_ERROR;
+ return 0;
+ }
+ DEBUGF(infof(conn->data, "nghttp2_session_mem_recv() returns %zd\n", rv));
+ /* Always send pending frames in nghttp2 session, because
+ nghttp2_session_mem_recv() may queue new frame */
+ rv = nghttp2_session_send(httpc->h2);
+ if(rv != 0) {
+ *err = CURLE_SEND_ERROR;
+ return 0;
+ }
+ if(len != httpc->len) {
+ return len - conn->proto.httpc.len;
+ }
+ /* If stream is closed, return 0 to signal the http routine to close
+ the connection */
+ if(httpc->closed) {
+ /* Reset to FALSE to prevent infinite loop in readwrite_data
+ function. */
+ httpc->closed = FALSE;
+ if(httpc->error_code != NGHTTP2_NO_ERROR) {
+ failf(conn->data,
+ "HTTP/2 stream = %x was not closed cleanly: error_code = %d",
+ httpc->stream_id, httpc->error_code);
+ *err = CURLE_HTTP2;
+ return -1;
+ }
+ return 0;
+ }
+ *err = CURLE_AGAIN;
+ return -1;
+}
+
+/* Index where :authority header field will appear in request header
+ field list. */
+#define AUTHORITY_DST_IDX 3
+
+/* return number of received (decrypted) bytes */
+static ssize_t http2_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *err)
+{
+ /*
+ * BIG TODO: Currently, we send request in this function, but this
+ * function is also used to send request body. It would be nice to
+ * add dedicated function for request.
+ */
+ int rv;
+ struct http_conn *httpc = &conn->proto.httpc;
+ nghttp2_nv *nva;
+ size_t nheader;
+ size_t i;
+ size_t authority_idx;
+ char *hdbuf = (char*)mem;
+ char *end;
+ nghttp2_data_provider data_prd;
+ int32_t stream_id;
+
+ (void)sockindex;
+
+ DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
+
+ if(httpc->stream_id != -1) {
+ /* If stream_id != -1, we have dispatched request HEADERS, and now
+ are going to send or sending request body in DATA frame */
+ httpc->upload_mem = mem;
+ httpc->upload_len = len;
+ nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
+ rv = nghttp2_session_send(httpc->h2);
+ if(nghttp2_is_fatal(rv)) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ return len - httpc->upload_len;
+ }
+
+ /* Calculate number of headers contained in [mem, mem + len) */
+ /* Here, we assume the curl http code generate *correct* HTTP header
+ field block */
+ nheader = 0;
+ for(i = 0; i < len; ++i) {
+ if(hdbuf[i] == 0x0a) {
+ ++nheader;
+ }
+ }
+ /* We counted additional 2 \n in the first and last line. We need 3
+ new headers: :method, :path and :scheme. Therefore we need one
+ more space. */
+ nheader += 1;
+ nva = malloc(sizeof(nghttp2_nv) * nheader);
+ if(nva == NULL) {
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ /* Extract :method, :path from request line */
+ end = strchr(hdbuf, ' ');
+ nva[0].name = (unsigned char *)":method";
+ nva[0].namelen = (uint16_t)strlen((char *)nva[0].name);
+ nva[0].value = (unsigned char *)hdbuf;
+ nva[0].valuelen = (uint16_t)(end - hdbuf);
+ nva[0].flags = NGHTTP2_NV_FLAG_NONE;
+
+ hdbuf = end + 1;
+
+ end = strchr(hdbuf, ' ');
+ nva[1].name = (unsigned char *)":path";
+ nva[1].namelen = (uint16_t)strlen((char *)nva[1].name);
+ nva[1].value = (unsigned char *)hdbuf;
+ nva[1].valuelen = (uint16_t)(end - hdbuf);
+ nva[1].flags = NGHTTP2_NV_FLAG_NONE;
+
+ nva[2].name = (unsigned char *)":scheme";
+ nva[2].namelen = (uint16_t)strlen((char *)nva[2].name);
+ if(conn->handler->flags & PROTOPT_SSL)
+ nva[2].value = (unsigned char *)"https";
+ else
+ nva[2].value = (unsigned char *)"http";
+ nva[2].valuelen = (uint16_t)strlen((char *)nva[2].value);
+ nva[2].flags = NGHTTP2_NV_FLAG_NONE;
+
+ hdbuf = strchr(hdbuf, 0x0a);
+ ++hdbuf;
+
+ authority_idx = 0;
+
+ for(i = 3; i < nheader; ++i) {
+ end = strchr(hdbuf, ':');
+ assert(end);
+ if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
+ authority_idx = i;
+ nva[i].name = (unsigned char *)":authority";
+ nva[i].namelen = (uint16_t)strlen((char *)nva[i].name);
+ }
+ else {
+ nva[i].name = (unsigned char *)hdbuf;
+ nva[i].namelen = (uint16_t)(end - hdbuf);
+ }
+ hdbuf = end + 1;
+ for(; *hdbuf == ' '; ++hdbuf);
+ end = strchr(hdbuf, 0x0d);
+ assert(end);
+ nva[i].value = (unsigned char *)hdbuf;
+ nva[i].valuelen = (uint16_t)(end - hdbuf);
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+
+ hdbuf = end + 2;
+ /* Inspect Content-Length header field and retrieve the request
+ entity length so that we can set END_STREAM to the last DATA
+ frame. */
+ if(nva[i].namelen == 14 &&
+ Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) {
+ size_t j;
+ for(j = 0; j < nva[i].valuelen; ++j) {
+ httpc->upload_left *= 10;
+ httpc->upload_left += nva[i].value[j] - '0';
+ }
+ DEBUGF(infof(conn->data,
+ "request content-length=%zu\n", httpc->upload_left));
+ }
+ }
+
+ /* :authority must come before non-pseudo header fields */
+ if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
+ nghttp2_nv authority = nva[authority_idx];
+ for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
+ nva[i] = nva[i - 1];
+ }
+ nva[i] = authority;
+ }
+
+ switch(conn->data->set.httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_PUT:
+ data_prd.read_callback = data_source_read_callback;
+ data_prd.source.ptr = NULL;
+ stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader,
+ &data_prd, NULL);
+ break;
+ default:
+ stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader,
+ NULL, NULL);
+ }
+
+ free(nva);
+
+ if(stream_id < 0) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ httpc->stream_id = stream_id;
+
+ rv = nghttp2_session_send(httpc->h2);
+
+ if(rv != 0) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ if(httpc->stream_id != -1) {
+ /* If whole HEADERS frame was sent off to the underlying socket,
+ the nghttp2 library calls data_source_read_callback. But only
+ it found that no data available, so it deferred the DATA
+ transmission. Which means that nghttp2_session_want_write()
+ returns 0 on http2_perform_getsock(), which results that no
+ writable socket check is performed. To workaround this, we
+ issue nghttp2_session_resume_data() here to bring back DATA
+ transmission from deferred state. */
+ nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
+ }
+
+ return len;
+}
+
+CURL_STATIC CURLcode Curl_http2_setup(struct connectdata *conn)
+{
+ CURLcode result;
+ struct http_conn *httpc = &conn->proto.httpc;
+ if(conn->handler->flags & PROTOPT_SSL)
+ conn->handler = &Curl_handler_http2_ssl;
+ else
+ conn->handler = &Curl_handler_http2;
+
+ result = Curl_http2_init(conn);
+ if(result)
+ return result;
+
+ infof(conn->data, "Using HTTP2\n");
+ httpc->bodystarted = FALSE;
+ httpc->error_code = NGHTTP2_NO_ERROR;
+ httpc->closed = FALSE;
+ httpc->header_recvbuf = Curl_add_buffer_init();
+ httpc->nread_header_recvbuf = 0;
+ httpc->data = NULL;
+ httpc->datalen = 0;
+ httpc->upload_left = 0;
+ httpc->upload_mem = NULL;
+ httpc->upload_len = 0;
+ httpc->stream_id = -1;
+ httpc->status_code = -1;
+
+ conn->httpversion = 20;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_http2_switched(struct connectdata *conn,
+ const char *mem, size_t nread)
+{
+ CURLcode result;
+ struct http_conn *httpc = &conn->proto.httpc;
+ int rv;
+ struct SessionHandle *data = conn->data;
+
+ result = Curl_http2_setup(conn);
+ if(result)
+ return result;
+
+ httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
+ httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
+ conn->recv[FIRSTSOCKET] = http2_recv;
+ conn->send[FIRSTSOCKET] = http2_send;
+
+ rv = (int) ((Curl_send*)httpc->send_underlying)
+ (conn, FIRSTSOCKET,
+ NGHTTP2_CLIENT_CONNECTION_PREFACE,
+ NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN,
+ &result);
+ if(result)
+ /* TODO: This may get CURLE_AGAIN */
+ return result;
+
+ if(rv != 24) {
+ failf(data, "Only sent partial HTTP2 packet");
+ return CURLE_SEND_ERROR;
+ }
+
+ if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
+ /* stream 1 is opened implicitly on upgrade */
+ httpc->stream_id = 1;
+ /* queue SETTINGS frame (again) */
+ rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
+ httpc->binlen, NULL);
+ if(rv != 0) {
+ failf(data, "nghttp2_session_upgrade() failed: %s(%d)",
+ nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
+ }
+ else {
+ /* stream ID is unknown at this point */
+ httpc->stream_id = -1;
+ rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
+ if(rv != 0) {
+ failf(data, "nghttp2_submit_settings() failed: %s(%d)",
+ nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
+ }
+
+ rv = (int)nghttp2_session_mem_recv(httpc->h2, (const uint8_t*)mem, nread);
+
+ if(rv != (int)nread) {
+ failf(data, "nghttp2_session_mem_recv() failed: %s(%d)",
+ nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
+
+ /* Try to send some frames since we may read SETTINGS already. */
+ rv = nghttp2_session_send(httpc->h2);
+
+ if(rv != 0) {
+ failf(data, "nghttp2_session_send() failed: %s(%d)",
+ nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
+
+ return CURLE_OK;
+}
+
+#endif
diff --git a/libcurl/src/lib/http2.h b/libcurl/src/lib/http2.h
new file mode 100644
index 0000000..fc801d3
--- /dev/null
+++ b/libcurl/src/lib/http2.h
@@ -0,0 +1,51 @@
+#ifndef HEADER_CURL_HTTP2_H
+#define HEADER_CURL_HTTP2_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NGHTTP2
+#include "http.h"
+/*
+ * Store nghttp2 version info in this buffer, Prefix with a space. Return
+ * total length written.
+ */
+CURL_STATIC int Curl_http2_ver(char *p, size_t len);
+
+CURL_STATIC CURLcode Curl_http2_init(struct connectdata *conn);
+CURL_STATIC CURLcode Curl_http2_send_request(struct connectdata *conn);
+CURL_STATIC CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+ struct connectdata *conn);
+CURL_STATIC CURLcode Curl_http2_setup(struct connectdata *conn);
+CURL_STATIC CURLcode Curl_http2_switched(struct connectdata *conn,
+ const char *data, size_t nread);
+#else /* USE_NGHTTP2 */
+#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
+#endif
+
+#endif /* HEADER_CURL_HTTP2_H */
+
diff --git a/libcurl/src/lib/http_chunks.c b/libcurl/src/lib/http_chunks.c
new file mode 100644
index 0000000..e37dfd8
--- /dev/null
+++ b/libcurl/src/lib/http_chunks.c
@@ -0,0 +1,382 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_HTTP
+
+#include "urldata.h" /* it includes http_chunks.h */
+#include "sendf.h" /* for the client write stuff */
+
+#include "content_encoding.h"
+#include "http.h"
+#include "non-ascii.h" /* for Curl_convert_to_network prototype */
+#include "strtoofft.h"
+#include "warnless.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * Chunk format (simplified):
+ *
+ * <HEX SIZE>[ chunk extension ] CRLF
+ * <DATA> CRLF
+ *
+ * Highlights from RFC2616 section 3.6 say:
+
+ The chunked encoding modifies the body of a message in order to
+ transfer it as a series of chunks, each with its own size indicator,
+ followed by an OPTIONAL trailer containing entity-header fields. This
+ allows dynamically produced content to be transferred along with the
+ information necessary for the recipient to verify that it has
+ received the full message.
+
+ Chunked-Body = *chunk
+ last-chunk
+ trailer
+ CRLF
+
+ chunk = chunk-size [ chunk-extension ] CRLF
+ chunk-data CRLF
+ chunk-size = 1*HEX
+ last-chunk = 1*("0") [ chunk-extension ] CRLF
+
+ chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+ chunk-ext-name = token
+ chunk-ext-val = token | quoted-string
+ chunk-data = chunk-size(OCTET)
+ trailer = *(entity-header CRLF)
+
+ The chunk-size field is a string of hex digits indicating the size of
+ the chunk. The chunked encoding is ended by any chunk whose size is
+ zero, followed by the trailer, which is terminated by an empty line.
+
+ */
+
+/* Check for an ASCII hex digit.
+ We avoid the use of isxdigit to accommodate non-ASCII hosts. */
+static bool Curl_isxdigit(char digit)
+{
+ return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
+ || (digit >= 0x41 && digit <= 0x46) /* A-F */
+ || (digit >= 0x61 && digit <= 0x66) /* a-f */ ) ? TRUE : FALSE;
+}
+
+CURL_STATIC void Curl_httpchunk_init(struct connectdata *conn)
+{
+ struct Curl_chunker *chunk = &conn->chunk;
+ chunk->hexindex=0; /* start at 0 */
+ chunk->dataleft=0; /* no data left yet! */
+ chunk->state = CHUNK_HEX; /* we get hex first! */
+}
+
+/*
+ * chunk_read() returns a OK for normal operations, or a positive return code
+ * for errors. STOP means this sequence of chunks is complete. The 'wrote'
+ * argument is set to tell the caller how many bytes we actually passed to the
+ * client (for byte-counting and whatever).
+ *
+ * The states and the state-machine is further explained in the header file.
+ *
+ * This function always uses ASCII hex values to accommodate non-ASCII hosts.
+ * For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
+ */
+CURL_STATIC CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
+ char *datap,
+ ssize_t datalen,
+ ssize_t *wrotep)
+{
+ CURLcode result=CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct Curl_chunker *ch = &conn->chunk;
+ struct SingleRequest *k = &data->req;
+ size_t piece;
+ curl_off_t length = (curl_off_t)datalen;
+ size_t *wrote = (size_t *)wrotep;
+
+ *wrote = 0; /* nothing's written yet */
+
+ /* the original data is written to the client, but we go on with the
+ chunk read process, to properly calculate the content length*/
+ if(data->set.http_te_skip && !k->ignorebody) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen);
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+ }
+
+ while(length) {
+ switch(ch->state) {
+ case CHUNK_HEX:
+ if(Curl_isxdigit(*datap)) {
+ if(ch->hexindex < MAXNUM_SIZE) {
+ ch->hexbuffer[ch->hexindex] = *datap;
+ datap++;
+ length--;
+ ch->hexindex++;
+ }
+ else {
+ return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */
+ }
+ }
+ else {
+ char *endptr;
+ if(0 == ch->hexindex)
+ /* This is illegal data, we received junk where we expected
+ a hexadecimal digit. */
+ return CHUNKE_ILLEGAL_HEX;
+
+ /* length and datap are unmodified */
+ ch->hexbuffer[ch->hexindex]=0;
+
+ /* convert to host encoding before calling strtoul */
+ result = Curl_convert_from_network(conn->data, ch->hexbuffer,
+ ch->hexindex);
+ if(result) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* Treat it as a bad hex character */
+ return CHUNKE_ILLEGAL_HEX;
+ }
+
+ ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16);
+ if((ch->datasize == CURL_OFF_T_MAX) && (errno == ERANGE))
+ /* overflow is an error */
+ return CHUNKE_ILLEGAL_HEX;
+ ch->state = CHUNK_LF; /* now wait for the CRLF */
+ }
+ break;
+
+ case CHUNK_LF:
+ /* waiting for the LF after a chunk size */
+ if(*datap == 0x0a) {
+ /* we're now expecting data to come, unless size was zero! */
+ if(0 == ch->datasize) {
+ ch->state = CHUNK_TRAILER; /* now check for trailers */
+ conn->trlPos=0;
+ }
+ else
+ ch->state = CHUNK_DATA;
+ }
+
+ datap++;
+ length--;
+ break;
+
+ case CHUNK_DATA:
+ /* We expect 'datasize' of data. We have 'length' right now, it can be
+ more or less than 'datasize'. Get the smallest piece.
+ */
+ piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
+
+ /* Write the data portion available */
+#ifdef HAVE_LIBZ
+ switch (conn->data->set.http_ce_skip?
+ IDENTITY : data->req.auto_decoding) {
+ case IDENTITY:
+#endif
+ if(!k->ignorebody) {
+ if(!data->set.http_te_skip)
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
+ piece);
+ else
+ result = CURLE_OK;
+ }
+#ifdef HAVE_LIBZ
+ break;
+
+ case DEFLATE:
+ /* update data->req.keep.str to point to the chunk data. */
+ data->req.str = datap;
+ result = Curl_unencode_deflate_write(conn, &data->req,
+ (ssize_t)piece);
+ break;
+
+ case GZIP:
+ /* update data->req.keep.str to point to the chunk data. */
+ data->req.str = datap;
+ result = Curl_unencode_gzip_write(conn, &data->req,
+ (ssize_t)piece);
+ break;
+
+ case COMPRESS:
+ default:
+ failf (conn->data,
+ "Unrecognized content encoding type. "
+ "libcurl understands `identity', `deflate' and `gzip' "
+ "content encodings.");
+ return CHUNKE_BAD_ENCODING;
+ }
+#endif
+
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+
+ *wrote += piece;
+
+ ch->datasize -= piece; /* decrease amount left to expect */
+ datap += piece; /* move read pointer forward */
+ length -= piece; /* decrease space left in this round */
+
+ if(0 == ch->datasize)
+ /* end of data this round, we now expect a trailing CRLF */
+ ch->state = CHUNK_POSTLF;
+ break;
+
+ case CHUNK_POSTLF:
+ if(*datap == 0x0a) {
+ /* The last one before we go back to hex state and start all over. */
+ Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */
+ }
+ else if(*datap != 0x0d)
+ return CHUNKE_BAD_CHUNK;
+ datap++;
+ length--;
+ break;
+
+ case CHUNK_TRAILER:
+ if((*datap == 0x0d) || (*datap == 0x0a)) {
+ /* this is the end of a trailer, but if the trailer was zero bytes
+ there was no trailer and we move on */
+
+ if(conn->trlPos) {
+ /* we allocate trailer with 3 bytes extra room to fit this */
+ conn->trailer[conn->trlPos++]=0x0d;
+ conn->trailer[conn->trlPos++]=0x0a;
+ conn->trailer[conn->trlPos]=0;
+
+ /* Convert to host encoding before calling Curl_client_write */
+ result = Curl_convert_from_network(conn->data, conn->trailer,
+ conn->trlPos);
+ if(result)
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* Treat it as a bad chunk */
+ return CHUNKE_BAD_CHUNK;
+
+ if(!data->set.http_te_skip) {
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ conn->trailer, conn->trlPos);
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+ }
+ conn->trlPos=0;
+ ch->state = CHUNK_TRAILER_CR;
+ if(*datap == 0x0a)
+ /* already on the LF */
+ break;
+ }
+ else {
+ /* no trailer, we're on the final CRLF pair */
+ ch->state = CHUNK_TRAILER_POSTCR;
+ break; /* don't advance the pointer */
+ }
+ }
+ else {
+ /* conn->trailer is assumed to be freed in url.c on a
+ connection basis */
+ if(conn->trlPos >= conn->trlMax) {
+ /* we always allocate three extra bytes, just because when the full
+ header has been received we append CRLF\0 */
+ char *ptr;
+ if(conn->trlMax) {
+ conn->trlMax *= 2;
+ ptr = realloc(conn->trailer, conn->trlMax + 3);
+ }
+ else {
+ conn->trlMax=128;
+ ptr = malloc(conn->trlMax + 3);
+ }
+ if(!ptr)
+ return CHUNKE_OUT_OF_MEMORY;
+ conn->trailer = ptr;
+ }
+ conn->trailer[conn->trlPos++]=*datap;
+ }
+ datap++;
+ length--;
+ break;
+
+ case CHUNK_TRAILER_CR:
+ if(*datap == 0x0a) {
+ ch->state = CHUNK_TRAILER_POSTCR;
+ datap++;
+ length--;
+ }
+ else
+ return CHUNKE_BAD_CHUNK;
+ break;
+
+ case CHUNK_TRAILER_POSTCR:
+ /* We enter this state when a CR should arrive so we expect to
+ have to first pass a CR before we wait for LF */
+ if((*datap != 0x0d) && (*datap != 0x0a)) {
+ /* not a CR then it must be another header in the trailer */
+ ch->state = CHUNK_TRAILER;
+ break;
+ }
+ if(*datap == 0x0d) {
+ /* skip if CR */
+ datap++;
+ length--;
+ }
+ /* now wait for the final LF */
+ ch->state = CHUNK_STOP;
+ break;
+
+ case CHUNK_STOP:
+ if(*datap == 0x0a) {
+ length--;
+
+ /* Record the length of any data left in the end of the buffer
+ even if there's no more chunks to read */
+ ch->dataleft = curlx_sotouz(length);
+
+ return CHUNKE_STOP; /* return stop */
+ }
+ else
+ return CHUNKE_BAD_CHUNK;
+ }
+ }
+ return CHUNKE_OK;
+}
+
+CURL_STATIC const char *Curl_chunked_strerror(CHUNKcode code)
+{
+ switch (code) {
+ default:
+ return "OK";
+ case CHUNKE_TOO_LONG_HEX:
+ return "Too long hexadecimal number";
+ case CHUNKE_ILLEGAL_HEX:
+ return "Illegal or missing hexadecimal sequence";
+ case CHUNKE_BAD_CHUNK:
+ return "Malformed encoding found";
+ case CHUNKE_WRITE_ERROR:
+ return "Write error";
+ case CHUNKE_BAD_ENCODING:
+ return "Bad content-encoding found";
+ case CHUNKE_OUT_OF_MEMORY:
+ return "Out of memory";
+ }
+}
+
+#endif /* CURL_DISABLE_HTTP */
diff --git a/libcurl/src/lib/http_chunks.h b/libcurl/src/lib/http_chunks.h
new file mode 100644
index 0000000..2389eaa
--- /dev/null
+++ b/libcurl/src/lib/http_chunks.h
@@ -0,0 +1,91 @@
+#ifndef HEADER_CURL_HTTP_CHUNKS_H
+#define HEADER_CURL_HTTP_CHUNKS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ * The longest possible hexadecimal number we support in a chunked transfer.
+ * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul()
+ * to convert it, we "only" support 2^32 bytes chunk data.
+ */
+#define MAXNUM_SIZE 16
+
+typedef enum {
+ /* await and buffer all hexadecimal digits until we get one that isn't a
+ hexadecimal digit. When done, we go CHUNK_LF */
+ CHUNK_HEX,
+
+ /* wait for LF, ignore all else */
+ CHUNK_LF,
+
+ /* We eat the amount of data specified. When done, we move on to the
+ POST_CR state. */
+ CHUNK_DATA,
+
+ /* POSTLF should get a CR and then a LF and nothing else, then move back to
+ HEX as the CRLF combination marks the end of a chunk. A missing CR is no
+ big deal. */
+ CHUNK_POSTLF,
+
+ /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft'
+ field in the struct that will tell how many bytes that were not passed to
+ the client in the end of the last buffer! */
+ CHUNK_STOP,
+
+ /* At this point optional trailer headers can be found, unless the next line
+ is CRLF */
+ CHUNK_TRAILER,
+
+ /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR.
+ Next char must be a LF */
+ CHUNK_TRAILER_CR,
+
+ /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be
+ signalled If this is an empty trailer CHUNKE_STOP will be signalled.
+ Otherwise the trailer will be broadcasted via Curl_client_write() and the
+ next state will be CHUNK_TRAILER */
+ CHUNK_TRAILER_POSTCR
+} ChunkyState;
+
+typedef enum {
+ CHUNKE_STOP = -1,
+ CHUNKE_OK = 0,
+ CHUNKE_TOO_LONG_HEX = 1,
+ CHUNKE_ILLEGAL_HEX,
+ CHUNKE_BAD_CHUNK,
+ CHUNKE_WRITE_ERROR,
+ CHUNKE_BAD_ENCODING,
+ CHUNKE_OUT_OF_MEMORY,
+ CHUNKE_LAST
+} CHUNKcode;
+
+CURL_STATIC const char *Curl_chunked_strerror(CHUNKcode code);
+
+struct Curl_chunker {
+ char hexbuffer[ MAXNUM_SIZE + 1];
+ int hexindex;
+ ChunkyState state;
+ curl_off_t datasize;
+ size_t dataleft; /* untouched data amount at the end of the last buffer */
+};
+
+#endif /* HEADER_CURL_HTTP_CHUNKS_H */
+
diff --git a/libcurl/src/lib/http_digest.c b/libcurl/src/lib/http_digest.c
new file mode 100644
index 0000000..2b116ef
--- /dev/null
+++ b/libcurl/src/lib/http_digest.c
@@ -0,0 +1,179 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
+#include "urldata.h"
+#include "rawstr.h"
+#include "curl_sasl.h"
+#include "http_digest.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* Test example headers:
+
+WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
+Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"
+
+*/
+
+CURL_STATIC CURLcode Curl_input_digest(struct connectdata *conn,
+ bool proxy,
+ const char *header) /* rest of the *-authenticate:
+ header */
+{
+ struct SessionHandle *data = conn->data;
+
+ /* Point to the correct struct with this */
+ struct digestdata *digest;
+
+ if(proxy) {
+ digest = &data->state.proxydigest;
+ }
+ else {
+ digest = &data->state.digest;
+ }
+
+ if(!checkprefix("Digest", header))
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ header += strlen("Digest");
+ while(*header && ISSPACE(*header))
+ header++;
+
+ return Curl_sasl_decode_digest_http_message(header, digest);
+}
+
+CURL_STATIC CURLcode Curl_output_digest(struct connectdata *conn,
+ bool proxy,
+ const unsigned char *request,
+ const unsigned char *uripath)
+{
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ unsigned char *path;
+ char *tmp;
+ char *response;
+ size_t len;
+ bool have_chlg;
+
+ /* Point to the address of the pointer that holds the string to send to the
+ server, which is for a plain host or for a HTTP proxy */
+ char **allocuserpwd;
+
+ /* Point to the name and password for this */
+ const char *userp;
+ const char *passwdp;
+
+ /* Point to the correct struct with this */
+ struct digestdata *digest;
+ struct auth *authp;
+
+ if(proxy) {
+ digest = &data->state.proxydigest;
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ passwdp = conn->proxypasswd;
+ authp = &data->state.authproxy;
+ }
+ else {
+ digest = &data->state.digest;
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ passwdp = conn->passwd;
+ authp = &data->state.authhost;
+ }
+
+ Curl_safefree(*allocuserpwd);
+
+ /* not set means empty */
+ if(!userp)
+ userp = "";
+
+ if(!passwdp)
+ passwdp = "";
+
+#if defined(USE_WINDOWS_SSPI)
+ have_chlg = digest->input_token ? TRUE : FALSE;
+#else
+ have_chlg = digest->nonce ? TRUE : FALSE;
+#endif
+
+ if(!have_chlg) {
+ authp->done = FALSE;
+ return CURLE_OK;
+ }
+
+ /* So IE browsers < v7 cut off the URI part at the query part when they
+ evaluate the MD5 and some (IIS?) servers work with them so we may need to
+ do the Digest IE-style. Note that the different ways cause different MD5
+ sums to get sent.
+
+ Apache servers can be set to do the Digest IE-style automatically using
+ the BrowserMatch feature:
+ http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie
+
+ Further details on Digest implementation differences:
+ http://www.fngtps.com/2006/09/http-authentication
+ */
+
+ if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
+ size_t urilen = tmp - (char *)uripath;
+
+ path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+ }
+ else
+ path = (unsigned char *) strdup((char *) uripath);
+
+ if(!path)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_sasl_create_digest_http_message(data, userp, passwdp, request,
+ path, digest, &response, &len);
+ free(path);
+ if(result)
+ return result;
+
+ *allocuserpwd = aprintf("%sAuthorization: Digest %s\r\n",
+ proxy ? "Proxy-" : "",
+ response);
+ free(response);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
+
+ authp->done = TRUE;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_digest_cleanup(struct SessionHandle *data)
+{
+ Curl_sasl_digest_cleanup(&data->state.digest);
+ Curl_sasl_digest_cleanup(&data->state.proxydigest);
+}
+
+#endif
diff --git a/libcurl/src/lib/http_digest.h b/libcurl/src/lib/http_digest.h
new file mode 100644
index 0000000..699e2b1
--- /dev/null
+++ b/libcurl/src/lib/http_digest.h
@@ -0,0 +1,42 @@
+#ifndef HEADER_CURL_HTTP_DIGEST_H
+#define HEADER_CURL_HTTP_DIGEST_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/* this is for digest header input */
+CURL_STATIC CURLcode Curl_input_digest(struct connectdata *conn,
+ bool proxy, const char *header);
+
+/* this is for creating digest header output */
+CURL_STATIC CURLcode Curl_output_digest(struct connectdata *conn,
+ bool proxy,
+ const unsigned char *request,
+ const unsigned char *uripath);
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+CURL_STATIC void Curl_digest_cleanup(struct SessionHandle *data);
+#else
+#define Curl_digest_cleanup(x) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_HTTP_DIGEST_H */
diff --git a/libcurl/src/lib/http_negotiate.c b/libcurl/src/lib/http_negotiate.c
new file mode 100644
index 0000000..89cb613
--- /dev/null
+++ b/libcurl/src/lib/http_negotiate.c
@@ -0,0 +1,208 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
+
+#include "urldata.h"
+#include "sendf.h"
+#include "curl_gssapi.h"
+#include "rawstr.h"
+#include "curl_base64.h"
+#include "http_negotiate.h"
+#include "curl_sasl.h"
+#include "url.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+CURL_STATIC CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
+ const char *header)
+{
+ struct SessionHandle *data = conn->data;
+ struct negotiatedata *neg_ctx = proxy?&data->state.proxyneg:
+ &data->state.negotiate;
+ OM_uint32 major_status, minor_status, discard_st;
+ gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+ size_t len;
+ size_t rawlen = 0;
+ CURLcode result;
+
+ if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
+ /* We finished successfully our part of authentication, but server
+ * rejected it (since we're again here). Exit with an error since we
+ * can't invent anything better */
+ Curl_cleanup_negotiate(data);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ if(!neg_ctx->server_name) {
+ /* Generate our SPN */
+ char *spn = Curl_sasl_build_gssapi_spn("HTTP", proxy ? conn->proxy.name :
+ conn->host.name);
+ if(!spn)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Populate the SPN structure */
+ spn_token.value = spn;
+ spn_token.length = strlen(spn);
+
+ /* Import the SPN */
+ major_status = gss_import_name(&minor_status, &spn_token,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ &neg_ctx->server_name);
+ if(GSS_ERROR(major_status)) {
+ Curl_gss_log_error(data, minor_status, "gss_import_name() failed: ");
+
+ free(spn);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ free(spn);
+ }
+
+ header += strlen("Negotiate");
+ while(*header && ISSPACE(*header))
+ header++;
+
+ len = strlen(header);
+ if(len > 0) {
+ result = Curl_base64_decode(header, (unsigned char **)&input_token.value,
+ &rawlen);
+ if(result)
+ return result;
+
+ if(!rawlen) {
+ infof(data, "Negotiate handshake failure (empty challenge message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ input_token.length = rawlen;
+
+ DEBUGASSERT(input_token.value != NULL);
+ }
+
+ major_status = Curl_gss_init_sec_context(data,
+ &minor_status,
+ &neg_ctx->context,
+ neg_ctx->server_name,
+ &Curl_spnego_mech_oid,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &input_token,
+ &output_token,
+ TRUE,
+ NULL);
+ Curl_safefree(input_token.value);
+
+ neg_ctx->status = major_status;
+ if(GSS_ERROR(major_status)) {
+ if(output_token.value)
+ gss_release_buffer(&discard_st, &output_token);
+ Curl_gss_log_error(conn->data, minor_status,
+ "gss_init_sec_context() failed: ");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!output_token.value || !output_token.length) {
+ if(output_token.value)
+ gss_release_buffer(&discard_st, &output_token);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ neg_ctx->output_token = output_token;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
+{
+ struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
+ &conn->data->state.negotiate;
+ char *encoded = NULL;
+ size_t len = 0;
+ char *userp;
+ CURLcode result;
+ OM_uint32 discard_st;
+
+ result = Curl_base64_encode(conn->data,
+ neg_ctx->output_token.value,
+ neg_ctx->output_token.length,
+ &encoded, &len);
+ if(result) {
+ gss_release_buffer(&discard_st, &neg_ctx->output_token);
+ neg_ctx->output_token.value = NULL;
+ neg_ctx->output_token.length = 0;
+ return result;
+ }
+
+ if(!encoded || !len) {
+ gss_release_buffer(&discard_st, &neg_ctx->output_token);
+ neg_ctx->output_token.value = NULL;
+ neg_ctx->output_token.length = 0;
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+ encoded);
+ if(proxy) {
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ conn->allocptr.proxyuserpwd = userp;
+ }
+ else {
+ Curl_safefree(conn->allocptr.userpwd);
+ conn->allocptr.userpwd = userp;
+ }
+
+ free(encoded);
+
+ return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+}
+
+static void cleanup(struct negotiatedata *neg_ctx)
+{
+ OM_uint32 minor_status;
+ if(neg_ctx->context != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
+
+ if(neg_ctx->output_token.value)
+ gss_release_buffer(&minor_status, &neg_ctx->output_token);
+
+ if(neg_ctx->server_name != GSS_C_NO_NAME)
+ gss_release_name(&minor_status, &neg_ctx->server_name);
+
+ memset(neg_ctx, 0, sizeof(*neg_ctx));
+}
+
+CURL_STATIC void Curl_cleanup_negotiate(struct SessionHandle *data)
+{
+ cleanup(&data->state.negotiate);
+ cleanup(&data->state.proxyneg);
+}
+
+#endif /* HAVE_GSSAPI && !CURL_DISABLE_HTTP && USE_SPNEGO */
diff --git a/libcurl/src/lib/http_negotiate.h b/libcurl/src/lib/http_negotiate.h
new file mode 100644
index 0000000..931ce1f
--- /dev/null
+++ b/libcurl/src/lib/http_negotiate.h
@@ -0,0 +1,42 @@
+#ifndef HEADER_CURL_HTTP_NEGOTIATE_H
+#define HEADER_CURL_HTTP_NEGOTIATE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_SPNEGO
+
+/* this is for Negotiate header input */
+CURL_STATIC CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
+ const char *header);
+
+/* this is for creating Negotiate header output */
+CURL_STATIC CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
+
+CURL_STATIC void Curl_cleanup_negotiate(struct SessionHandle *data);
+
+#ifdef USE_WINDOWS_SSPI
+#define GSS_ERROR(status) (status & 0x80000000)
+#endif
+
+#endif /* USE_SPNEGO */
+
+#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
diff --git a/libcurl/src/lib/http_negotiate_sspi.c b/libcurl/src/lib/http_negotiate_sspi.c
new file mode 100644
index 0000000..efd2164
--- /dev/null
+++ b/libcurl/src/lib/http_negotiate_sspi.c
@@ -0,0 +1,298 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_WINDOWS_SSPI
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
+
+#include "urldata.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "warnless.h"
+#include "curl_base64.h"
+#include "curl_sasl.h"
+#include "http_negotiate.h"
+#include "curl_multibyte.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+CURL_STATIC CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
+ const char *header)
+{
+ BYTE *input_token = NULL;
+ SecBufferDesc out_buff_desc;
+ SecBuffer out_sec_buff;
+ SecBufferDesc in_buff_desc;
+ SecBuffer in_sec_buff;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+ size_t len = 0, input_token_len = 0;
+ CURLcode result;
+
+ /* Point to the username and password */
+ const char *userp;
+ const char *passwdp;
+
+ /* Point to the correct struct with this */
+ struct negotiatedata *neg_ctx;
+
+ if(proxy) {
+ userp = conn->proxyuser;
+ passwdp = conn->proxypasswd;
+ neg_ctx = &conn->data->state.proxyneg;
+ }
+ else {
+ userp = conn->user;
+ passwdp = conn->passwd;
+ neg_ctx = &conn->data->state.negotiate;
+ }
+
+ /* Not set means empty */
+ if(!userp)
+ userp = "";
+
+ if(!passwdp)
+ passwdp = "";
+
+ if(neg_ctx->context && neg_ctx->status == SEC_E_OK) {
+ /* We finished successfully our part of authentication, but server
+ * rejected it (since we're again here). Exit with an error since we
+ * can't invent anything better */
+ Curl_cleanup_negotiate(conn->data);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ if(!neg_ctx->server_name) {
+ /* Check proxy auth requested but no given proxy name */
+ if(proxy && !conn->proxy.name)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ /* Generate our SPN */
+ neg_ctx->server_name = Curl_sasl_build_spn("HTTP",
+ proxy ? conn->proxy.name :
+ conn->host.name);
+ if(!neg_ctx->server_name)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!neg_ctx->output_token) {
+ PSecPkgInfo SecurityPackage;
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
+ TEXT(SP_NAME_NEGOTIATE),
+ &SecurityPackage);
+ if(status != SEC_E_OK)
+ return CURLE_NOT_BUILT_IN;
+
+ /* Allocate input and output buffers according to the max token size
+ as indicated by the security package */
+ neg_ctx->token_max = SecurityPackage->cbMaxToken;
+ neg_ctx->output_token = malloc(neg_ctx->token_max);
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+ }
+
+ /* Obtain the input token, if any */
+ header += strlen("Negotiate");
+ while(*header && ISSPACE(*header))
+ header++;
+
+ len = strlen(header);
+ if(!len) {
+ /* Is this the first call in a new negotiation? */
+ if(neg_ctx->context) {
+ /* The server rejected our authentication and hasn't suppled any more
+ negotiation mechanisms */
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* We have to acquire credentials and allocate memory for the context */
+ neg_ctx->credentials = malloc(sizeof(CredHandle));
+ neg_ctx->context = malloc(sizeof(CtxtHandle));
+
+ if(!neg_ctx->credentials || !neg_ctx->context)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(userp && *userp) {
+ /* Populate our identity structure */
+ result = Curl_create_sspi_identity(userp, passwdp, &neg_ctx->identity);
+ if(result)
+ return result;
+
+ /* Allow proper cleanup of the identity structure */
+ neg_ctx->p_identity = &neg_ctx->identity;
+ }
+ else
+ /* Use the current Windows user */
+ neg_ctx->p_identity = NULL;
+
+ /* Acquire our credientials handle */
+ neg_ctx->status =
+ s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT(SP_NAME_NEGOTIATE),
+ SECPKG_CRED_OUTBOUND, NULL,
+ neg_ctx->p_identity, NULL, NULL,
+ neg_ctx->credentials, &expiry);
+ if(neg_ctx->status != SEC_E_OK)
+ return CURLE_LOGIN_DENIED;
+ }
+ else {
+ result = Curl_base64_decode(header,
+ (unsigned char **)&input_token,
+ &input_token_len);
+ if(result)
+ return result;
+
+ if(!input_token_len) {
+ infof(conn->data,
+ "Negotiate handshake failure (empty challenge message)\n");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+ }
+
+ /* Setup the "output" security buffer */
+ out_buff_desc.ulVersion = SECBUFFER_VERSION;
+ out_buff_desc.cBuffers = 1;
+ out_buff_desc.pBuffers = &out_sec_buff;
+ out_sec_buff.BufferType = SECBUFFER_TOKEN;
+ out_sec_buff.pvBuffer = neg_ctx->output_token;
+ out_sec_buff.cbBuffer = curlx_uztoul(neg_ctx->token_max);
+
+ /* Setup the "input" security buffer if present */
+ if(input_token) {
+ in_buff_desc.ulVersion = SECBUFFER_VERSION;
+ in_buff_desc.cBuffers = 1;
+ in_buff_desc.pBuffers = &in_sec_buff;
+ in_sec_buff.BufferType = SECBUFFER_TOKEN;
+ in_sec_buff.pvBuffer = input_token;
+ in_sec_buff.cbBuffer = curlx_uztoul(input_token_len);
+ }
+
+ /* Generate our message */
+ neg_ctx->status = s_pSecFn->InitializeSecurityContext(
+ neg_ctx->credentials,
+ input_token ? neg_ctx->context : NULL,
+ neg_ctx->server_name,
+ ISC_REQ_CONFIDENTIALITY,
+ 0,
+ SECURITY_NATIVE_DREP,
+ input_token ? &in_buff_desc : NULL,
+ 0,
+ neg_ctx->context,
+ &out_buff_desc,
+ &attrs,
+ &expiry);
+
+ free(input_token);
+
+ if(GSS_ERROR(neg_ctx->status))
+ return CURLE_OUT_OF_MEMORY;
+
+ if(neg_ctx->status == SEC_I_COMPLETE_NEEDED ||
+ neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE) {
+ neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context,
+ &out_buff_desc);
+ if(GSS_ERROR(neg_ctx->status))
+ return CURLE_RECV_ERROR;
+ }
+
+ neg_ctx->output_token_length = out_sec_buff.cbBuffer;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
+{
+ struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
+ &conn->data->state.negotiate;
+ char *encoded = NULL;
+ size_t len = 0;
+ char *userp;
+ CURLcode error;
+
+ error = Curl_base64_encode(conn->data,
+ (const char*)neg_ctx->output_token,
+ neg_ctx->output_token_length,
+ &encoded, &len);
+ if(error)
+ return error;
+
+ if(!len)
+ return CURLE_REMOTE_ACCESS_DENIED;
+
+ userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+ encoded);
+
+ if(proxy) {
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ conn->allocptr.proxyuserpwd = userp;
+ }
+ else {
+ Curl_safefree(conn->allocptr.userpwd);
+ conn->allocptr.userpwd = userp;
+ }
+ free(encoded);
+ return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+}
+
+static void cleanup(struct negotiatedata *neg_ctx)
+{
+ /* Free our security context */
+ if(neg_ctx->context) {
+ s_pSecFn->DeleteSecurityContext(neg_ctx->context);
+ free(neg_ctx->context);
+ neg_ctx->context = NULL;
+ }
+
+ /* Free our credentials handle */
+ if(neg_ctx->credentials) {
+ s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials);
+ free(neg_ctx->credentials);
+ neg_ctx->credentials = NULL;
+ }
+
+ /* Free our identity */
+ Curl_sspi_free_identity(neg_ctx->p_identity);
+ neg_ctx->p_identity = NULL;
+
+ /* Free the SPN and output token */
+ Curl_safefree(neg_ctx->server_name);
+ Curl_safefree(neg_ctx->output_token);
+
+ /* Reset any variables */
+ neg_ctx->token_max = 0;
+}
+
+CURL_STATIC void Curl_cleanup_negotiate(struct SessionHandle *data)
+{
+ cleanup(&data->state.negotiate);
+ cleanup(&data->state.proxyneg);
+}
+
+#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
+
+#endif /* USE_WINDOWS_SSPI */
diff --git a/libcurl/src/lib/http_proxy.c b/libcurl/src/lib/http_proxy.c
new file mode 100644
index 0000000..4c45b9c
--- /dev/null
+++ b/libcurl/src/lib/http_proxy.c
@@ -0,0 +1,590 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "http_proxy.h"
+#include "sendf.h"
+#include "http.h"
+#include "url.h"
+#include "select.h"
+#include "rawstr.h"
+#include "progress.h"
+#include "non-ascii.h"
+#include "connect.h"
+#include "curl_printf.h"
+#include "curlx.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURL_STATIC CURLcode Curl_proxy_connect(struct connectdata *conn)
+{
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
+#ifndef CURL_DISABLE_PROXY
+ /* for [protocol] tunneled through HTTP proxy */
+ struct HTTP http_proxy;
+ void *prot_save;
+ CURLcode result;
+
+ /* BLOCKING */
+ /* We want "seamless" operations through HTTP proxy tunnel */
+
+ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
+ * member conn->proto.http; we want [protocol] through HTTP and we have
+ * to change the member temporarily for connecting to the HTTP
+ * proxy. After Curl_proxyCONNECT we have to set back the member to the
+ * original pointer
+ *
+ * This function might be called several times in the multi interface case
+ * if the proxy's CONNTECT response is not instant.
+ */
+ prot_save = conn->data->req.protop;
+ memset(&http_proxy, 0, sizeof(http_proxy));
+ conn->data->req.protop = &http_proxy;
+ connkeep(conn, "HTTP proxy CONNECT");
+ result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
+ conn->host.name, conn->remote_port);
+ conn->data->req.protop = prot_save;
+ if(CURLE_OK != result)
+ return result;
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
+ }
+ /* no HTTP tunnel proxy, just return */
+ return CURLE_OK;
+}
+
+/*
+ * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
+ * function will issue the necessary commands to get a seamless tunnel through
+ * this proxy. After that, the socket can be used just as a normal socket.
+ */
+
+CURL_STATIC CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+ int sockindex,
+ const char *hostname,
+ int remote_port)
+{
+ int subversion=0;
+ struct SessionHandle *data=conn->data;
+ struct SingleRequest *k = &data->req;
+ CURLcode result;
+ curl_socket_t tunnelsocket = conn->sock[sockindex];
+ curl_off_t cl=0;
+ bool closeConnection = FALSE;
+ bool chunked_encoding = FALSE;
+ long check;
+
+#define SELECT_OK 0
+#define SELECT_ERROR 1
+#define SELECT_TIMEOUT 2
+ int error = SELECT_OK;
+
+ if(conn->tunnel_state[sockindex] == TUNNEL_COMPLETE)
+ return CURLE_OK; /* CONNECT is already completed */
+
+ conn->bits.proxy_connect_closed = FALSE;
+
+ do {
+ if(TUNNEL_INIT == conn->tunnel_state[sockindex]) {
+ /* BEGIN CONNECT PHASE */
+ char *host_port;
+ Curl_send_buffer *req_buffer;
+
+ infof(data, "Establish HTTP proxy tunnel to %s:%hu\n",
+ hostname, remote_port);
+
+ /* This only happens if we've looped here due to authentication
+ reasons, and we don't really use the newly cloned URL here
+ then. Just free() it. */
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+
+ /* initialize a dynamic send-buffer */
+ req_buffer = Curl_add_buffer_init();
+
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ host_port = aprintf("%s:%hu", hostname, remote_port);
+ if(!host_port) {
+ free(req_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);
+
+ free(host_port);
+
+ if(!result) {
+ char *host=(char *)"";
+ const char *proxyconn="";
+ const char *useragent="";
+ const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
+ "1.0" : "1.1";
+ char *hostheader= /* host:port with IPv6 support */
+ aprintf("%s%s%s:%hu", conn->bits.ipv6_ip?"[":"",
+ hostname, conn->bits.ipv6_ip?"]":"",
+ remote_port);
+ if(!hostheader) {
+ free(req_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!Curl_checkProxyheaders(conn, "Host:")) {
+ host = aprintf("Host: %s\r\n", hostheader);
+ if(!host) {
+ free(hostheader);
+ free(req_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
+ proxyconn = "Proxy-Connection: Keep-Alive\r\n";
+
+ if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
+ data->set.str[STRING_USERAGENT])
+ useragent = conn->allocptr.uagent;
+
+ result =
+ Curl_add_bufferf(req_buffer,
+ "CONNECT %s HTTP/%s\r\n"
+ "%s" /* Host: */
+ "%s" /* Proxy-Authorization */
+ "%s" /* User-Agent */
+ "%s", /* Proxy-Connection */
+ hostheader,
+ http,
+ host,
+ conn->allocptr.proxyuserpwd?
+ conn->allocptr.proxyuserpwd:"",
+ useragent,
+ proxyconn);
+
+ if(host && *host)
+ free(host);
+ free(hostheader);
+
+ if(!result)
+ result = Curl_add_custom_headers(conn, TRUE, req_buffer);
+
+ if(!result)
+ /* CRLF terminate the request */
+ result = Curl_add_bufferf(req_buffer, "\r\n");
+
+ if(!result) {
+ /* Send the connect request to the proxy */
+ /* BLOCKING */
+ result =
+ Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, sockindex);
+ }
+ req_buffer = NULL;
+ if(result)
+ failf(data, "Failed sending CONNECT to proxy");
+ }
+
+ free(req_buffer);
+ if(result)
+ return result;
+
+ conn->tunnel_state[sockindex] = TUNNEL_CONNECT;
+ } /* END CONNECT PHASE */
+
+ check = Curl_timeleft(data, NULL, TRUE);
+ if(check <= 0) {
+ failf(data, "Proxy CONNECT aborted due to timeout");
+ return CURLE_RECV_ERROR;
+ }
+
+ if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
+ /* return so we'll be called again polling-style */
+ return CURLE_OK;
+ else {
+ DEBUGF(infof(data,
+ "Read response immediately from proxy CONNECT\n"));
+ }
+
+ /* at this point, the tunnel_connecting phase is over. */
+
+ { /* READING RESPONSE PHASE */
+ size_t nread; /* total size read */
+ int perline; /* count bytes per line */
+ int keepon=TRUE;
+ ssize_t gotbytes;
+ char *ptr;
+ char *line_start;
+
+ ptr=data->state.buffer;
+ line_start = ptr;
+
+ nread=0;
+ perline=0;
+
+ while((nread<BUFSIZE) && (keepon && !error)) {
+
+ check = Curl_timeleft(data, NULL, TRUE);
+ if(check <= 0) {
+ failf(data, "Proxy CONNECT aborted due to timeout");
+ error = SELECT_TIMEOUT; /* already too little time */
+ break;
+ }
+
+ /* loop every second at least, less if the timeout is near */
+ switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
+ check<1000L?check:1000)) {
+ case -1: /* select() error, stop reading */
+ error = SELECT_ERROR;
+ failf(data, "Proxy CONNECT aborted due to select/poll error");
+ break;
+ case 0: /* timeout */
+ break;
+ default:
+ DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
+ result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
+ &gotbytes);
+ if(result==CURLE_AGAIN)
+ continue; /* go loop yourself */
+ else if(result)
+ keepon = FALSE;
+ else if(gotbytes <= 0) {
+ keepon = FALSE;
+ if(data->set.proxyauth && data->state.authproxy.avail) {
+ /* proxy auth was requested and there was proxy auth available,
+ then deem this as "mere" proxy disconnect */
+ conn->bits.proxy_connect_closed = TRUE;
+ infof(data, "Proxy CONNECT connection closed");
+ }
+ else {
+ error = SELECT_ERROR;
+ failf(data, "Proxy CONNECT aborted");
+ }
+ }
+ else {
+ /*
+ * We got a whole chunk of data, which can be anything from one
+ * byte to a set of lines and possibly just a piece of the last
+ * line.
+ */
+ int i;
+
+ nread += gotbytes;
+
+ if(keepon > TRUE) {
+ /* This means we are currently ignoring a response-body */
+
+ nread = 0; /* make next read start over in the read buffer */
+ ptr=data->state.buffer;
+ if(cl) {
+ /* A Content-Length based body: simply count down the counter
+ and make sure to break out of the loop when we're done! */
+ cl -= gotbytes;
+ if(cl<=0) {
+ keepon = FALSE;
+ break;
+ }
+ }
+ else {
+ /* chunked-encoded body, so we need to do the chunked dance
+ properly to know when the end of the body is reached */
+ CHUNKcode r;
+ ssize_t tookcareof=0;
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ /* we did the full CONNECT treatment, go COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ }
+ else
+ infof(data, "Read %zd bytes of chunk, continue\n",
+ tookcareof);
+ }
+ }
+ else
+ for(i = 0; i < gotbytes; ptr++, i++) {
+ perline++; /* amount of bytes in this line so far */
+ if(*ptr == 0x0a) {
+ char letter;
+ int writetype;
+
+ /* convert from the network encoding */
+ result = Curl_convert_from_network(data, line_start,
+ perline);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ /* output debug if that is requested */
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ line_start, (size_t)perline, conn);
+
+ /* send the header to the callback */
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+
+ result = Curl_client_write(conn, writetype, line_start,
+ perline);
+
+ data->info.header_size += (long)perline;
+ data->req.headerbytecount += (long)perline;
+
+ if(result)
+ return result;
+
+ /* Newlines are CRLF, so the CR is ignored as the line isn't
+ really terminated until the LF comes. Treat a following CR
+ as end-of-headers as well.*/
+
+ if(('\r' == line_start[0]) ||
+ ('\n' == line_start[0])) {
+ /* end of response-headers from the proxy */
+ nread = 0; /* make next read start over in the read
+ buffer */
+ ptr=data->state.buffer;
+ if((407 == k->httpcode) && !data->state.authproblem) {
+ /* If we get a 407 response code with content length
+ when we have no auth problem, we must ignore the
+ whole response-body */
+ keepon = 2;
+
+ if(cl) {
+ infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
+ " bytes of response-body\n", cl);
+
+ /* remove the remaining chunk of what we already
+ read */
+ cl -= (gotbytes - i);
+
+ if(cl<=0)
+ /* if the whole thing was already read, we are done!
+ */
+ keepon=FALSE;
+ }
+ else if(chunked_encoding) {
+ CHUNKcode r;
+ /* We set ignorebody true here since the chunked
+ decoder function will acknowledge that. Pay
+ attention so that this is cleared again when this
+ function returns! */
+ k->ignorebody = TRUE;
+ infof(data, "%zd bytes of chunk left\n", gotbytes-i);
+
+ if(line_start[1] == '\n') {
+ /* this can only be a LF if the letter at index 0
+ was a CR */
+ line_start++;
+ i++;
+ }
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(conn, line_start+1,
+ gotbytes -i, &gotbytes);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ /* we did the full CONNECT treatment, go to
+ COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ }
+ else
+ infof(data, "Read %zd bytes of chunk, continue\n",
+ gotbytes);
+ }
+ else {
+ /* without content-length or chunked encoding, we
+ can't keep the connection alive since the close is
+ the end signal so we bail out at once instead */
+ keepon=FALSE;
+ }
+ }
+ else {
+ keepon = FALSE;
+ if(200 == data->info.httpproxycode) {
+ if(gotbytes - (i+1))
+ failf(data, "Proxy CONNECT followed by %zd bytes "
+ "of opaque data. Data ignored (known bug #39)",
+ gotbytes - (i+1));
+ }
+ }
+ /* we did the full CONNECT treatment, go to COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ break; /* breaks out of for-loop, not switch() */
+ }
+
+ /* keep a backup of the position we are about to blank */
+ letter = line_start[perline];
+ line_start[perline]=0; /* zero terminate the buffer */
+ if((checkprefix("WWW-Authenticate:", line_start) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", line_start) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(line_start);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_http_input_auth(conn, proxy, auth);
+
+ free(auth);
+
+ if(result)
+ return result;
+ }
+ else if(checkprefix("Content-Length:", line_start)) {
+ cl = curlx_strtoofft(line_start +
+ strlen("Content-Length:"), NULL, 10);
+ }
+ else if(Curl_compareheader(line_start,
+ "Connection:", "close"))
+ closeConnection = TRUE;
+ else if(Curl_compareheader(line_start,
+ "Transfer-Encoding:",
+ "chunked")) {
+ infof(data, "CONNECT responded chunked\n");
+ chunked_encoding = TRUE;
+ /* init our chunky engine */
+ Curl_httpchunk_init(conn);
+ }
+ else if(Curl_compareheader(line_start,
+ "Proxy-Connection:", "close"))
+ closeConnection = TRUE;
+ else if(2 == sscanf(line_start, "HTTP/1.%d %d",
+ &subversion,
+ &k->httpcode)) {
+ /* store the HTTP code from the proxy */
+ data->info.httpproxycode = k->httpcode;
+ }
+ /* put back the letter we blanked out before */
+ line_start[perline]= letter;
+
+ perline=0; /* line starts over here */
+ line_start = ptr+1; /* this skips the zero byte we wrote */
+ }
+ }
+ }
+ break;
+ } /* switch */
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ } /* while there's buffer left and loop is requested */
+
+ if(error)
+ return CURLE_RECV_ERROR;
+
+ if(data->info.httpproxycode != 200) {
+ /* Deal with the possibly already received authenticate
+ headers. 'newurl' is set to a new URL if we must loop. */
+ result = Curl_http_auth_act(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.close)
+ /* the connection has been marked for closure, most likely in the
+ Curl_http_auth_act() function and thus we can kill it at once
+ below
+ */
+ closeConnection = TRUE;
+ }
+
+ if(closeConnection && data->req.newurl) {
+ /* Connection closed by server. Don't use it anymore */
+ Curl_closesocket(conn, conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+ break;
+ }
+ } /* END READING RESPONSE PHASE */
+
+ /* If we are supposed to continue and request a new URL, which basically
+ * means the HTTP authentication is still going on so if the tunnel
+ * is complete we start over in INIT state */
+ if(data->req.newurl &&
+ (TUNNEL_COMPLETE == conn->tunnel_state[sockindex])) {
+ conn->tunnel_state[sockindex] = TUNNEL_INIT;
+ infof(data, "TUNNEL_STATE switched to: %d\n",
+ conn->tunnel_state[sockindex]);
+ }
+
+ } while(data->req.newurl);
+
+ if(200 != data->req.httpcode) {
+ if(closeConnection && data->req.newurl) {
+ conn->bits.proxy_connect_closed = TRUE;
+ infof(data, "Connect me again please\n");
+ }
+ else {
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+ /* failure, close this connection to avoid re-use */
+ connclose(conn, "proxy CONNECT failure");
+ Curl_closesocket(conn, conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+ }
+
+ /* to back to init state */
+ conn->tunnel_state[sockindex] = TUNNEL_INIT;
+
+ if(conn->bits.proxy_connect_closed)
+ /* this is not an error, just part of the connection negotiation */
+ return CURLE_OK;
+ else {
+ failf(data, "Received HTTP code %d from proxy after CONNECT",
+ data->req.httpcode);
+ return CURLE_RECV_ERROR;
+ }
+ }
+
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+
+ /* If a proxy-authorization header was used for the proxy, then we should
+ make sure that it isn't accidentally used for the document request
+ after we've connected. So let's free and clear it here. */
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ conn->allocptr.proxyuserpwd = NULL;
+
+ data->state.authproxy.done = TRUE;
+
+ infof (data, "Proxy replied OK to CONNECT request\n");
+ data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
+ conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
+ document request */
+ return CURLE_OK;
+}
+#endif /* CURL_DISABLE_PROXY */
diff --git a/libcurl/src/lib/http_proxy.h b/libcurl/src/lib/http_proxy.h
new file mode 100644
index 0000000..cb50346
--- /dev/null
+++ b/libcurl/src/lib/http_proxy.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_HTTP_PROXY_H
+#define HEADER_CURL_HTTP_PROXY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
+/* ftp can use this as well */
+CURL_STATIC CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+ int tunnelsocket,
+ const char *hostname, int remote_port);
+
+/* Default proxy timeout in milliseconds */
+#define PROXY_TIMEOUT (3600*1000)
+
+CURL_STATIC CURLcode Curl_proxy_connect(struct connectdata *conn);
+
+#else
+#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
+#define Curl_proxy_connect(x) CURLE_OK
+#endif
+
+#endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/libcurl/src/lib/idn_win32.c b/libcurl/src/lib/idn_win32.c
new file mode 100644
index 0000000..b369723
--- /dev/null
+++ b/libcurl/src/lib/idn_win32.c
@@ -0,0 +1,108 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+ /*
+ * IDN conversions using Windows kernel32 and normaliz libraries.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_WIN32_IDN
+
+#include "curl_multibyte.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef WANT_IDN_PROTOTYPES
+# if defined(_SAL_VERSION)
+WINNORMALIZEAPI int WINAPI
+IdnToAscii(_In_ DWORD dwFlags,
+ _In_reads_(cchUnicodeChar) LPCWSTR lpUnicodeCharStr,
+ _In_ int cchUnicodeChar,
+ _Out_writes_opt_(cchASCIIChar) LPWSTR lpASCIICharStr,
+ _In_ int cchASCIIChar);
+WINNORMALIZEAPI int WINAPI
+IdnToUnicode(_In_ DWORD dwFlags,
+ _In_reads_(cchASCIIChar) LPCWSTR lpASCIICharStr,
+ _In_ int cchASCIIChar,
+ _Out_writes_opt_(cchUnicodeChar) LPWSTR lpUnicodeCharStr,
+ _In_ int cchUnicodeChar);
+# else
+WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags,
+ const WCHAR *lpUnicodeCharStr,
+ int cchUnicodeChar,
+ WCHAR *lpASCIICharStr,
+ int cchASCIIChar);
+WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
+ const WCHAR *lpASCIICharStr,
+ int cchASCIIChar,
+ WCHAR *lpUnicodeCharStr,
+ int cchUnicodeChar);
+# endif
+#endif
+
+#define IDN_MAX_LENGTH 255
+
+int curl_win32_idn_to_ascii(const char *in, char **out);
+int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8);
+
+int curl_win32_idn_to_ascii(const char *in, char **out)
+{
+ wchar_t *in_w = Curl_convert_UTF8_to_wchar(in);
+ if(in_w) {
+ wchar_t punycode[IDN_MAX_LENGTH];
+ if(IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH) == 0) {
+ wprintf(L"ERROR %d converting to Punycode\n", GetLastError());
+ free(in_w);
+ return 0;
+ }
+ free(in_w);
+
+ *out = Curl_convert_wchar_to_UTF8(punycode);
+ if(!*out)
+ return 0;
+ }
+ return 1;
+}
+
+int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8)
+{
+ (void)in_len; /* unused */
+ if(in) {
+ WCHAR unicode[IDN_MAX_LENGTH];
+
+ if(IdnToUnicode(0, (wchar_t *)in, -1, unicode, IDN_MAX_LENGTH) == 0) {
+ wprintf(L"ERROR %d converting to Punycode\n", GetLastError());
+ return 0;
+ }
+ else {
+ *out_utf8 = Curl_convert_wchar_to_UTF8(unicode);
+ if(!*out_utf8)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#endif /* USE_WIN32_IDN */
diff --git a/libcurl/src/lib/if2ip.c b/libcurl/src/lib/if2ip.c
new file mode 100644
index 0000000..c4f6e70
--- /dev/null
+++ b/libcurl/src/lib/if2ip.c
@@ -0,0 +1,271 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+#ifdef HAVE_IFADDRS_H
+# include <ifaddrs.h>
+#endif
+#ifdef HAVE_STROPTS_H
+# include <stropts.h>
+#endif
+#ifdef __VMS
+# include <inet.h>
+#endif
+
+#include "inet_ntop.h"
+#include "strequal.h"
+#include "if2ip.h"
+#include "curl_printf.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* ------------------------------------------------------------------ */
+
+/* Return the scope of the given address. */
+CURL_STATIC unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
+{
+#ifndef ENABLE_IPV6
+ (void) sa;
+#else
+ if(sa->sa_family == AF_INET6) {
+ const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *) sa;
+ const unsigned char * b = sa6->sin6_addr.s6_addr;
+ unsigned short w = (unsigned short) ((b[0] << 8) | b[1]);
+
+ switch(w & 0xFFC0) {
+ case 0xFE80:
+ return IPV6_SCOPE_LINKLOCAL;
+ case 0xFEC0:
+ return IPV6_SCOPE_SITELOCAL;
+ case 0x0000:
+ w = b[1] | b[2] | b[3] | b[4] | b[5] | b[6] | b[7] | b[8] | b[9] |
+ b[10] | b[11] | b[12] | b[13] | b[14];
+ if(w || b[15] != 0x01)
+ break;
+ return IPV6_SCOPE_NODELOCAL;
+ default:
+ break;
+ }
+ }
+#endif
+
+ return IPV6_SCOPE_GLOBAL;
+}
+
+
+#if defined(HAVE_GETIFADDRS)
+
+CURL_STATIC bool Curl_if_is_interface_name(const char *interf)
+{
+ bool result = FALSE;
+
+ struct ifaddrs *iface, *head;
+
+ if(getifaddrs(&head) >= 0) {
+ for(iface=head; iface != NULL; iface=iface->ifa_next) {
+ if(curl_strequal(iface->ifa_name, interf)) {
+ result = TRUE;
+ break;
+ }
+ }
+ freeifaddrs(head);
+ }
+ return result;
+}
+
+CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ unsigned int remote_scope_id, const char *interf,
+ char *buf, int buf_size)
+{
+ struct ifaddrs *iface, *head;
+ if2ip_result_t res = IF2IP_NOT_FOUND;
+
+#ifndef ENABLE_IPV6
+ (void) remote_scope;
+
+#ifndef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ (void) remote_scope_id;
+#endif
+
+#endif
+
+ if(getifaddrs(&head) >= 0) {
+ for(iface = head; iface != NULL; iface=iface->ifa_next) {
+ if(iface->ifa_addr != NULL) {
+ if(iface->ifa_addr->sa_family == af) {
+ if(curl_strequal(iface->ifa_name, interf)) {
+ void *addr;
+ char *ip;
+ char scope[12] = "";
+ char ipstr[64];
+#ifdef ENABLE_IPV6
+ if(af == AF_INET6) {
+ unsigned int scopeid = 0;
+ unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
+
+ if(ifscope != remote_scope) {
+ /* We are interested only in interface addresses whose
+ scope matches the remote address we want to
+ connect to: global for global, link-local for
+ link-local, etc... */
+ if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED;
+ continue;
+ }
+
+ addr = &((struct sockaddr_in6 *)iface->ifa_addr)->sin6_addr;
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ /* Include the scope of this interface as part of the address */
+ scopeid =
+ ((struct sockaddr_in6 *)iface->ifa_addr)->sin6_scope_id;
+
+ /* If given, scope id should match. */
+ if(remote_scope_id && scopeid != remote_scope_id) {
+ if(res == IF2IP_NOT_FOUND)
+ res = IF2IP_AF_NOT_SUPPORTED;
+
+ continue;
+ }
+#endif
+ if(scopeid)
+ snprintf(scope, sizeof(scope), "%%%u", scopeid);
+ }
+ else
+#endif
+ addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr;
+ res = IF2IP_FOUND;
+ ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
+ snprintf(buf, buf_size, "%s%s", ip, scope);
+ break;
+ }
+ }
+ else if((res == IF2IP_NOT_FOUND) &&
+ curl_strequal(iface->ifa_name, interf)) {
+ res = IF2IP_AF_NOT_SUPPORTED;
+ }
+ }
+ }
+
+ freeifaddrs(head);
+ }
+
+ return res;
+}
+
+#elif defined(HAVE_IOCTL_SIOCGIFADDR)
+
+CURL_STATIC bool Curl_if_is_interface_name(const char *interf)
+{
+ /* This is here just to support the old interfaces */
+ char buf[256];
+
+ return (Curl_if2ip(AF_INET, 0 /* unused */, 0, interf, buf, sizeof(buf)) ==
+ IF2IP_NOT_FOUND) ? FALSE : TRUE;
+}
+
+CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ unsigned int remote_scope_id, const char *interf,
+ char *buf, int buf_size)
+{
+ struct ifreq req;
+ struct in_addr in;
+ struct sockaddr_in *s;
+ curl_socket_t dummy;
+ size_t len;
+
+ (void)remote_scope;
+ (void)remote_scope_id;
+
+ if(!interf || (af != AF_INET))
+ return IF2IP_NOT_FOUND;
+
+ len = strlen(interf);
+ if(len >= sizeof(req.ifr_name))
+ return IF2IP_NOT_FOUND;
+
+ dummy = socket(AF_INET, SOCK_STREAM, 0);
+ if(CURL_SOCKET_BAD == dummy)
+ return IF2IP_NOT_FOUND;
+
+ memset(&req, 0, sizeof(req));
+ memcpy(req.ifr_name, interf, len+1);
+ req.ifr_addr.sa_family = AF_INET;
+
+ if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
+ sclose(dummy);
+ /* With SIOCGIFADDR, we cannot tell the difference between an interface
+ that does not exist and an interface that has no address of the
+ correct family. Assume the interface does not exist */
+ return IF2IP_NOT_FOUND;
+ }
+
+ s = (struct sockaddr_in *)&req.ifr_addr;
+ memcpy(&in, &s->sin_addr, sizeof(in));
+ Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
+
+ sclose(dummy);
+ return IF2IP_FOUND;
+}
+
+#else
+
+CURL_STATIC bool Curl_if_is_interface_name(const char *interf)
+{
+ (void) interf;
+
+ return FALSE;
+}
+
+CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ unsigned int remote_scope_id, const char *interf,
+ char *buf, int buf_size)
+{
+ (void) af;
+ (void) remote_scope;
+ (void) remote_scope_id;
+ (void) interf;
+ (void) buf;
+ (void) buf_size;
+ return IF2IP_NOT_FOUND;
+}
+
+#endif
diff --git a/libcurl/src/lib/if2ip.h b/libcurl/src/lib/if2ip.h
new file mode 100644
index 0000000..d6499f3
--- /dev/null
+++ b/libcurl/src/lib/if2ip.h
@@ -0,0 +1,83 @@
+#ifndef HEADER_CURL_IF2IP_H
+#define HEADER_CURL_IF2IP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/* IPv6 address scopes. */
+#define IPV6_SCOPE_GLOBAL 0 /* Global scope. */
+#define IPV6_SCOPE_LINKLOCAL 1 /* Link-local scope. */
+#define IPV6_SCOPE_SITELOCAL 2 /* Site-local scope (deprecated). */
+#define IPV6_SCOPE_NODELOCAL 3 /* Loopback. */
+
+CURL_STATIC unsigned int Curl_ipv6_scope(const struct sockaddr *sa);
+
+CURL_STATIC bool Curl_if_is_interface_name(const char *interf);
+
+typedef enum {
+ IF2IP_NOT_FOUND = 0, /* Interface not found */
+ IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */
+ IF2IP_FOUND = 2 /* The address has been stored in "buf" */
+} if2ip_result_t;
+
+CURL_STATIC if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ unsigned int remote_scope_id, const char *interf,
+ char *buf, int buf_size);
+
+#ifdef __INTERIX
+
+/* Nedelcho Stanev's work-around for SFU 3.0 */
+struct ifreq {
+#define IFNAMSIZ 16
+#define IFHWADDRLEN 6
+ union {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ } ifr_ifrn;
+
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ } ifr_ifru;
+};
+
+/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the
+ C code. */
+
+#define ifr_name ifr_ifrn.ifrn_name /* interface name */
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
+#define ifr_metric ifr_ifru.ifru_metric /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+
+#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
+
+#endif /* __INTERIX */
+
+#endif /* HEADER_CURL_IF2IP_H */
diff --git a/libcurl/src/lib/imap.c b/libcurl/src/lib/imap.c
new file mode 100644
index 0000000..e6d83f2
--- /dev/null
+++ b/libcurl/src/lib/imap.c
@@ -0,0 +1,2142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2595 Using TLS with IMAP, POP3 and ACAP
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC3501 IMAPv4 protocol
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ * RFC4959 IMAP Extension for SASL Initial Client Response
+ * RFC5092 IMAP URL Scheme
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_IMAP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "imap.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "select.h"
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "curl_sasl.h"
+#include "warnless.h"
+#include "curl_printf.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local API functions */
+static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
+static CURLcode imap_do(struct connectdata *conn, bool *done);
+static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+ bool premature);
+static CURLcode imap_connect(struct connectdata *conn, bool *done);
+static CURLcode imap_disconnect(struct connectdata *conn, bool dead);
+static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done);
+static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
+static CURLcode imap_setup_connection(struct connectdata *conn);
+static char *imap_atom(const char *str);
+static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...);
+static CURLcode imap_parse_url_options(struct connectdata *conn);
+static CURLcode imap_parse_url_path(struct connectdata *conn);
+static CURLcode imap_parse_custom_request(struct connectdata *conn);
+static CURLcode imap_perform_authenticate(struct connectdata *conn,
+ const char *mech,
+ const char *initresp);
+static CURLcode imap_continue_authenticate(struct connectdata *conn,
+ const char *resp);
+static void imap_get_message(char *buffer, char** outptr);
+
+/*
+ * IMAP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_imap = {
+ "IMAP", /* scheme */
+ imap_setup_connection, /* setup_connection */
+ imap_do, /* do_it */
+ imap_done, /* done */
+ ZERO_NULL, /* do_more */
+ imap_connect, /* connect_it */
+ imap_multi_statemach, /* connecting */
+ imap_doing, /* doing */
+ imap_getsock, /* proto_getsock */
+ imap_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ imap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAP, /* defport */
+ CURLPROTO_IMAP, /* protocol */
+ PROTOPT_CLOSEACTION /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * IMAPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_imaps = {
+ "IMAPS", /* scheme */
+ imap_setup_connection, /* setup_connection */
+ imap_do, /* do_it */
+ imap_done, /* done */
+ ZERO_NULL, /* do_more */
+ imap_connect, /* connect_it */
+ imap_multi_statemach, /* connecting */
+ imap_doing, /* doing */
+ imap_getsock, /* proto_getsock */
+ imap_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ imap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAPS, /* defport */
+ CURLPROTO_IMAPS, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed IMAP protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_imap_proxy = {
+ "IMAP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed IMAPS protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_imaps_proxy = {
+ "IMAPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAPS, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+/* SASL parameters for the imap protocol */
+static const struct SASLproto saslimap = {
+ "imap", /* The service name */
+ '+', /* Code received when continuation is expected */
+ 'O', /* Code to receive upon authentication success */
+ 0, /* Maximum initial response length (no max) */
+ imap_perform_authenticate, /* Send authentication command */
+ imap_continue_authenticate, /* Send authentication continuation */
+ imap_get_message /* Get SASL response message */
+};
+
+
+#ifdef USE_SSL
+static void imap_to_imaps(struct connectdata *conn)
+{
+ conn->handler = &Curl_handler_imaps;
+}
+#else
+#define imap_to_imaps(x) Curl_nop_stmt
+#endif
+
+/***********************************************************************
+ *
+ * imap_matchresp()
+ *
+ * Determines whether the untagged response is related to the specified
+ * command by checking if it is in format "* <command-name> ..." or
+ * "* <number> <command-name> ...".
+ *
+ * The "* " marker is assumed to have already been checked by the caller.
+ */
+static bool imap_matchresp(const char *line, size_t len, const char *cmd)
+{
+ const char *end = line + len;
+ size_t cmd_len = strlen(cmd);
+
+ /* Skip the untagged response marker */
+ line += 2;
+
+ /* Do we have a number after the marker? */
+ if(line < end && ISDIGIT(*line)) {
+ /* Skip the number */
+ do
+ line++;
+ while(line < end && ISDIGIT(*line));
+
+ /* Do we have the space character? */
+ if(line == end || *line != ' ')
+ return FALSE;
+
+ line++;
+ }
+
+ /* Does the command name match and is it followed by a space character or at
+ the end of line? */
+ if(line + cmd_len <= end && Curl_raw_nequal(line, cmd, cmd_len) &&
+ (line[cmd_len] == ' ' || line + cmd_len + 2 == end))
+ return TRUE;
+
+ return FALSE;
+}
+
+/***********************************************************************
+ *
+ * imap_endofresp()
+ *
+ * Checks whether the given string is a valid tagged, untagged or continuation
+ * response which can be processed by the response handler.
+ */
+static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *resp)
+{
+ struct IMAP *imap = conn->data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *id = imapc->resptag;
+ size_t id_len = strlen(id);
+
+ /* Do we have a tagged command response? */
+ if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') {
+ line += id_len + 1;
+ len -= id_len + 1;
+
+ if(len >= 2 && !memcmp(line, "OK", 2))
+ *resp = 'O';
+ else if(len >= 2 && !memcmp(line, "NO", 2))
+ *resp = 'N';
+ else if(len >= 3 && !memcmp(line, "BAD", 3))
+ *resp = 'B';
+ else {
+ failf(conn->data, "Bad tagged response");
+ *resp = -1;
+ }
+
+ return TRUE;
+ }
+
+ /* Do we have an untagged command response? */
+ if(len >= 2 && !memcmp("* ", line, 2)) {
+ switch(imapc->state) {
+ /* States which are interested in untagged responses */
+ case IMAP_CAPABILITY:
+ if(!imap_matchresp(line, len, "CAPABILITY"))
+ return FALSE;
+ break;
+
+ case IMAP_LIST:
+ if((!imap->custom && !imap_matchresp(line, len, "LIST")) ||
+ (imap->custom && !imap_matchresp(line, len, imap->custom) &&
+ (strcmp(imap->custom, "STORE") ||
+ !imap_matchresp(line, len, "FETCH")) &&
+ strcmp(imap->custom, "SELECT") &&
+ strcmp(imap->custom, "EXAMINE") &&
+ strcmp(imap->custom, "SEARCH") &&
+ strcmp(imap->custom, "EXPUNGE") &&
+ strcmp(imap->custom, "LSUB") &&
+ strcmp(imap->custom, "UID") &&
+ strcmp(imap->custom, "NOOP")))
+ return FALSE;
+ break;
+
+ case IMAP_SELECT:
+ /* SELECT is special in that its untagged responses do not have a
+ common prefix so accept anything! */
+ break;
+
+ case IMAP_FETCH:
+ if(!imap_matchresp(line, len, "FETCH"))
+ return FALSE;
+ break;
+
+ case IMAP_SEARCH:
+ if(!imap_matchresp(line, len, "SEARCH"))
+ return FALSE;
+ break;
+
+ /* Ignore other untagged responses */
+ default:
+ return FALSE;
+ }
+
+ *resp = '*';
+ return TRUE;
+ }
+
+ /* Do we have a continuation response? This should be a + symbol followed by
+ a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
+ APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
+ some e-mail servers ignore this and only send a single + instead. */
+ if((len == 3 && !memcmp("+", line, 1)) ||
+ (len >= 2 && !memcmp("+ ", line, 2))) {
+ switch(imapc->state) {
+ /* States which are interested in continuation responses */
+ case IMAP_AUTHENTICATE:
+ case IMAP_APPEND:
+ *resp = '+';
+ break;
+
+ default:
+ failf(conn->data, "Unexpected continuation response");
+ *resp = -1;
+ break;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE; /* Nothing for us */
+}
+
+/***********************************************************************
+ *
+ * imap_get_message()
+ *
+ * Gets the authentication message from the response buffer.
+ */
+static void imap_get_message(char *buffer, char** outptr)
+{
+ size_t len = 0;
+ char* message = NULL;
+
+ /* Find the start of the message */
+ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
+ ;
+
+ /* Find the end of the message */
+ for(len = strlen(message); len--;)
+ if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+ message[len] != '\t')
+ break;
+
+ /* Terminate the message */
+ if(++len) {
+ message[len] = '\0';
+ }
+
+ *outptr = message;
+}
+
+/***********************************************************************
+ *
+ * state()
+ *
+ * This is the ONLY way to change IMAP state!
+ */
+static void state(struct connectdata *conn, imapstate newstate)
+{
+ struct imap_conn *imapc = &conn->proto.imapc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[]={
+ "STOP",
+ "SERVERGREET",
+ "CAPABILITY",
+ "STARTTLS",
+ "UPGRADETLS",
+ "AUTHENTICATE",
+ "LOGIN",
+ "LIST",
+ "SELECT",
+ "FETCH",
+ "FETCH_FINAL",
+ "APPEND",
+ "APPEND_FINAL",
+ "SEARCH",
+ "LOGOUT",
+ /* LAST */
+ };
+
+ if(imapc->state != newstate)
+ infof(conn->data, "IMAP %p state change from %s to %s\n",
+ (void *)imapc, names[imapc->state], names[newstate]);
+#endif
+
+ imapc->state = newstate;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_capability()
+ *
+ * Sends the CAPABILITY command in order to obtain a list of server side
+ * supported capabilities.
+ */
+static CURLcode imap_perform_capability(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */
+ imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */
+ imapc->tls_supported = FALSE; /* Clear the TLS capability */
+
+ /* Send the CAPABILITY command */
+ result = imap_sendf(conn, "CAPABILITY");
+
+ if(!result)
+ state(conn, IMAP_CAPABILITY);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_starttls()
+ *
+ * Sends the STARTTLS command to start the upgrade to TLS.
+ */
+static CURLcode imap_perform_starttls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the STARTTLS command */
+ result = imap_sendf(conn, "STARTTLS");
+
+ if(!result)
+ state(conn, IMAP_STARTTLS);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_upgrade_tls()
+ *
+ * Performs the upgrade to TLS.
+ */
+static CURLcode imap_perform_upgrade_tls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ /* Start the SSL connection */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
+
+ if(!result) {
+ if(imapc->state != IMAP_UPGRADETLS)
+ state(conn, IMAP_UPGRADETLS);
+
+ if(imapc->ssldone) {
+ imap_to_imaps(conn);
+ result = imap_perform_capability(conn);
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_login()
+ *
+ * Sends a clear text LOGIN command to authenticate with.
+ */
+static CURLcode imap_perform_login(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ char *user;
+ char *passwd;
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, IMAP_STOP);
+
+ return result;
+ }
+
+ /* Make sure the username and password are in the correct atom format */
+ user = imap_atom(conn->user);
+ passwd = imap_atom(conn->passwd);
+
+ /* Send the LOGIN command */
+ result = imap_sendf(conn, "LOGIN %s %s", user ? user : "",
+ passwd ? passwd : "");
+
+ free(user);
+ free(passwd);
+
+ if(!result)
+ state(conn, IMAP_LOGIN);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_authenticate()
+ *
+ * Sends an AUTHENTICATE command allowing the client to login with the given
+ * SASL authentication mechanism.
+ */
+static CURLcode imap_perform_authenticate(struct connectdata *conn,
+ const char *mech,
+ const char *initresp)
+{
+ CURLcode result = CURLE_OK;
+
+ if(initresp) {
+ /* Send the AUTHENTICATE command with the initial response */
+ result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp);
+ }
+ else {
+ /* Send the AUTHENTICATE command */
+ result = imap_sendf(conn, "AUTHENTICATE %s", mech);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_continue_authenticate()
+ *
+ * Sends SASL continuation data or cancellation.
+ */
+static CURLcode imap_continue_authenticate(struct connectdata *conn,
+ const char *resp)
+{
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ return Curl_pp_sendf(&imapc->pp, "%s", resp);
+}
+
+/***********************************************************************
+ *
+ * imap_perform_authentication()
+ *
+ * Initiates the authentication sequence, with the appropriate SASL
+ * authentication mechanism, falling back to clear text should a common
+ * mechanism not be available between the client and server.
+ */
+static CURLcode imap_perform_authentication(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ saslprogress progress;
+
+ /* Check we have enough data to authenticate with and end the
+ connect phase if we don't */
+ if(!Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
+ state(conn, IMAP_STOP);
+ return result;
+ }
+
+ /* Calculate the SASL login details */
+ result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress);
+
+ if(!result) {
+ if(progress == SASL_INPROGRESS)
+ state(conn, IMAP_AUTHENTICATE);
+ else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
+ /* Perform clear text authentication */
+ result = imap_perform_login(conn);
+ else {
+ /* Other mechanisms not supported */
+ infof(conn->data, "No known authentication mechanisms supported!\n");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_list()
+ *
+ * Sends a LIST command or an alternative custom request.
+ */
+static CURLcode imap_perform_list(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ char *mailbox;
+
+ if(imap->custom)
+ /* Send the custom request */
+ result = imap_sendf(conn, "%s%s", imap->custom,
+ imap->custom_params ? imap->custom_params : "");
+ else {
+ /* Make sure the mailbox is in the correct atom format */
+ mailbox = imap_atom(imap->mailbox ? imap->mailbox : "");
+ if(!mailbox)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the LIST command */
+ result = imap_sendf(conn, "LIST \"%s\" *", mailbox);
+
+ free(mailbox);
+ }
+
+ if(!result)
+ state(conn, IMAP_LIST);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_select()
+ *
+ * Sends a SELECT command to ask the server to change the selected mailbox.
+ */
+static CURLcode imap_perform_select(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ char *mailbox;
+
+ /* Invalidate old information as we are switching mailboxes */
+ Curl_safefree(imapc->mailbox);
+ Curl_safefree(imapc->mailbox_uidvalidity);
+
+ /* Check we have a mailbox */
+ if(!imap->mailbox) {
+ failf(conn->data, "Cannot SELECT without a mailbox.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Make sure the mailbox is in the correct atom format */
+ mailbox = imap_atom(imap->mailbox);
+ if(!mailbox)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the SELECT command */
+ result = imap_sendf(conn, "SELECT %s", mailbox);
+
+ free(mailbox);
+
+ if(!result)
+ state(conn, IMAP_SELECT);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_fetch()
+ *
+ * Sends a FETCH command to initiate the download of a message.
+ */
+static CURLcode imap_perform_fetch(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct IMAP *imap = conn->data->req.protop;
+
+ /* Check we have a UID */
+ if(!imap->uid) {
+ failf(conn->data, "Cannot FETCH without a UID.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Send the FETCH command */
+ if(imap->partial)
+ result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
+ imap->uid,
+ imap->section ? imap->section : "",
+ imap->partial);
+ else
+ result = imap_sendf(conn, "FETCH %s BODY[%s]",
+ imap->uid,
+ imap->section ? imap->section : "");
+
+ if(!result)
+ state(conn, IMAP_FETCH);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_append()
+ *
+ * Sends an APPEND command to initiate the upload of a message.
+ */
+static CURLcode imap_perform_append(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct IMAP *imap = conn->data->req.protop;
+ char *mailbox;
+
+ /* Check we have a mailbox */
+ if(!imap->mailbox) {
+ failf(conn->data, "Cannot APPEND without a mailbox.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Check we know the size of the upload */
+ if(conn->data->state.infilesize < 0) {
+ failf(conn->data, "Cannot APPEND with unknown input file size\n");
+ return CURLE_UPLOAD_FAILED;
+ }
+
+ /* Make sure the mailbox is in the correct atom format */
+ mailbox = imap_atom(imap->mailbox);
+ if(!mailbox)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the APPEND command */
+ result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
+ mailbox, conn->data->state.infilesize);
+
+ free(mailbox);
+
+ if(!result)
+ state(conn, IMAP_APPEND);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_search()
+ *
+ * Sends a SEARCH command.
+ */
+static CURLcode imap_perform_search(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct IMAP *imap = conn->data->req.protop;
+
+ /* Check we have a query string */
+ if(!imap->query) {
+ failf(conn->data, "Cannot SEARCH without a query string.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Send the SEARCH command */
+ result = imap_sendf(conn, "SEARCH %s", imap->query);
+
+ if(!result)
+ state(conn, IMAP_SEARCH);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_logout()
+ *
+ * Performs the logout action prior to sclose() being called.
+ */
+static CURLcode imap_perform_logout(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the LOGOUT command */
+ result = imap_sendf(conn, "LOGOUT");
+
+ if(!result)
+ state(conn, IMAP_LOGOUT);
+
+ return result;
+}
+
+/* For the initial server greeting */
+static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != 'O') {
+ failf(data, "Got unexpected imap-server response");
+ result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
+ }
+ else
+ result = imap_perform_capability(conn);
+
+ return result;
+}
+
+/* For CAPABILITY responses */
+static CURLcode imap_state_capability_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *line = data->state.buffer;
+ size_t wordlen;
+
+ (void)instate; /* no use for this yet */
+
+ /* Do we have a untagged response? */
+ if(imapcode == '*') {
+ line += 2;
+
+ /* Loop through the data line */
+ for(;;) {
+ while(*line &&
+ (*line == ' ' || *line == '\t' ||
+ *line == '\r' || *line == '\n')) {
+
+ line++;
+ }
+
+ if(!*line)
+ break;
+
+ /* Extract the word */
+ for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' &&
+ line[wordlen] != '\t' && line[wordlen] != '\r' &&
+ line[wordlen] != '\n';)
+ wordlen++;
+
+ /* Does the server support the STARTTLS capability? */
+ if(wordlen == 8 && !memcmp(line, "STARTTLS", 8))
+ imapc->tls_supported = TRUE;
+
+ /* Has the server explicitly disabled clear text authentication? */
+ else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13))
+ imapc->login_disabled = TRUE;
+
+ /* Does the server support the SASL-IR capability? */
+ else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7))
+ imapc->ir_supported = TRUE;
+
+ /* Do we have a SASL based authentication mechanism? */
+ else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) {
+ size_t llen;
+ unsigned int mechbit;
+
+ line += 5;
+ wordlen -= 5;
+
+ /* Test the word for a matching authentication mechanism */
+ if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) &&
+ llen == wordlen)
+ imapc->sasl.authmechs |= mechbit;
+ }
+
+ line += wordlen;
+ }
+ }
+ else if(imapcode == 'O') {
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but SSL is requested */
+ if(imapc->tls_supported)
+ /* Switch to TLS connection now */
+ result = imap_perform_starttls(conn);
+ else if(data->set.use_ssl == CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = imap_perform_authentication(conn);
+ else {
+ failf(data, "STARTTLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
+ }
+ else
+ result = imap_perform_authentication(conn);
+ }
+ else
+ result = imap_perform_authentication(conn);
+
+ return result;
+}
+
+/* For STARTTLS responses */
+static CURLcode imap_state_starttls_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != 'O') {
+ if(data->set.use_ssl != CURLUSESSL_TRY) {
+ failf(data, "STARTTLS denied. %c", imapcode);
+ result = CURLE_USE_SSL_FAILED;
+ }
+ else
+ result = imap_perform_authentication(conn);
+ }
+ else
+ result = imap_perform_upgrade_tls(conn);
+
+ return result;
+}
+
+/* For SASL authentication responses */
+static CURLcode imap_state_auth_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ saslprogress progress;
+
+ (void)instate; /* no use for this yet */
+
+ result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress);
+ if(!result)
+ switch(progress) {
+ case SASL_DONE:
+ state(conn, IMAP_STOP); /* Authenticated */
+ break;
+ case SASL_IDLE: /* No mechanism left after cancellation */
+ if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
+ /* Perform clear text authentication */
+ result = imap_perform_login(conn);
+ else {
+ failf(data, "Authentication cancelled");
+ result = CURLE_LOGIN_DENIED;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+/* For LOGIN responses */
+static CURLcode imap_state_login_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != 'O') {
+ failf(data, "Access denied. %c", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For LIST responses */
+static CURLcode imap_state_list_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ char *line = conn->data->state.buffer;
+ size_t len = strlen(line);
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode == '*') {
+ /* Temporarily add the LF character back and send as body to the client */
+ line[len] = '\n';
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ line[len] = '\0';
+ }
+ else if(imapcode != 'O')
+ result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+ else
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For SELECT responses */
+static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = conn->data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *line = data->state.buffer;
+ char tmp[20];
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode == '*') {
+ /* See if this is an UIDVALIDITY response */
+ if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
+ Curl_safefree(imapc->mailbox_uidvalidity);
+ imapc->mailbox_uidvalidity = strdup(tmp);
+ }
+ }
+ else if(imapcode == 'O') {
+ /* Check if the UIDVALIDITY has been specified and matches */
+ if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
+ strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
+ failf(conn->data, "Mailbox UIDVALIDITY has changed");
+ result = CURLE_REMOTE_FILE_NOT_FOUND;
+ }
+ else {
+ /* Note the currently opened mailbox on this connection */
+ imapc->mailbox = strdup(imap->mailbox);
+
+ if(imap->custom)
+ result = imap_perform_list(conn);
+ else if(imap->query)
+ result = imap_perform_search(conn);
+ else
+ result = imap_perform_fetch(conn);
+ }
+ }
+ else {
+ failf(data, "Select failed");
+ result = CURLE_LOGIN_DENIED;
+ }
+
+ return result;
+}
+
+/* For the (first line of the) FETCH responses */
+static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ struct pingpong *pp = &imapc->pp;
+ const char *ptr = data->state.buffer;
+ bool parsed = FALSE;
+ curl_off_t size;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '*') {
+ Curl_pgrsSetDownloadSize(data, -1);
+ state(conn, IMAP_STOP);
+ return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */
+ }
+
+ /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
+ the continuation data contained within the curly brackets */
+ while(*ptr && (*ptr != '{'))
+ ptr++;
+
+ if(*ptr == '{') {
+ char *endptr;
+ size = curlx_strtoofft(ptr + 1, &endptr, 10);
+ if(endptr - ptr > 1 && endptr[0] == '}' &&
+ endptr[1] == '\r' && endptr[2] == '\0')
+ parsed = TRUE;
+ }
+
+ if(parsed) {
+ infof(data, "Found %" CURL_FORMAT_CURL_OFF_TU " bytes to download\n",
+ size);
+ Curl_pgrsSetDownloadSize(data, size);
+
+ if(pp->cache) {
+ /* At this point there is a bunch of data in the header "cache" that is
+ actually body content, send it as body and then skip it. Do note
+ that there may even be additional "headers" after the body. */
+ size_t chunk = pp->cache_size;
+
+ if(chunk > (size_t)size)
+ /* The conversion from curl_off_t to size_t is always fine here */
+ chunk = (size_t)size;
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
+ if(result)
+ return result;
+
+ data->req.bytecount += chunk;
+
+ infof(data, "Written %" CURL_FORMAT_CURL_OFF_TU
+ " bytes, %" CURL_FORMAT_CURL_OFF_TU
+ " bytes are left for transfer\n", (curl_off_t)chunk,
+ size - chunk);
+
+ /* Have we used the entire cache or just part of it?*/
+ if(pp->cache_size > chunk) {
+ /* Only part of it so shrink the cache to fit the trailing data */
+ memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk);
+ pp->cache_size -= chunk;
+ }
+ else {
+ /* Free the cache */
+ Curl_safefree(pp->cache);
+
+ /* Reset the cache size */
+ pp->cache_size = 0;
+ }
+ }
+
+ if(data->req.bytecount == size)
+ /* The entire data is already transferred! */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ else {
+ /* IMAP download */
+ data->req.maxdownload = size;
+ Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL);
+ }
+ }
+ else {
+ /* We don't know how to parse this line */
+ failf(pp->conn->data, "Failed to parse FETCH response.");
+ result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
+ }
+
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For final FETCH responses performed after the download */
+static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode != 'O')
+ result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: Fix error code */
+ else
+ /* End of DONE phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For APPEND responses */
+static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode != '+') {
+ result = CURLE_UPLOAD_FAILED;
+ }
+ else {
+ /* Set the progress upload size */
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* IMAP upload */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+ }
+
+ return result;
+}
+
+/* For final APPEND responses performed after the upload */
+static CURLcode imap_state_append_final_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode != 'O')
+ result = CURLE_UPLOAD_FAILED;
+ else
+ /* End of DONE phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For SEARCH responses */
+static CURLcode imap_state_search_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ char *line = conn->data->state.buffer;
+ size_t len = strlen(line);
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode == '*') {
+ /* Temporarily add the LF character back and send as body to the client */
+ line[len] = '\n';
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ line[len] = '\0';
+ }
+ else if(imapcode != 'O')
+ result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+ else
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+static CURLcode imap_statemach_act(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ int imapcode;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ struct pingpong *pp = &imapc->pp;
+ size_t nread = 0;
+
+ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
+ if(imapc->state == IMAP_UPGRADETLS)
+ return imap_perform_upgrade_tls(conn);
+
+ /* Flush any data that needs to be sent */
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ do {
+ /* Read the response from the server */
+ result = Curl_pp_readresp(sock, pp, &imapcode, &nread);
+ if(result)
+ return result;
+
+ /* Was there an error parsing the response line? */
+ if(imapcode == -1)
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
+
+ if(!imapcode)
+ break;
+
+ /* We have now received a full IMAP server response */
+ switch(imapc->state) {
+ case IMAP_SERVERGREET:
+ result = imap_state_servergreet_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_CAPABILITY:
+ result = imap_state_capability_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_STARTTLS:
+ result = imap_state_starttls_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE:
+ result = imap_state_auth_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_LOGIN:
+ result = imap_state_login_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_LIST:
+ result = imap_state_list_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_SELECT:
+ result = imap_state_select_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_FETCH:
+ result = imap_state_fetch_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_FETCH_FINAL:
+ result = imap_state_fetch_final_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_APPEND:
+ result = imap_state_append_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_APPEND_FINAL:
+ result = imap_state_append_final_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_SEARCH:
+ result = imap_state_search_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_LOGOUT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, IMAP_STOP);
+ break;
+ }
+ } while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp));
+
+ return result;
+}
+
+/* Called repeatedly until done from multi.c */
+static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
+ if(result || !imapc->ssldone)
+ return result;
+ }
+
+ result = Curl_pp_statemach(&imapc->pp, FALSE);
+ *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode imap_block_statemach(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ while(imapc->state != IMAP_STOP && !result)
+ result = Curl_pp_statemach(&imapc->pp, TRUE);
+
+ return result;
+}
+
+/* Allocate and initialize the struct IMAP for the current SessionHandle if
+ required */
+static CURLcode imap_init(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap;
+
+ imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
+ if(!imap)
+ result = CURLE_OUT_OF_MEMORY;
+
+ return result;
+}
+
+/* For the IMAP "protocol connect" and "doing" phases only */
+static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks);
+}
+
+/***********************************************************************
+ *
+ * imap_connect()
+ *
+ * This function should do everything that is to be considered a part of the
+ * connection phase.
+ *
+ * The variable 'done' points to will be TRUE if the protocol-layer connect
+ * phase is done when this function returns, or FALSE if not.
+ */
+static CURLcode imap_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ struct pingpong *pp = &imapc->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections in IMAP */
+ connkeep(conn, "IMAP default");
+
+ /* Set the default response time-out */
+ pp->response_time = RESP_TIMEOUT;
+ pp->statemach_act = imap_statemach_act;
+ pp->endofresp = imap_endofresp;
+ pp->conn = conn;
+
+ /* Set the default preferred authentication type and mechanism */
+ imapc->preftype = IMAP_TYPE_ANY;
+ Curl_sasl_init(&imapc->sasl, &saslimap);
+
+ /* Initialise the pingpong layer */
+ Curl_pp_init(pp);
+
+ /* Parse the URL options */
+ result = imap_parse_url_options(conn);
+ if(result)
+ return result;
+
+ /* Start off waiting for the server greeting response */
+ state(conn, IMAP_SERVERGREET);
+
+ /* Start off with an response id of '*' */
+ strcpy(imapc->resptag, "*");
+
+ result = imap_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+
+ (void)premature;
+
+ if(!imap)
+ /* When the easy handle is removed from the multi interface while libcurl
+ is still trying to resolve the host name, the IMAP struct is not yet
+ initialized. However, the removal action calls Curl_done() which in
+ turn calls this function, so we simply return success. */
+ return CURLE_OK;
+
+ if(status) {
+ connclose(conn, "IMAP done with bad status"); /* marked for closure */
+ result = status; /* use the already set error code */
+ }
+ else if(!data->set.connect_only && !imap->custom &&
+ (imap->uid || data->set.upload)) {
+ /* Handle responses after FETCH or APPEND transfer has finished */
+ if(!data->set.upload)
+ state(conn, IMAP_FETCH_FINAL);
+ else {
+ /* End the APPEND command first by sending an empty line */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
+ if(!result)
+ state(conn, IMAP_APPEND_FINAL);
+ }
+
+ /* Run the state-machine
+
+ TODO: when the multi interface is used, this _really_ should be using
+ the imap_multi_statemach function but we have no general support for
+ non-blocking DONE operations, not in the multi state machine and with
+ Curl_done() invokes on several places in the code!
+ */
+ if(!result)
+ result = imap_block_statemach(conn);
+ }
+
+ /* Cleanup our per-request based variables */
+ Curl_safefree(imap->mailbox);
+ Curl_safefree(imap->uidvalidity);
+ Curl_safefree(imap->uid);
+ Curl_safefree(imap->section);
+ Curl_safefree(imap->partial);
+ Curl_safefree(imap->query);
+ Curl_safefree(imap->custom);
+ Curl_safefree(imap->custom_params);
+
+ /* Clear the transfer mode for the next request */
+ imap->transfer = FTPTRANSFER_BODY;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform()
+ *
+ * This is the actual DO function for IMAP. Fetch or append a message, or do
+ * other things according to the options previously setup.
+ */
+static CURLcode imap_perform(struct connectdata *conn, bool *connected,
+ bool *dophase_done)
+{
+ /* This is IMAP and no proxy */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ bool selected = FALSE;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(conn->data->set.opt_no_body) {
+ /* Requested no body means no transfer */
+ imap->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* Determine if the requested mailbox (with the same UIDVALIDITY if set)
+ has already been selected on this connection */
+ if(imap->mailbox && imapc->mailbox &&
+ !strcmp(imap->mailbox, imapc->mailbox) &&
+ (!imap->uidvalidity || !imapc->mailbox_uidvalidity ||
+ !strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)))
+ selected = TRUE;
+
+ /* Start the first command in the DO phase */
+ if(conn->data->set.upload)
+ /* APPEND can be executed directly */
+ result = imap_perform_append(conn);
+ else if(imap->custom && (selected || !imap->mailbox))
+ /* Custom command using the same mailbox or no mailbox */
+ result = imap_perform_list(conn);
+ else if(!imap->custom && selected && imap->uid)
+ /* FETCH from the same mailbox */
+ result = imap_perform_fetch(conn);
+ else if(!imap->custom && selected && imap->query)
+ /* SEARCH the current mailbox */
+ result = imap_perform_search(conn);
+ else if(imap->mailbox && !selected &&
+ (imap->custom || imap->uid || imap->query))
+ /* SELECT the mailbox */
+ result = imap_perform_select(conn);
+ else
+ /* LIST */
+ result = imap_perform_list(conn);
+
+ if(result)
+ return result;
+
+ /* Run the state-machine */
+ result = imap_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (imap_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode imap_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+
+ *done = FALSE; /* default to false */
+
+ /* Parse the URL path */
+ result = imap_parse_url_path(conn);
+ if(result)
+ return result;
+
+ /* Parse the custom request */
+ result = imap_parse_custom_request(conn);
+ if(result)
+ return result;
+
+ result = imap_regular_transfer(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_disconnect()
+ *
+ * Disconnect from an IMAP server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to. */
+
+ /* The IMAP session may or may not have been allocated/setup at this
+ point! */
+ if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
+ if(!imap_perform_logout(conn))
+ (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
+
+ /* Disconnect from the server */
+ Curl_pp_disconnect(&imapc->pp);
+
+ /* Cleanup the SASL module */
+ Curl_sasl_cleanup(conn, imapc->sasl.authused);
+
+ /* Cleanup our connection based variables */
+ Curl_safefree(imapc->mailbox);
+ Curl_safefree(imapc->mailbox_uidvalidity);
+
+ return CURLE_OK;
+}
+
+/* Call this when the DO phase has completed */
+static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
+{
+ struct IMAP *imap = conn->data->req.protop;
+
+ (void)connected;
+
+ if(imap->transfer != FTPTRANSFER_BODY)
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ return CURLE_OK;
+}
+
+/* Called from multi.c while DOing */
+static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = imap_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = imap_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ */
+static CURLcode imap_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ struct SessionHandle *data = conn->data;
+
+ /* Make sure size is unknown at this point */
+ data->req.size = -1;
+
+ /* Set the progress data */
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ /* Carry out the perform */
+ result = imap_perform(conn, &connected, dophase_done);
+
+ /* Perform post DO phase operations if necessary */
+ if(!result && *dophase_done)
+ result = imap_dophase_done(conn, connected);
+
+ return result;
+}
+
+static CURLcode imap_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+
+ /* Initialise the IMAP layer */
+ CURLcode result = imap_init(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel IMAP operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_imap)
+ conn->handler = &Curl_handler_imap_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_imaps_proxy;
+#else
+ failf(data, "IMAPS not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ /* set it up as an HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+#else
+ failf(data, "IMAP over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ data->state.path++; /* don't include the initial slash */
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * imap_sendf()
+ *
+ * Sends the formated string as an IMAP command to the server.
+ *
+ * Designed to never block.
+ */
+static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ char *taggedfmt;
+ va_list ap;
+
+ DEBUGASSERT(fmt);
+
+ /* Calculate the next command ID wrapping at 3 digits */
+ imapc->cmdid = (imapc->cmdid + 1) % 1000;
+
+ /* Calculate the tag based on the connection ID and command ID */
+ snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
+ 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
+
+ /* Prefix the format with the tag */
+ taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
+ if(!taggedfmt)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the data with the tag */
+ va_start(ap, fmt);
+ result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
+ va_end(ap);
+
+ free(taggedfmt);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_atom()
+ *
+ * Checks the input string for characters that need escaping and returns an
+ * atom ready for sending to the server.
+ *
+ * The returned string needs to be freed.
+ *
+ */
+static char *imap_atom(const char *str)
+{
+ const char *p1;
+ char *p2;
+ size_t backsp_count = 0;
+ size_t quote_count = 0;
+ bool space_exists = FALSE;
+ size_t newlen = 0;
+ char *newstr = NULL;
+
+ if(!str)
+ return NULL;
+
+ /* Count any unescaped characters */
+ p1 = str;
+ while(*p1) {
+ if(*p1 == '\\')
+ backsp_count++;
+ else if(*p1 == '"')
+ quote_count++;
+ else if(*p1 == ' ')
+ space_exists = TRUE;
+
+ p1++;
+ }
+
+ /* Does the input contain any unescaped characters? */
+ if(!backsp_count && !quote_count && !space_exists)
+ return strdup(str);
+
+ /* Calculate the new string length */
+ newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0);
+
+ /* Allocate the new string */
+ newstr = (char *) malloc((newlen + 1) * sizeof(char));
+ if(!newstr)
+ return NULL;
+
+ /* Surround the string in quotes if necessary */
+ p2 = newstr;
+ if(space_exists) {
+ newstr[0] = '"';
+ newstr[newlen - 1] = '"';
+ p2++;
+ }
+
+ /* Copy the string, escaping backslash and quote characters along the way */
+ p1 = str;
+ while(*p1) {
+ if(*p1 == '\\' || *p1 == '"') {
+ *p2 = '\\';
+ p2++;
+ }
+
+ *p2 = *p1;
+
+ p1++;
+ p2++;
+ }
+
+ /* Terminate the string */
+ newstr[newlen] = '\0';
+
+ return newstr;
+}
+
+/***********************************************************************
+ *
+ * imap_is_bchar()
+ *
+ * Portable test of whether the specified char is a "bchar" as defined in the
+ * grammar of RFC-5092.
+ */
+static bool imap_is_bchar(char ch)
+{
+ switch(ch) {
+ /* bchar */
+ case ':': case '@': case '/':
+ /* bchar -> achar */
+ case '&': case '=':
+ /* bchar -> achar -> uchar -> unreserved */
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
+ case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
+ case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
+ case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+ case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
+ case 'v': case 'w': case 'x': case 'y': case 'z':
+ case '-': case '.': case '_': case '~':
+ /* bchar -> achar -> uchar -> sub-delims-sh */
+ case '!': case '$': case '\'': case '(': case ')': case '*':
+ case '+': case ',':
+ /* bchar -> achar -> uchar -> pct-encoded */
+ case '%': /* HEXDIG chars are already included above */
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/***********************************************************************
+ *
+ * imap_parse_url_options()
+ *
+ * Parse the URL login options.
+ */
+static CURLcode imap_parse_url_options(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *ptr = conn->options;
+
+ imapc->sasl.resetprefs = TRUE;
+
+ while(!result && ptr && *ptr) {
+ const char *key = ptr;
+ const char *value;
+
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ value = ptr + 1;
+
+ while(*ptr && *ptr != ';')
+ ptr++;
+
+ if(strnequal(key, "AUTH=", 5))
+ result = Curl_sasl_parse_url_auth_option(&imapc->sasl,
+ value, ptr - value);
+ else
+ result = CURLE_URL_MALFORMAT;
+
+ if(*ptr == ';')
+ ptr++;
+ }
+
+ switch(imapc->sasl.prefmech) {
+ case SASL_AUTH_NONE:
+ imapc->preftype = IMAP_TYPE_NONE;
+ break;
+ case SASL_AUTH_DEFAULT:
+ imapc->preftype = IMAP_TYPE_ANY;
+ break;
+ default:
+ imapc->preftype = IMAP_TYPE_SASL;
+ break;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ *
+ */
+static CURLcode imap_parse_url_path(struct connectdata *conn)
+{
+ /* The imap struct is already initialised in imap_connect() */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ const char *begin = data->state.path;
+ const char *ptr = begin;
+
+ /* See how much of the URL is a valid path and decode it */
+ while(imap_is_bchar(*ptr))
+ ptr++;
+
+ if(ptr != begin) {
+ /* Remove the trailing slash if present */
+ const char *end = ptr;
+ if(end > begin && end[-1] == '/')
+ end--;
+
+ result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL,
+ TRUE);
+ if(result)
+ return result;
+ }
+ else
+ imap->mailbox = NULL;
+
+ /* There can be any number of parameters in the form ";NAME=VALUE" */
+ while(*ptr == ';') {
+ char *name;
+ char *value;
+ size_t valuelen;
+
+ /* Find the length of the name parameter */
+ begin = ++ptr;
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ if(!*ptr)
+ return CURLE_URL_MALFORMAT;
+
+ /* Decode the name parameter */
+ result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE);
+ if(result)
+ return result;
+
+ /* Find the length of the value parameter */
+ begin = ++ptr;
+ while(imap_is_bchar(*ptr))
+ ptr++;
+
+ /* Decode the value parameter */
+ result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE);
+ if(result) {
+ free(name);
+ return result;
+ }
+
+ DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value));
+
+ /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and
+ PARTIAL) stripping of the trailing slash character if it is present.
+
+ Note: Unknown parameters trigger a URL_MALFORMAT error. */
+ if(Curl_raw_equal(name, "UIDVALIDITY") && !imap->uidvalidity) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->uidvalidity = value;
+ value = NULL;
+ }
+ else if(Curl_raw_equal(name, "UID") && !imap->uid) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->uid = value;
+ value = NULL;
+ }
+ else if(Curl_raw_equal(name, "SECTION") && !imap->section) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->section = value;
+ value = NULL;
+ }
+ else if(Curl_raw_equal(name, "PARTIAL") && !imap->partial) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->partial = value;
+ value = NULL;
+ }
+ else {
+ free(name);
+ free(value);
+
+ return CURLE_URL_MALFORMAT;
+ }
+
+ free(name);
+ free(value);
+ }
+
+ /* Does the URL contain a query parameter? Only valid when we have a mailbox
+ and no UID as per RFC-5092 */
+ if(imap->mailbox && !imap->uid && *ptr == '?') {
+ /* Find the length of the query parameter */
+ begin = ++ptr;
+ while(imap_is_bchar(*ptr))
+ ptr++;
+
+ /* Decode the query parameter */
+ result = Curl_urldecode(data, begin, ptr - begin, &imap->query, NULL,
+ TRUE);
+ if(result)
+ return result;
+ }
+
+ /* Any extra stuff at the end of the URL is an error */
+ if(*ptr)
+ return CURLE_URL_MALFORMAT;
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * imap_parse_custom_request()
+ *
+ * Parse the custom request.
+ */
+static CURLcode imap_parse_custom_request(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ const char *custom = data->set.str[STRING_CUSTOMREQUEST];
+
+ if(custom) {
+ /* URL decode the custom request */
+ result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE);
+
+ /* Extract the parameters if specified */
+ if(!result) {
+ const char *params = imap->custom;
+
+ while(*params && *params != ' ')
+ params++;
+
+ if(*params) {
+ imap->custom_params = strdup(params);
+ imap->custom[params - imap->custom] = '\0';
+
+ if(!imap->custom_params)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ }
+
+ return result;
+}
+
+#endif /* CURL_DISABLE_IMAP */
diff --git a/libcurl/src/lib/imap.h b/libcurl/src/lib/imap.h
new file mode 100644
index 0000000..3189daa
--- /dev/null
+++ b/libcurl/src/lib/imap.h
@@ -0,0 +1,96 @@
+#ifndef HEADER_CURL_IMAP_H
+#define HEADER_CURL_IMAP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+#include "curl_sasl.h"
+
+/****************************************************************************
+ * IMAP unique setup
+ ***************************************************************************/
+typedef enum {
+ IMAP_STOP, /* do nothing state, stops the state machine */
+ IMAP_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ IMAP_CAPABILITY,
+ IMAP_STARTTLS,
+ IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ IMAP_AUTHENTICATE,
+ IMAP_LOGIN,
+ IMAP_LIST,
+ IMAP_SELECT,
+ IMAP_FETCH,
+ IMAP_FETCH_FINAL,
+ IMAP_APPEND,
+ IMAP_APPEND_FINAL,
+ IMAP_SEARCH,
+ IMAP_LOGOUT,
+ IMAP_LAST /* never used */
+} imapstate;
+
+/* This IMAP struct is used in the SessionHandle. All IMAP data that is
+ connection-oriented must be in imap_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct IMAP {
+ curl_pp_transfer transfer;
+ char *mailbox; /* Mailbox to select */
+ char *uidvalidity; /* UIDVALIDITY to check in select */
+ char *uid; /* Message UID to fetch */
+ char *section; /* Message SECTION to fetch */
+ char *partial; /* Message PARTIAL to fetch */
+ char *query; /* Query to search for */
+ char *custom; /* Custom request */
+ char *custom_params; /* Parameters for the custom request */
+};
+
+/* imap_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct imap_conn {
+ struct pingpong pp;
+ imapstate state; /* Always use imap.c:state() to change state! */
+ bool ssldone; /* Is connect() over SSL done? */
+ struct SASL sasl; /* SASL-related parameters */
+ unsigned int preftype; /* Preferred authentication type */
+ int cmdid; /* Last used command ID */
+ char resptag[5]; /* Response tag to wait for */
+ bool tls_supported; /* StartTLS capability supported by server */
+ bool login_disabled; /* LOGIN command disabled by server */
+ bool ir_supported; /* Initial response supported by server */
+ char *mailbox; /* The last selected mailbox */
+ char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
+};
+
+extern const struct Curl_handler Curl_handler_imap;
+extern const struct Curl_handler Curl_handler_imaps;
+
+/* Authentication type flags */
+#define IMAP_TYPE_CLEARTEXT (1 << 0)
+#define IMAP_TYPE_SASL (1 << 1)
+
+/* Authentication type values */
+#define IMAP_TYPE_NONE 0
+#define IMAP_TYPE_ANY ~0U
+
+#endif /* HEADER_CURL_IMAP_H */
diff --git a/libcurl/src/lib/inet_ntop.c b/libcurl/src/lib/inet_ntop.c
new file mode 100644
index 0000000..daf9c1c
--- /dev/null
+++ b/libcurl/src/lib/inet_ntop.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 1996-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Original code by Paul Vixie. "curlified" by Gisle Vanem.
+ */
+
+#include "curl_setup.h"
+
+#ifndef HAVE_INET_NTOP
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "curl_printf.h"
+
+#include "inet_ntop.h"
+
+#define IN6ADDRSZ 16
+#define INADDRSZ 4
+#define INT16SZ 2
+
+/*
+ * Format an IPv4 address, more or less like inet_ntoa().
+ *
+ * Returns `dst' (as a const)
+ * Note:
+ * - uses no statics
+ * - takes a unsigned char* not an in_addr as input
+ */
+static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
+{
+ char tmp[sizeof "255.255.255.255"];
+ size_t len;
+
+ DEBUGASSERT(size >= 16);
+
+ tmp[0] = '\0';
+ (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
+ ((int)((unsigned char)src[0])) & 0xff,
+ ((int)((unsigned char)src[1])) & 0xff,
+ ((int)((unsigned char)src[2])) & 0xff,
+ ((int)((unsigned char)src[3])) & 0xff);
+
+ len = strlen(tmp);
+ if(len == 0 || len >= size) {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return dst;
+}
+
+#ifdef ENABLE_IPV6
+/*
+ * Convert IPv6 binary address into presentation (printable) format.
+ */
+static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ char *tp;
+ struct {
+ long base;
+ long len;
+ } best, cur;
+ unsigned long words[IN6ADDRSZ / INT16SZ];
+ int i;
+
+ /* Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof(words));
+ for(i = 0; i < IN6ADDRSZ; i++)
+ words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
+
+ best.base = -1;
+ cur.base = -1;
+ best.len = 0;
+ cur.len = 0;
+
+ for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+ if(words[i] == 0) {
+ if(cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ }
+ else if(cur.base != -1) {
+ if(best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
+ best = cur;
+ if(best.base != -1 && best.len < 2)
+ best.base = -1;
+ /* Format the result. */
+ tp = tmp;
+ for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if(best.base != -1 && i >= best.base && i < (best.base + best.len)) {
+ if(i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+
+ /* Are we following an initial run of 0x00s or any real hex?
+ */
+ if(i != 0)
+ *tp++ = ':';
+
+ /* Is this address an encapsulated IPv4?
+ */
+ if(i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+ if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += snprintf(tp, 5, "%lx", words[i]);
+ }
+
+ /* Was it a trailing run of 0x00's?
+ */
+ if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /* Check for overflow, copy, and we're done.
+ */
+ if((size_t)(tp - tmp) > size) {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return dst;
+}
+#endif /* ENABLE_IPV6 */
+
+/*
+ * Convert a network format address to presentation format.
+ *
+ * Returns pointer to presentation format address (`buf').
+ * Returns NULL on error and errno set with the specific
+ * error, EAFNOSUPPORT or ENOSPC.
+ *
+ * On Windows we store the error in the thread errno, not
+ * in the winsock error code. This is to avoid losing the
+ * actual last winsock error. So use macro ERRNO to fetch the
+ * errno this function sets when returning NULL, not SOCKERRNO.
+ */
+CURL_STATIC char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return inet_ntop4((const unsigned char*)src, buf, size);
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ return inet_ntop6((const unsigned char*)src, buf, size);
+#endif
+ default:
+ SET_ERRNO(EAFNOSUPPORT);
+ return NULL;
+ }
+}
+#endif /* HAVE_INET_NTOP */
diff --git a/libcurl/src/lib/inet_ntop.h b/libcurl/src/lib/inet_ntop.h
new file mode 100644
index 0000000..68e393a
--- /dev/null
+++ b/libcurl/src/lib/inet_ntop.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_INET_NTOP_H
+#define HEADER_CURL_INET_NTOP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+CURL_STATIC char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
+
+#ifdef HAVE_INET_NTOP
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#define Curl_inet_ntop(af,addr,buf,size) \
+ inet_ntop(af, addr, buf, (curl_socklen_t)size)
+#endif
+
+#endif /* HEADER_CURL_INET_NTOP_H */
+
diff --git a/libcurl/src/lib/inet_pton.c b/libcurl/src/lib/inet_pton.c
new file mode 100644
index 0000000..5556b30
--- /dev/null
+++ b/libcurl/src/lib/inet_pton.c
@@ -0,0 +1,234 @@
+/* This is from the BIND 4.9.4 release, modified to compile by itself */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "curl_setup.h"
+
+#ifndef HAVE_INET_PTON
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "inet_pton.h"
+
+#define IN6ADDRSZ 16
+#define INADDRSZ 4
+#define INT16SZ 2
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, unsigned char *dst);
+#ifdef ENABLE_IPV6
+static int inet_pton6(const char *src, unsigned char *dst);
+#endif
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * notice:
+ * On Windows we store the error in the thread errno, not
+ * in the winsock error code. This is to avoid losing the
+ * actual last winsock error. So use macro ERRNO to fetch the
+ * errno this function sets when returning (-1), not SOCKERRNO.
+ * author:
+ * Paul Vixie, 1996.
+ */
+CURL_STATIC int
+Curl_inet_pton(int af, const char *src, void *dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, (unsigned char *)dst));
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ return (inet_pton6(src, (unsigned char *)dst));
+#endif
+ default:
+ SET_ERRNO(EAFNOSUPPORT);
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ tp = tmp;
+ *tp = 0;
+ while((ch = *src++) != '\0') {
+ const char *pch;
+
+ if((pch = strchr(digits, ch)) != NULL) {
+ unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
+
+ if(saw_digit && *tp == 0)
+ return (0);
+ if(val > 255)
+ return (0);
+ *tp = (unsigned char)val;
+ if(! saw_digit) {
+ if(++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ }
+ else if(ch == '.' && saw_digit) {
+ if(octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ }
+ else
+ return (0);
+ }
+ if(octets < 4)
+ return (0);
+ memcpy(dst, tmp, INADDRSZ);
+ return (1);
+}
+
+#ifdef ENABLE_IPV6
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ size_t val;
+
+ memset((tp = tmp), 0, IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if(*src == ':')
+ if(*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while((ch = *src++) != '\0') {
+ const char *pch;
+
+ if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if(pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if(++saw_xdigit > 4)
+ return (0);
+ continue;
+ }
+ if(ch == ':') {
+ curtok = src;
+ if(!saw_xdigit) {
+ if(colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if(tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if(saw_xdigit) {
+ if(tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if(colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const ssize_t n = tp - colonp;
+ ssize_t i;
+
+ if(tp == endp)
+ return (0);
+ for(i = 1; i <= n; i++) {
+ *(endp - i) = *(colonp + n - i);
+ *(colonp + n - i) = 0;
+ }
+ tp = endp;
+ }
+ if(tp != endp)
+ return (0);
+ memcpy(dst, tmp, IN6ADDRSZ);
+ return (1);
+}
+#endif /* ENABLE_IPV6 */
+
+#endif /* HAVE_INET_PTON */
diff --git a/libcurl/src/lib/inet_pton.h b/libcurl/src/lib/inet_pton.h
new file mode 100644
index 0000000..a17b001
--- /dev/null
+++ b/libcurl/src/lib/inet_pton.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_INET_PTON_H
+#define HEADER_CURL_INET_PTON_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+CURL_STATIC int Curl_inet_pton(int, const char *, void *);
+
+#ifdef HAVE_INET_PTON
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
+#endif
+
+#endif /* HEADER_CURL_INET_PTON_H */
+
diff --git a/libcurl/src/lib/krb5.c b/libcurl/src/lib/krb5.c
new file mode 100644
index 0000000..4c5b78f
--- /dev/null
+++ b/libcurl/src/lib/krb5.c
@@ -0,0 +1,332 @@
+/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c
+ *
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Hgskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * Copyright (c) 2004 - 2015 Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include "curl_setup.h"
+
+#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_FTP)
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "urldata.h"
+#include "curl_base64.h"
+#include "ftp.h"
+#include "curl_gssapi.h"
+#include "sendf.h"
+#include "curl_sec.h"
+#include "warnless.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define LOCAL_ADDR (&conn->local_addr)
+#define REMOTE_ADDR conn->ip_addr->ai_addr
+
+static int
+krb5_init(void *app_data)
+{
+ gss_ctx_id_t *context = app_data;
+ /* Make sure our context is initialized for krb5_end. */
+ *context = GSS_C_NO_CONTEXT;
+ return 0;
+}
+
+static int
+krb5_check_prot(void *app_data, int level)
+{
+ (void)app_data; /* unused */
+ if(level == PROT_CONFIDENTIAL)
+ return -1;
+ return 0;
+}
+
+static int
+krb5_decode(void *app_data, void *buf, int len,
+ int level UNUSED_PARAM,
+ struct connectdata *conn UNUSED_PARAM)
+{
+ gss_ctx_id_t *context = app_data;
+ OM_uint32 maj, min;
+ gss_buffer_desc enc, dec;
+
+ (void)level;
+ (void)conn;
+
+ enc.value = buf;
+ enc.length = len;
+ maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL);
+ if(maj != GSS_S_COMPLETE) {
+ if(len >= 4)
+ strcpy(buf, "599 ");
+ return -1;
+ }
+
+ memcpy(buf, dec.value, dec.length);
+ len = curlx_uztosi(dec.length);
+ gss_release_buffer(&min, &dec);
+
+ return len;
+}
+
+static int
+krb5_overhead(void *app_data, int level, int len)
+{
+ /* no arguments are used */
+ (void)app_data;
+ (void)level;
+ (void)len;
+ return 0;
+}
+
+static int
+krb5_encode(void *app_data, const void *from, int length, int level, void **to)
+{
+ gss_ctx_id_t *context = app_data;
+ gss_buffer_desc dec, enc;
+ OM_uint32 maj, min;
+ int state;
+ int len;
+
+ /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
+ * libraries modify the input buffer in gss_seal()
+ */
+ dec.value = (void*)from;
+ dec.length = length;
+ maj = gss_seal(&min, *context,
+ level == PROT_PRIVATE,
+ GSS_C_QOP_DEFAULT,
+ &dec, &state, &enc);
+
+ if(maj != GSS_S_COMPLETE)
+ return -1;
+
+ /* malloc a new buffer, in case gss_release_buffer doesn't work as
+ expected */
+ *to = malloc(enc.length);
+ if(!*to)
+ return -1;
+ memcpy(*to, enc.value, enc.length);
+ len = curlx_uztosi(enc.length);
+ gss_release_buffer(&min, &enc);
+ return len;
+}
+
+static int
+krb5_auth(void *app_data, struct connectdata *conn)
+{
+ int ret = AUTH_OK;
+ char *p;
+ const char *host = conn->host.name;
+ ssize_t nread;
+ curl_socklen_t l = sizeof(conn->local_addr);
+ struct SessionHandle *data = conn->data;
+ CURLcode result;
+ const char *service = "ftp", *srv_host = "host";
+ gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp;
+ OM_uint32 maj, min;
+ gss_name_t gssname;
+ gss_ctx_id_t *context = app_data;
+ struct gss_channel_bindings_struct chan;
+ size_t base64_sz = 0;
+
+ if(getsockname(conn->sock[FIRSTSOCKET],
+ (struct sockaddr *)LOCAL_ADDR, &l) < 0)
+ perror("getsockname()");
+
+ chan.initiator_addrtype = GSS_C_AF_INET;
+ chan.initiator_address.length = l - 4;
+ chan.initiator_address.value =
+ &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr;
+ chan.acceptor_addrtype = GSS_C_AF_INET;
+ chan.acceptor_address.length = l - 4;
+ chan.acceptor_address.value =
+ &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr;
+ chan.application_data.length = 0;
+ chan.application_data.value = NULL;
+
+ /* this loop will execute twice (once for service, once for host) */
+ for(;;) {
+ /* this really shouldn't be repeated here, but can't help it */
+ if(service == srv_host) {
+ result = Curl_ftpsendf(conn, "AUTH GSSAPI");
+
+ if(result)
+ return -2;
+ if(Curl_GetFTPResponse(&nread, conn, NULL))
+ return -1;
+
+ if(data->state.buffer[0] != '3')
+ return -1;
+ }
+
+ input_buffer.value = data->state.buffer;
+ input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s",
+ service, host);
+ maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE,
+ &gssname);
+ if(maj != GSS_S_COMPLETE) {
+ gss_release_name(&min, &gssname);
+ if(service == srv_host) {
+ Curl_failf(data, "Error importing service name %s",
+ input_buffer.value);
+ return AUTH_ERROR;
+ }
+ service = srv_host;
+ continue;
+ }
+ /* We pass NULL as |output_name_type| to avoid a leak. */
+ gss_display_name(&min, gssname, &output_buffer, NULL);
+ Curl_infof(data, "Trying against %s\n", output_buffer.value);
+ gssresp = GSS_C_NO_BUFFER;
+ *context = GSS_C_NO_CONTEXT;
+
+ do {
+ /* Release the buffer at each iteration to avoid leaking: the first time
+ we are releasing the memory from gss_display_name. The last item is
+ taken care by a final gss_release_buffer. */
+ gss_release_buffer(&min, &output_buffer);
+ ret = AUTH_OK;
+ maj = Curl_gss_init_sec_context(data,
+ &min,
+ context,
+ gssname,
+ &Curl_krb5_mech_oid,
+ &chan,
+ gssresp,
+ &output_buffer,
+ TRUE,
+ NULL);
+
+ if(gssresp) {
+ free(_gssresp.value);
+ gssresp = NULL;
+ }
+
+ if(GSS_ERROR(maj)) {
+ Curl_infof(data, "Error creating security context\n");
+ ret = AUTH_ERROR;
+ break;
+ }
+
+ if(output_buffer.length != 0) {
+ result = Curl_base64_encode(data, (char *)output_buffer.value,
+ output_buffer.length, &p, &base64_sz);
+ if(result) {
+ Curl_infof(data, "base64-encoding: %s\n",
+ curl_easy_strerror(result));
+ ret = AUTH_CONTINUE;
+ break;
+ }
+
+ result = Curl_ftpsendf(conn, "ADAT %s", p);
+
+ free(p);
+
+ if(result) {
+ ret = -2;
+ break;
+ }
+
+ if(Curl_GetFTPResponse(&nread, conn, NULL)) {
+ ret = -1;
+ break;
+ }
+
+ if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') {
+ Curl_infof(data, "Server didn't accept auth data\n");
+ ret = AUTH_ERROR;
+ break;
+ }
+
+ p = data->state.buffer + 4;
+ p = strstr(p, "ADAT=");
+ if(p) {
+ result = Curl_base64_decode(p + 5,
+ (unsigned char **)&_gssresp.value,
+ &_gssresp.length);
+ if(result) {
+ Curl_failf(data, "base64-decoding: %s",
+ curl_easy_strerror(result));
+ ret = AUTH_CONTINUE;
+ break;
+ }
+ }
+
+ gssresp = &_gssresp;
+ }
+ } while(maj == GSS_S_CONTINUE_NEEDED);
+
+ gss_release_name(&min, &gssname);
+ gss_release_buffer(&min, &output_buffer);
+
+ if(gssresp)
+ free(_gssresp.value);
+
+ if(ret == AUTH_OK || service == srv_host)
+ return ret;
+
+ service = srv_host;
+ }
+ return ret;
+}
+
+static void krb5_end(void *app_data)
+{
+ OM_uint32 min;
+ gss_ctx_id_t *context = app_data;
+ if(*context != GSS_C_NO_CONTEXT) {
+#ifdef DEBUGBUILD
+ OM_uint32 maj =
+#endif
+ gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER);
+ DEBUGASSERT(maj == GSS_S_COMPLETE);
+ }
+}
+
+struct Curl_sec_client_mech Curl_krb5_client_mech = {
+ "GSSAPI",
+ sizeof(gss_ctx_id_t),
+ krb5_init,
+ krb5_auth,
+ krb5_end,
+ krb5_check_prot,
+ krb5_overhead,
+ krb5_encode,
+ krb5_decode
+};
+
+#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */
diff --git a/libcurl/src/lib/ldap.c b/libcurl/src/lib/ldap.c
new file mode 100644
index 0000000..4d91282
--- /dev/null
+++ b/libcurl/src/lib/ldap.c
@@ -0,0 +1,1013 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP)
+
+/*
+ * Notice that USE_OPENLDAP is only a source code selection switch. When
+ * libcurl is built with USE_OPENLDAP defined the libcurl source code that
+ * gets compiled is the code from openldap.c, otherwise the code that gets
+ * compiled is the code from ldap.c.
+ *
+ * When USE_OPENLDAP is defined a recent version of the OpenLDAP library
+ * might be required for compilation and runtime. In order to use ancient
+ * OpenLDAP library versions, USE_OPENLDAP shall not be defined.
+ */
+
+#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */
+# include <winldap.h>
+# ifndef LDAP_VENDOR_NAME
+# error Your Platform SDK is NOT sufficient for LDAP support! \
+ Update your Platform SDK, or disable LDAP support!
+# else
+# include <winber.h>
+# endif
+#else
+# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */
+# ifdef HAVE_LBER_H
+# include <lber.h>
+# endif
+# include <ldap.h>
+# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H))
+# include <ldap_ssl.h>
+# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
+#endif
+
+/* These are macros in both <wincrypt.h> (in above <winldap.h>) and typedefs
+ * in BoringSSL's <openssl/x509.h>
+ */
+#ifdef HAVE_BORINGSSL
+# undef X509_NAME
+# undef X509_CERT_PAIR
+# undef X509_EXTENSIONS
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "sendf.h"
+#include "escape.h"
+#include "progress.h"
+#include "transfer.h"
+#include "strequal.h"
+#include "strtok.h"
+#include "curl_ldap.h"
+#include "curl_multibyte.h"
+#include "curl_base64.h"
+#include "rawstr.h"
+#include "connect.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef HAVE_LDAP_URL_PARSE
+
+/* Use our own implementation. */
+
+typedef struct {
+ char *lud_host;
+ int lud_port;
+#if defined(USE_WIN32_LDAP)
+ TCHAR *lud_dn;
+ TCHAR **lud_attrs;
+#else
+ char *lud_dn;
+ char **lud_attrs;
+#endif
+ int lud_scope;
+#if defined(USE_WIN32_LDAP)
+ TCHAR *lud_filter;
+#else
+ char *lud_filter;
+#endif
+ char **lud_exts;
+ size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the
+ "real" struct so can only be used in code
+ without HAVE_LDAP_URL_PARSE defined */
+} CURL_LDAPURLDesc;
+
+#undef LDAPURLDesc
+#define LDAPURLDesc CURL_LDAPURLDesc
+
+static int _ldap_url_parse (const struct connectdata *conn,
+ LDAPURLDesc **ludp);
+static void _ldap_free_urldesc (LDAPURLDesc *ludp);
+
+#undef ldap_free_urldesc
+#define ldap_free_urldesc _ldap_free_urldesc
+#endif
+
+#ifdef DEBUG_LDAP
+ #define LDAP_TRACE(x) do { \
+ _ldap_trace ("%u: ", __LINE__); \
+ _ldap_trace x; \
+ } WHILE_FALSE
+
+ static void _ldap_trace (const char *fmt, ...);
+#else
+ #define LDAP_TRACE(x) Curl_nop_stmt
+#endif
+
+
+static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
+
+/*
+ * LDAP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldap = {
+ "LDAP", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_ldap, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAP, /* defport */
+ CURLPROTO_LDAP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef HAVE_LDAP_SSL
+/*
+ * LDAPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldaps = {
+ "LDAPS", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_ldap, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAPS, /* defport */
+ CURLPROTO_LDAPS, /* protocol */
+ PROTOPT_SSL /* flags */
+};
+#endif
+
+
+static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ int rc = 0;
+ LDAP *server = NULL;
+ LDAPURLDesc *ludp = NULL;
+ LDAPMessage *ldapmsg = NULL;
+ LDAPMessage *entryIterator;
+ int num = 0;
+ struct SessionHandle *data=conn->data;
+ int ldap_proto = LDAP_VERSION3;
+ int ldap_ssl = 0;
+ char *val_b64 = NULL;
+ size_t val_b64_sz = 0;
+ curl_off_t dlsize = 0;
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+ struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */
+#endif
+#if defined(USE_WIN32_LDAP)
+ TCHAR *host = NULL;
+ TCHAR *user = NULL;
+ TCHAR *passwd = NULL;
+#else
+ char *host = NULL;
+ char *user = NULL;
+ char *passwd = NULL;
+#endif
+
+ *done = TRUE; /* unconditionally */
+ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
+ LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
+ infof(data, "LDAP local: %s\n", data->change.url);
+
+#ifdef HAVE_LDAP_URL_PARSE
+ rc = ldap_url_parse(data->change.url, &ludp);
+#else
+ rc = _ldap_url_parse(conn, &ludp);
+#endif
+ if(rc != 0) {
+ failf(data, "LDAP local: %s", ldap_err2string(rc));
+ result = CURLE_LDAP_INVALID_URL;
+ goto quit;
+ }
+
+ /* Get the URL scheme ( either ldap or ldaps ) */
+ if(conn->given->flags & PROTOPT_SSL)
+ ldap_ssl = 1;
+ infof(data, "LDAP local: trying to establish %s connection\n",
+ ldap_ssl ? "encrypted" : "cleartext");
+
+#if defined(USE_WIN32_LDAP)
+ host = Curl_convert_UTF8_to_tchar(conn->host.name);
+ if(!host) {
+ result = CURLE_OUT_OF_MEMORY;
+
+ goto quit;
+ }
+
+ if(conn->bits.user_passwd) {
+ user = Curl_convert_UTF8_to_tchar(conn->user);
+ passwd = Curl_convert_UTF8_to_tchar(conn->passwd);
+ if(!user || !passwd) {
+ result = CURLE_OUT_OF_MEMORY;
+
+ goto quit;
+ }
+ }
+#else
+ host = conn->host.name;
+
+ if(conn->bits.user_passwd) {
+ user = conn->user;
+ passwd = conn->passwd;
+ }
+#endif
+
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+ ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
+#endif
+ ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+
+ if(ldap_ssl) {
+#ifdef HAVE_LDAP_SSL
+#ifdef USE_WIN32_LDAP
+ /* Win32 LDAP SDK doesn't support insecure mode without CA! */
+ server = ldap_sslinit(host, (int)conn->port, 1);
+ ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
+#else
+ int ldap_option;
+ char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
+#if defined(CURL_HAS_NOVELL_LDAPSDK)
+ rc = ldapssl_client_init(NULL, NULL);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ if(data->set.ssl.verifypeer) {
+ /* Novell SDK supports DER or BASE64 files. */
+ int cert_type = LDAPSSL_CERT_FILETYPE_B64;
+ if((data->set.str[STRING_CERT_TYPE]) &&
+ (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
+ cert_type = LDAPSSL_CERT_FILETYPE_DER;
+ if(!ldap_ca) {
+ failf(data, "LDAP local: ERROR %s CA cert not set!",
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ infof(data, "LDAP local: using %s CA cert '%s'\n",
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
+ ldap_ca);
+ rc = ldapssl_add_trusted_cert(ldap_ca, cert_type);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting %s CA cert: %s",
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
+ ldap_err2string(rc));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ ldap_option = LDAPSSL_VERIFY_SERVER;
+ }
+ else
+ ldap_option = LDAPSSL_VERIFY_NONE;
+ rc = ldapssl_set_verify_mode(ldap_option);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting cert verify mode: %s",
+ ldap_err2string(rc));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ server = ldapssl_init(host, (int)conn->port, 1);
+ if(server == NULL) {
+ failf(data, "LDAP local: Cannot connect to %s:%ld",
+ conn->host.dispname, conn->port);
+ result = CURLE_COULDNT_CONNECT;
+ goto quit;
+ }
+#elif defined(LDAP_OPT_X_TLS)
+ if(data->set.ssl.verifypeer) {
+ /* OpenLDAP SDK supports BASE64 files. */
+ if((data->set.str[STRING_CERT_TYPE]) &&
+ (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
+ failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ if(!ldap_ca) {
+ failf(data, "LDAP local: ERROR PEM CA cert not set!");
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca);
+ rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting PEM CA cert: %s",
+ ldap_err2string(rc));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ ldap_option = LDAP_OPT_X_TLS_DEMAND;
+ }
+ else
+ ldap_option = LDAP_OPT_X_TLS_NEVER;
+
+ rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting cert verify mode: %s",
+ ldap_err2string(rc));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ server = ldap_init(host, (int)conn->port);
+ if(server == NULL) {
+ failf(data, "LDAP local: Cannot connect to %s:%ld",
+ conn->host.dispname, conn->port);
+ result = CURLE_COULDNT_CONNECT;
+ goto quit;
+ }
+ ldap_option = LDAP_OPT_X_TLS_HARD;
+ rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s",
+ ldap_err2string(rc));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+/*
+ rc = ldap_start_tls_s(server, NULL, NULL);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s",
+ ldap_err2string(rc));
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+*/
+#else
+ /* we should probably never come up to here since configure
+ should check in first place if we can support LDAP SSL/TLS */
+ failf(data, "LDAP local: SSL/TLS not supported with this version "
+ "of the OpenLDAP toolkit\n");
+ result = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+#endif
+#endif
+#endif /* CURL_LDAP_USE_SSL */
+ }
+ else {
+ server = ldap_init(host, (int)conn->port);
+ if(server == NULL) {
+ failf(data, "LDAP local: Cannot connect to %s:%ld",
+ conn->host.dispname, conn->port);
+ result = CURLE_COULDNT_CONNECT;
+ goto quit;
+ }
+ }
+#ifdef USE_WIN32_LDAP
+ ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+#endif
+
+ rc = ldap_simple_bind_s(server, user, passwd);
+ if(!ldap_ssl && rc != 0) {
+ ldap_proto = LDAP_VERSION2;
+ ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+ rc = ldap_simple_bind_s(server, user, passwd);
+ }
+ if(rc != 0) {
+ failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
+ result = CURLE_LDAP_CANNOT_BIND;
+ goto quit;
+ }
+
+ rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
+ ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
+
+ if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
+ failf(data, "LDAP remote: %s", ldap_err2string(rc));
+ result = CURLE_LDAP_SEARCH_FAILED;
+ goto quit;
+ }
+
+ for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg);
+ entryIterator;
+ entryIterator = ldap_next_entry(server, entryIterator), num++) {
+ BerElement *ber = NULL;
+#if defined(USE_WIN32_LDAP)
+ TCHAR *attribute;
+#else
+ char *attribute; /*! suspicious that this isn't 'const' */
+#endif
+ int i;
+
+ /* Get the DN and write it to the client */
+ {
+ char *name;
+ size_t name_len;
+#if defined(USE_WIN32_LDAP)
+ TCHAR *dn = ldap_get_dn(server, entryIterator);
+ name = Curl_convert_tchar_to_UTF8(dn);
+ if(!name) {
+ ldap_memfree(dn);
+
+ result = CURLE_OUT_OF_MEMORY;
+
+ goto quit;
+ }
+#else
+ char *dn = name = ldap_get_dn(server, entryIterator);
+#endif
+ name_len = strlen(name);
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ if(result) {
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(name);
+#endif
+ ldap_memfree(dn);
+
+ goto quit;
+ }
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name,
+ name_len);
+ if(result) {
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(name);
+#endif
+ ldap_memfree(dn);
+
+ goto quit;
+ }
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(result) {
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(name);
+#endif
+ ldap_memfree(dn);
+
+ goto quit;
+ }
+
+ dlsize += name_len + 5;
+
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(name);
+#endif
+ ldap_memfree(dn);
+ }
+
+ /* Get the attributes and write them to the client */
+ for(attribute = ldap_first_attribute(server, entryIterator, &ber);
+ attribute;
+ attribute = ldap_next_attribute(server, entryIterator, ber)) {
+ BerValue **vals;
+ size_t attr_len;
+#if defined(USE_WIN32_LDAP)
+ char *attr = Curl_convert_tchar_to_UTF8(attribute);
+ if(!attr) {
+ if(ber)
+ ber_free(ber, 0);
+
+ result = CURLE_OUT_OF_MEMORY;
+
+ goto quit;
+ }
+#else
+ char *attr = attribute;
+#endif
+ attr_len = strlen(attr);
+
+ vals = ldap_get_values_len(server, entryIterator, attribute);
+ if(vals != NULL) {
+ for(i = 0; (vals[i] != NULL); i++) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ if(result) {
+ ldap_value_free_len(vals);
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+ if(ber)
+ ber_free(ber, 0);
+
+ goto quit;
+ }
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ (char *) attr, attr_len);
+ if(result) {
+ ldap_value_free_len(vals);
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+ if(ber)
+ ber_free(ber, 0);
+
+ goto quit;
+ }
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
+ if(result) {
+ ldap_value_free_len(vals);
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+ if(ber)
+ ber_free(ber, 0);
+
+ goto quit;
+ }
+
+ dlsize += attr_len + 3;
+
+ if((attr_len > 7) &&
+ (strcmp(";binary", (char *) attr + (attr_len - 7)) == 0)) {
+ /* Binary attribute, encode to base64. */
+ result = Curl_base64_encode(data,
+ vals[i]->bv_val,
+ vals[i]->bv_len,
+ &val_b64,
+ &val_b64_sz);
+ if(result) {
+ ldap_value_free_len(vals);
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+ if(ber)
+ ber_free(ber, 0);
+
+ goto quit;
+ }
+
+ if(val_b64_sz > 0) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
+ val_b64_sz);
+ free(val_b64);
+ if(result) {
+ ldap_value_free_len(vals);
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+ if(ber)
+ ber_free(ber, 0);
+
+ goto quit;
+ }
+
+ dlsize += val_b64_sz;
+ }
+ }
+ else {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
+ vals[i]->bv_len);
+ if(result) {
+ ldap_value_free_len(vals);
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+ if(ber)
+ ber_free(ber, 0);
+
+ goto quit;
+ }
+
+ dlsize += vals[i]->bv_len;
+ }
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(result) {
+ ldap_value_free_len(vals);
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+ if(ber)
+ ber_free(ber, 0);
+
+ goto quit;
+ }
+
+ dlsize++;
+ }
+
+ /* Free memory used to store values */
+ ldap_value_free_len(vals);
+ }
+
+ /* Free the attribute as we are done with it */
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(attr);
+#endif
+ ldap_memfree(attribute);
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(result)
+ goto quit;
+ dlsize++;
+ Curl_pgrsSetDownloadCounter(data, dlsize);
+ }
+
+ if(ber)
+ ber_free(ber, 0);
+ }
+
+quit:
+ if(ldapmsg) {
+ ldap_msgfree(ldapmsg);
+ LDAP_TRACE (("Received %d entries\n", num));
+ }
+ if(rc == LDAP_SIZELIMIT_EXCEEDED)
+ infof(data, "There are more than %d entries\n", num);
+ if(ludp)
+ ldap_free_urldesc(ludp);
+ if(server)
+ ldap_unbind_s(server);
+#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK)
+ if(ldap_ssl)
+ ldapssl_client_deinit();
+#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
+
+#if defined(USE_WIN32_LDAP)
+ Curl_unicodefree(passwd);
+ Curl_unicodefree(user);
+ Curl_unicodefree(host);
+#endif
+
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ connclose(conn, "LDAP connection always disable re-use");
+
+ return result;
+}
+
+#ifdef DEBUG_LDAP
+static void _ldap_trace (const char *fmt, ...)
+{
+ static int do_trace = -1;
+ va_list args;
+
+ if(do_trace == -1) {
+ const char *env = getenv("CURL_TRACE");
+ do_trace = (env && strtol(env, NULL, 10) > 0);
+ }
+ if(!do_trace)
+ return;
+
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ va_end (args);
+}
+#endif
+
+#ifndef HAVE_LDAP_URL_PARSE
+
+/*
+ * Return scope-value for a scope-string.
+ */
+static int str2scope (const char *p)
+{
+ if(strequal(p, "one"))
+ return LDAP_SCOPE_ONELEVEL;
+ if(strequal(p, "onetree"))
+ return LDAP_SCOPE_ONELEVEL;
+ if(strequal(p, "base"))
+ return LDAP_SCOPE_BASE;
+ if(strequal(p, "sub"))
+ return LDAP_SCOPE_SUBTREE;
+ if(strequal( p, "subtree"))
+ return LDAP_SCOPE_SUBTREE;
+ return (-1);
+}
+
+/*
+ * Split 'str' into strings separated by commas.
+ * Note: out[] points into 'str'.
+ */
+static bool split_str(char *str, char ***out, size_t *count)
+{
+ char **res;
+ char *lasts;
+ char *s;
+ size_t i;
+ size_t items = 1;
+
+ s = strchr(str, ',');
+ while(s) {
+ items++;
+ s = strchr(++s, ',');
+ }
+
+ res = calloc(items, sizeof(char *));
+ if(!res)
+ return FALSE;
+
+ for(i = 0, s = strtok_r(str, ",", &lasts); s && i < items;
+ s = strtok_r(NULL, ",", &lasts), i++)
+ res[i] = s;
+
+ *out = res;
+ *count = items;
+
+ return TRUE;
+}
+
+/*
+ * Break apart the pieces of an LDAP URL.
+ * Syntax:
+ * ldap://<hostname>:<port>/<base_dn>?<attributes>?<scope>?<filter>?<ext>
+ *
+ * <hostname> already known from 'conn->host.name'.
+ * <port> already known from 'conn->remote_port'.
+ * extract the rest from 'conn->data->state.path+1'. All fields are optional.
+ * e.g.
+ * ldap://<hostname>:<port>/?<attributes>?<scope>?<filter>
+ * yields ludp->lud_dn = "".
+ *
+ * Defined in RFC4516 section 2.
+ */
+static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
+{
+ int rc = LDAP_SUCCESS;
+ char *path;
+ char *p;
+ char *q;
+ size_t i;
+
+ if(!conn->data ||
+ !conn->data->state.path ||
+ conn->data->state.path[0] != '/' ||
+ !checkprefix("LDAP", conn->data->change.url))
+ return LDAP_INVALID_SYNTAX;
+
+ ludp->lud_scope = LDAP_SCOPE_BASE;
+ ludp->lud_port = conn->remote_port;
+ ludp->lud_host = conn->host.name;
+
+ /* Duplicate the path */
+ p = path = strdup(conn->data->state.path + 1);
+ if(!path)
+ return LDAP_NO_MEMORY;
+
+ /* Parse the DN (Distinguished Name) */
+ q = strchr(p, '?');
+ if(q)
+ *q++ = '\0';
+
+ if(*p) {
+ char *dn = p;
+ char *unescaped;
+
+ LDAP_TRACE (("DN '%s'\n", dn));
+
+ /* Unescape the DN */
+ unescaped = curl_easy_unescape(conn->data, dn, 0, NULL);
+ if(!unescaped) {
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+
+#if defined(USE_WIN32_LDAP)
+ /* Convert the unescaped string to a tchar */
+ ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped);
+
+ /* Free the unescaped string as we are done with it */
+ Curl_unicodefree(unescaped);
+
+ if(!ludp->lud_dn) {
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+#else
+ ludp->lud_dn = unescaped;
+#endif
+ }
+
+ p = q;
+ if(!p)
+ goto quit;
+
+ /* Parse the attributes. skip "??" */
+ q = strchr(p, '?');
+ if(q)
+ *q++ = '\0';
+
+ if(*p) {
+ char **attributes;
+ size_t count = 0;
+
+ /* Split the string into an array of attributes */
+ if(!split_str(p, &attributes, &count)) {
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+
+ /* Allocate our array (+1 for the NULL entry) */
+#if defined(USE_WIN32_LDAP)
+ ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *));
+#else
+ ludp->lud_attrs = calloc(count + 1, sizeof(char *));
+#endif
+ if(!ludp->lud_attrs) {
+ free(attributes);
+
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+
+ for(i = 0; i < count; i++) {
+ char *unescaped;
+
+ LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i]));
+
+ /* Unescape the attribute */
+ unescaped = curl_easy_unescape(conn->data, attributes[i], 0, NULL);
+ if(!unescaped) {
+ free(attributes);
+
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+
+#if defined(USE_WIN32_LDAP)
+ /* Convert the unescaped string to a tchar */
+ ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped);
+
+ /* Free the unescaped string as we are done with it */
+ Curl_unicodefree(unescaped);
+
+ if(!ludp->lud_attrs[i]) {
+ free(attributes);
+
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+#else
+ ludp->lud_attrs[i] = unescaped;
+#endif
+
+ ludp->lud_attrs_dups++;
+ }
+
+ free(attributes);
+ }
+
+ p = q;
+ if(!p)
+ goto quit;
+
+ /* Parse the scope. skip "??" */
+ q = strchr(p, '?');
+ if(q)
+ *q++ = '\0';
+
+ if(*p) {
+ ludp->lud_scope = str2scope(p);
+ if(ludp->lud_scope == -1) {
+ rc = LDAP_INVALID_SYNTAX;
+
+ goto quit;
+ }
+ LDAP_TRACE (("scope %d\n", ludp->lud_scope));
+ }
+
+ p = q;
+ if(!p)
+ goto quit;
+
+ /* Parse the filter */
+ q = strchr(p, '?');
+ if(q)
+ *q++ = '\0';
+
+ if(*p) {
+ char *filter = p;
+ char *unescaped;
+
+ LDAP_TRACE (("filter '%s'\n", filter));
+
+ /* Unescape the filter */
+ unescaped = curl_easy_unescape(conn->data, filter, 0, NULL);
+ if(!unescaped) {
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+
+#if defined(USE_WIN32_LDAP)
+ /* Convert the unescaped string to a tchar */
+ ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped);
+
+ /* Free the unescaped string as we are done with it */
+ Curl_unicodefree(unescaped);
+
+ if(!ludp->lud_filter) {
+ rc = LDAP_NO_MEMORY;
+
+ goto quit;
+ }
+#else
+ ludp->lud_filter = unescaped;
+#endif
+ }
+
+ p = q;
+ if(p && !*p) {
+ rc = LDAP_INVALID_SYNTAX;
+
+ goto quit;
+ }
+
+quit:
+ free(path);
+
+ return rc;
+}
+
+static int _ldap_url_parse (const struct connectdata *conn,
+ LDAPURLDesc **ludpp)
+{
+ LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
+ int rc;
+
+ *ludpp = NULL;
+ if(!ludp)
+ return LDAP_NO_MEMORY;
+
+ rc = _ldap_url_parse2 (conn, ludp);
+ if(rc != LDAP_SUCCESS) {
+ _ldap_free_urldesc(ludp);
+ ludp = NULL;
+ }
+ *ludpp = ludp;
+ return (rc);
+}
+
+static void _ldap_free_urldesc (LDAPURLDesc *ludp)
+{
+ size_t i;
+
+ if(!ludp)
+ return;
+
+ free(ludp->lud_dn);
+ free(ludp->lud_filter);
+
+ if(ludp->lud_attrs) {
+ for(i = 0; i < ludp->lud_attrs_dups; i++)
+ free(ludp->lud_attrs[i]);
+ free(ludp->lud_attrs);
+ }
+
+ free (ludp);
+}
+#endif /* !HAVE_LDAP_URL_PARSE */
+#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */
diff --git a/libcurl/src/lib/libcurl.rc b/libcurl/src/lib/libcurl.rc
new file mode 100644
index 0000000..47b944a
--- /dev/null
+++ b/libcurl/src/lib/libcurl.rc
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include <winver.h>
+#include "../include/curl/curlver.h"
+
+LANGUAGE 0x09,0x01
+
+#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RC_VERSION
+ PRODUCTVERSION RC_VERSION
+ FILEFLAGSMASK 0x3fL
+#if defined(DEBUGBUILD) || defined(_DEBUG)
+ FILEFLAGS 1
+#else
+ FILEFLAGS 0
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "The cURL library, http://curl.haxx.se/\0"
+ VALUE "FileDescription", "libcurl Shared Library\0"
+ VALUE "FileVersion", LIBCURL_VERSION "\0"
+ VALUE "InternalName", "libcurl\0"
+ VALUE "OriginalFilename", "libcurl.dll\0"
+ VALUE "ProductName", "The cURL library\0"
+ VALUE "ProductVersion", LIBCURL_VERSION "\0"
+ VALUE "LegalCopyright", " " LIBCURL_COPYRIGHT "\0"
+ VALUE "License", "http://curl.haxx.se/docs/copyright.html\0"
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/libcurl/src/lib/llist.c b/libcurl/src/lib/llist.c
new file mode 100644
index 0000000..9e6e6ce
--- /dev/null
+++ b/libcurl/src/lib/llist.c
@@ -0,0 +1,212 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "llist.h"
+#include "curl_memory.h"
+
+/* this must be the last include file */
+#include "memdebug.h"
+
+/*
+ * @unittest: 1300
+ */
+static void
+llist_init(struct curl_llist *l, curl_llist_dtor dtor)
+{
+ l->size = 0;
+ l->dtor = dtor;
+ l->head = NULL;
+ l->tail = NULL;
+}
+
+CURL_STATIC struct curl_llist *
+Curl_llist_alloc(curl_llist_dtor dtor)
+{
+ struct curl_llist *list;
+
+ list = malloc(sizeof(struct curl_llist));
+ if(!list)
+ return NULL;
+
+ llist_init(list, dtor);
+
+ return list;
+}
+
+/*
+ * Curl_llist_insert_next()
+ *
+ * Inserts a new list element after the given one 'e'. If the given existing
+ * entry is NULL and the list already has elements, the new one will be
+ * inserted first in the list.
+ *
+ * Returns: 1 on success and 0 on failure.
+ *
+ * @unittest: 1300
+ */
+CURL_STATIC int
+Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
+ const void *p)
+{
+ struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element));
+ if(!ne)
+ return 0;
+
+ ne->ptr = (void *) p;
+ if(list->size == 0) {
+ list->head = ne;
+ list->head->prev = NULL;
+ list->head->next = NULL;
+ list->tail = ne;
+ }
+ else {
+ /* if 'e' is NULL here, we insert the new element first in the list */
+ ne->next = e?e->next:list->head;
+ ne->prev = e;
+ if(!e) {
+ list->head->prev = ne;
+ list->head = ne;
+ }
+ else if(e->next) {
+ e->next->prev = ne;
+ }
+ else {
+ list->tail = ne;
+ }
+ if(e)
+ e->next = ne;
+ }
+
+ ++list->size;
+
+ return 1;
+}
+
+/*
+ * @unittest: 1300
+ */
+CURL_STATIC int
+Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
+ void *user)
+{
+ if(e == NULL || list->size == 0)
+ return 1;
+
+ if(e == list->head) {
+ list->head = e->next;
+
+ if(list->head == NULL)
+ list->tail = NULL;
+ else
+ e->next->prev = NULL;
+ }
+ else {
+ e->prev->next = e->next;
+ if(!e->next)
+ list->tail = e->prev;
+ else
+ e->next->prev = e->prev;
+ }
+
+ list->dtor(user, e->ptr);
+
+ e->ptr = NULL;
+ e->prev = NULL;
+ e->next = NULL;
+
+ free(e);
+ --list->size;
+
+ return 1;
+}
+
+CURL_STATIC void
+Curl_llist_destroy(struct curl_llist *list, void *user)
+{
+ if(list) {
+ while(list->size > 0)
+ Curl_llist_remove(list, list->tail, user);
+
+ free(list);
+ }
+}
+
+CURL_STATIC size_t
+Curl_llist_count(struct curl_llist *list)
+{
+ return list->size;
+}
+
+/*
+ * @unittest: 1300
+ */
+CURL_STATIC int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
+ struct curl_llist *to_list,
+ struct curl_llist_element *to_e)
+{
+ /* Remove element from list */
+ if(e == NULL || list->size == 0)
+ return 0;
+
+ if(e == list->head) {
+ list->head = e->next;
+
+ if(list->head == NULL)
+ list->tail = NULL;
+ else
+ e->next->prev = NULL;
+ }
+ else {
+ e->prev->next = e->next;
+ if(!e->next)
+ list->tail = e->prev;
+ else
+ e->next->prev = e->prev;
+ }
+
+ --list->size;
+
+ /* Add element to to_list after to_e */
+ if(to_list->size == 0) {
+ to_list->head = e;
+ to_list->head->prev = NULL;
+ to_list->head->next = NULL;
+ to_list->tail = e;
+ }
+ else {
+ e->next = to_e->next;
+ e->prev = to_e;
+ if(to_e->next) {
+ to_e->next->prev = e;
+ }
+ else {
+ to_list->tail = e;
+ }
+ to_e->next = e;
+ }
+
+ ++to_list->size;
+
+ return 1;
+}
diff --git a/libcurl/src/lib/llist.h b/libcurl/src/lib/llist.h
new file mode 100644
index 0000000..85915b0
--- /dev/null
+++ b/libcurl/src/lib/llist.h
@@ -0,0 +1,57 @@
+#ifndef HEADER_CURL_LLIST_H
+#define HEADER_CURL_LLIST_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include <stddef.h>
+
+typedef void (*curl_llist_dtor)(void *, void *);
+
+struct curl_llist_element {
+ void *ptr;
+
+ struct curl_llist_element *prev;
+ struct curl_llist_element *next;
+};
+
+struct curl_llist {
+ struct curl_llist_element *head;
+ struct curl_llist_element *tail;
+
+ curl_llist_dtor dtor;
+
+ size_t size;
+};
+
+CURL_STATIC struct curl_llist *Curl_llist_alloc(curl_llist_dtor);
+CURL_STATIC int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
+ const void *);
+CURL_STATIC int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
+ void *);
+CURL_STATIC size_t Curl_llist_count(struct curl_llist *);
+CURL_STATIC void Curl_llist_destroy(struct curl_llist *, void *);
+CURL_STATIC int Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
+ struct curl_llist *, struct curl_llist_element *);
+
+#endif /* HEADER_CURL_LLIST_H */
+
diff --git a/libcurl/src/lib/md4.c b/libcurl/src/lib/md4.c
new file mode 100644
index 0000000..700f832
--- /dev/null
+++ b/libcurl/src/lib/md4.c
@@ -0,0 +1,304 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD4 Message-Digest Algorithm (RFC 1320).
+ *
+ * Homepage:
+ http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain. In case
+ * this attempt to disclaim copyright and place the software in the public
+ * domain is deemed null and void, then the software is Copyright (c) 2001
+ * Alexander Peslyak and it is hereby released to the general public under the
+ * following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's. No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible. Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
+
+#include "curl_setup.h"
+
+/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
+ * that we have a local implementation of it */
+#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
+
+#include "curl_md4.h"
+#include "warnless.h"
+
+#ifndef HAVE_OPENSSL
+
+#include <string.h>
+
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef unsigned int MD4_u32plus;
+
+typedef struct {
+ MD4_u32plus lo, hi;
+ MD4_u32plus a, b, c, d;
+ unsigned char buffer[64];
+ MD4_u32plus block[16];
+} MD4_CTX;
+
+static void MD4_Init(MD4_CTX *ctx);
+static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
+static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
+
+/*
+ * The basic MD4 functions.
+ *
+ * F and G are optimized compared to their RFC 1320 definitions, with the
+ * optimization for F borrowed from Colin Plumb's MD5 implementation.
+ */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/*
+ * The MD4 transformation for all three rounds.
+ */
+#define STEP(f, a, b, c, d, x, s) \
+ (a) += f((b), (c), (d)) + (x); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them
+ * in a properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned
+ * memory accesses is just an optimization. Nothing will break if it
+ * doesn't work.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+ (*(MD4_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+#else
+#define SET(n) \
+ (ctx->block[(n)] = \
+ (MD4_u32plus)ptr[(n) * 4] | \
+ ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
+ ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
+ ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+ (ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update
+ * the bit counters. There are no alignment requirements.
+ */
+static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
+{
+ const unsigned char *ptr;
+ MD4_u32plus a, b, c, d;
+ MD4_u32plus saved_a, saved_b, saved_c, saved_d;
+
+ ptr = (const unsigned char *)data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+/* Round 1 */
+ STEP(F, a, b, c, d, SET(0), 3)
+ STEP(F, d, a, b, c, SET(1), 7)
+ STEP(F, c, d, a, b, SET(2), 11)
+ STEP(F, b, c, d, a, SET(3), 19)
+ STEP(F, a, b, c, d, SET(4), 3)
+ STEP(F, d, a, b, c, SET(5), 7)
+ STEP(F, c, d, a, b, SET(6), 11)
+ STEP(F, b, c, d, a, SET(7), 19)
+ STEP(F, a, b, c, d, SET(8), 3)
+ STEP(F, d, a, b, c, SET(9), 7)
+ STEP(F, c, d, a, b, SET(10), 11)
+ STEP(F, b, c, d, a, SET(11), 19)
+ STEP(F, a, b, c, d, SET(12), 3)
+ STEP(F, d, a, b, c, SET(13), 7)
+ STEP(F, c, d, a, b, SET(14), 11)
+ STEP(F, b, c, d, a, SET(15), 19)
+
+/* Round 2 */
+ STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
+ STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
+ STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
+ STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
+ STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
+ STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
+ STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
+ STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
+ STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
+ STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
+ STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
+ STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
+ STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
+ STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
+ STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
+ STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
+
+/* Round 3 */
+ STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
+ STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
+ STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
+ STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
+ STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
+ STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
+ STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
+ STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
+ STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
+ STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
+ STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
+ STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
+ STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
+ STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
+ STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
+ STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while(size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
+}
+
+static void MD4_Init(MD4_CTX *ctx)
+{
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
+
+static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
+{
+ MD4_u32plus saved_lo;
+ unsigned long used, available;
+
+ saved_lo = ctx->lo;
+ if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += (MD4_u32plus)size >> 29;
+
+ used = saved_lo & 0x3f;
+
+ if(used) {
+ available = 64 - used;
+
+ if(size < available) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
+ body(ctx, ctx->buffer, 64);
+ }
+
+ if(size >= 64) {
+ data = body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
+
+ memcpy(ctx->buffer, data, size);
+}
+
+static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
+{
+ unsigned long used, available;
+
+ used = ctx->lo & 0x3f;
+
+ ctx->buffer[used++] = 0x80;
+
+ available = 64 - used;
+
+ if(available < 8) {
+ memset(&ctx->buffer[used], 0, available);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ available = 64;
+ }
+
+ memset(&ctx->buffer[used], 0, available - 8);
+
+ ctx->lo <<= 3;
+ ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
+ ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
+ ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
+ ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff);
+ ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
+ ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
+ ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
+ ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
+
+ body(ctx, ctx->buffer, 64);
+
+ result[0] = curlx_ultouc((ctx->a)&0xff);
+ result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
+ result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
+ result[3] = curlx_ultouc(ctx->a >> 24);
+ result[4] = curlx_ultouc((ctx->b)&0xff);
+ result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
+ result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
+ result[7] = curlx_ultouc(ctx->b >> 24);
+ result[8] = curlx_ultouc((ctx->c)&0xff);
+ result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
+ result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
+ result[11] = curlx_ultouc(ctx->c >> 24);
+ result[12] = curlx_ultouc((ctx->d)&0xff);
+ result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
+ result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
+ result[15] = curlx_ultouc(ctx->d >> 24);
+
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+#endif
+
+CURL_STATIC void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
+{
+ MD4_CTX ctx;
+ MD4_Init(&ctx);
+ MD4_Update(&ctx, input, curlx_uztoui(len));
+ MD4_Final(output, &ctx);
+}
+#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
diff --git a/libcurl/src/lib/md5.c b/libcurl/src/lib/md5.c
new file mode 100644
index 0000000..efed3b8
--- /dev/null
+++ b/libcurl/src/lib/md5.c
@@ -0,0 +1,560 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+#include "curl_md5.h"
+#include "curl_hmac.h"
+#include "warnless.h"
+
+#if defined(USE_GNUTLS_NETTLE)
+
+#include <nettle/md5.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef struct md5_ctx MD5_CTX;
+
+static void MD5_Init(MD5_CTX * ctx)
+{
+ md5_init(ctx);
+}
+
+static void MD5_Update(MD5_CTX * ctx,
+ const unsigned char * input,
+ unsigned int inputLen)
+{
+ md5_update(ctx, inputLen, input);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+{
+ md5_digest(ctx, 16, digest);
+}
+
+#elif defined(USE_GNUTLS)
+
+#include <gcrypt.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef gcry_md_hd_t MD5_CTX;
+
+static void MD5_Init(MD5_CTX * ctx)
+{
+ gcry_md_open(ctx, GCRY_MD_MD5, 0);
+}
+
+static void MD5_Update(MD5_CTX * ctx,
+ const unsigned char * input,
+ unsigned int inputLen)
+{
+ gcry_md_write(*ctx, input, inputLen);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+{
+ memcpy(digest, gcry_md_read(*ctx, 0), 16);
+ gcry_md_close(*ctx);
+}
+
+#elif defined(USE_OPENSSL)
+/* When OpenSSL is available we use the MD5-function from OpenSSL */
+#include <openssl/md5.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
+
+/* For Apple operating systems: CommonCrypto has the functions we need.
+ These functions are available on Tiger and later, as well as iOS 2.0
+ and later. If you're building for an older cat, well, sorry.
+
+ Declaring the functions as static like this seems to be a bit more
+ reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
+# include <CommonCrypto/CommonDigest.h>
+# define MD5_CTX CC_MD5_CTX
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void MD5_Init(MD5_CTX *ctx)
+{
+ CC_MD5_Init(ctx);
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ CC_MD5_Update(ctx, input, inputLen);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ CC_MD5_Final(digest, ctx);
+}
+
+#elif defined(_WIN32)
+
+#include <wincrypt.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef struct {
+ HCRYPTPROV hCryptProv;
+ HCRYPTHASH hHash;
+} MD5_CTX;
+
+static void MD5_Init(MD5_CTX *ctx)
+{
+ if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
+ }
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ unsigned long length = 0;
+ CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
+ if(length == 16)
+ CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
+ if(ctx->hHash)
+ CryptDestroyHash(ctx->hHash);
+ if(ctx->hCryptProv)
+ CryptReleaseContext(ctx->hCryptProv, 0);
+}
+
+#elif defined(USE_AXTLS)
+#include <axTLS/config.h>
+#include <axTLS/os_int.h>
+#include <axTLS/crypto.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+#else
+/* When no other crypto library is available we use this code segment */
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's. No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible. Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
+
+#include <string.h>
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef unsigned int MD5_u32plus;
+
+typedef struct {
+ MD5_u32plus lo, hi;
+ MD5_u32plus a, b, c, d;
+ unsigned char buffer[64];
+ MD5_u32plus block[16];
+} MD5_CTX;
+
+static void MD5_Init(MD5_CTX *ctx);
+static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
+static void MD5_Final(unsigned char *result, MD5_CTX *ctx);
+
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z) (((x) ^ (y)) ^ (z))
+#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+ (a) += f((b), (c), (d)) + (x) + (t); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+ (a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them
+ * in a properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned
+ * memory accesses is just an optimization. Nothing will break if it
+ * doesn't work.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+ (*(MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+#else
+#define SET(n) \
+ (ctx->block[(n)] = \
+ (MD5_u32plus)ptr[(n) * 4] | \
+ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+ (ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update
+ * the bit counters. There are no alignment requirements.
+ */
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ const unsigned char *ptr;
+ MD5_u32plus a, b, c, d;
+ MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+ ptr = (const unsigned char *)data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+/* Round 1 */
+ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+ STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+ STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+ STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+ STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+ STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+ STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+ STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+ STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+ STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+ STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+ STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+ STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+ STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+ STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+ STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+/* Round 2 */
+ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+ STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+ STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+ STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+ STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+ STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+ STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+ STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+ STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+ STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+ STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+ STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+ STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+ STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+ STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+ STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+/* Round 3 */
+ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+ STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+ STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+ STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+ STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+ STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+ STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+ STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+ STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+ STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+ STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+ STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+ STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+ STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+ STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+ STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+/* Round 4 */
+ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+ STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+ STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+ STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+ STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+ STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+ STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+ STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+ STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+ STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+ STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+ STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+ STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+ STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+ STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+ STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while(size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
+}
+
+static void MD5_Init(MD5_CTX *ctx)
+{
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
+
+static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ MD5_u32plus saved_lo;
+ unsigned long used, available;
+
+ saved_lo = ctx->lo;
+ if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += (MD5_u32plus)size >> 29;
+
+ used = saved_lo & 0x3f;
+
+ if(used) {
+ available = 64 - used;
+
+ if(size < available) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
+ body(ctx, ctx->buffer, 64);
+ }
+
+ if(size >= 64) {
+ data = body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
+
+ memcpy(ctx->buffer, data, size);
+}
+
+static void MD5_Final(unsigned char *result, MD5_CTX *ctx)
+{
+ unsigned long used, available;
+
+ used = ctx->lo & 0x3f;
+
+ ctx->buffer[used++] = 0x80;
+
+ available = 64 - used;
+
+ if(available < 8) {
+ memset(&ctx->buffer[used], 0, available);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ available = 64;
+ }
+
+ memset(&ctx->buffer[used], 0, available - 8);
+
+ ctx->lo <<= 3;
+ ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
+ ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
+ ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
+ ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
+ ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
+ ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
+ ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
+ ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
+
+ body(ctx, ctx->buffer, 64);
+
+ result[0] = curlx_ultouc((ctx->a)&0xff);
+ result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
+ result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
+ result[3] = curlx_ultouc(ctx->a >> 24);
+ result[4] = curlx_ultouc((ctx->b)&0xff);
+ result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
+ result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
+ result[7] = curlx_ultouc(ctx->b >> 24);
+ result[8] = curlx_ultouc((ctx->c)&0xff);
+ result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
+ result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
+ result[11] = curlx_ultouc(ctx->c >> 24);
+ result[12] = curlx_ultouc((ctx->d)&0xff);
+ result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
+ result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
+ result[15] = curlx_ultouc(ctx->d >> 24);
+
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+#endif /* CRYPTO LIBS */
+
+const HMAC_params Curl_HMAC_MD5[] = {
+ {
+ (HMAC_hinit_func) MD5_Init, /* Hash initialization function. */
+ (HMAC_hupdate_func) MD5_Update, /* Hash update function. */
+ (HMAC_hfinal_func) MD5_Final, /* Hash computation end function. */
+ sizeof(MD5_CTX), /* Size of hash context structure. */
+ 64, /* Maximum key length. */
+ 16 /* Result size. */
+ }
+};
+
+const MD5_params Curl_DIGEST_MD5[] = {
+ {
+ (Curl_MD5_init_func) MD5_Init, /* Digest initialization function */
+ (Curl_MD5_update_func) MD5_Update, /* Digest update function */
+ (Curl_MD5_final_func) MD5_Final, /* Digest computation end function */
+ sizeof(MD5_CTX), /* Size of digest context struct */
+ 16 /* Result size */
+ }
+};
+
+/*
+ * @unittest: 1601
+ */
+CURL_STATIC void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
+ const unsigned char *input)
+{
+ MD5_CTX ctx;
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
+ MD5_Final(outbuffer, &ctx);
+}
+
+CURL_STATIC MD5_context *Curl_MD5_init(const MD5_params *md5params)
+{
+ MD5_context *ctxt;
+
+ /* Create MD5 context */
+ ctxt = malloc(sizeof *ctxt);
+
+ if(!ctxt)
+ return ctxt;
+
+ ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize);
+
+ if(!ctxt->md5_hashctx) {
+ free(ctxt);
+ return NULL;
+ }
+
+ ctxt->md5_hash = md5params;
+
+ (*md5params->md5_init_func)(ctxt->md5_hashctx);
+
+ return ctxt;
+}
+
+CURL_STATIC int Curl_MD5_update(MD5_context *context,
+ const unsigned char *data,
+ unsigned int len)
+{
+ (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
+
+ return 0;
+}
+
+CURL_STATIC int Curl_MD5_final(MD5_context *context, unsigned char *result)
+{
+ (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
+
+ free(context->md5_hashctx);
+ free(context);
+
+ return 0;
+}
+
+#endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/libcurl/src/lib/memdebug.c b/libcurl/src/lib/memdebug.c
new file mode 100644
index 0000000..3b38a74
--- /dev/null
+++ b/libcurl/src/lib/memdebug.c
@@ -0,0 +1,489 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURLDEBUG
+
+#include <curl/curl.h>
+
+#include "curl_printf.h"
+#include "urldata.h"
+
+#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef HAVE_ASSERT_H
+# define assert(x) Curl_nop_stmt
+#endif
+
+/*
+ * Until 2011-08-17 libcurl's Memory Tracking feature also performed
+ * automatic malloc and free filling operations using 0xA5 and 0x13
+ * values. Our own preinitialization of dynamically allocated memory
+ * might be useful when not using third party memory debuggers, but
+ * on the other hand this would fool memory debuggers into thinking
+ * that all dynamically allocated memory is properly initialized.
+ *
+ * As a default setting, libcurl's Memory Tracking feature no longer
+ * performs preinitialization of dynamically allocated memory on its
+ * own. If you know what you are doing, and really want to retain old
+ * behavior, you can achieve this compiling with preprocessor symbols
+ * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate
+ * values.
+ */
+
+#ifdef CURL_MT_MALLOC_FILL
+# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff)
+# error "invalid CURL_MT_MALLOC_FILL or out of range"
+# endif
+#endif
+
+#ifdef CURL_MT_FREE_FILL
+# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff)
+# error "invalid CURL_MT_FREE_FILL or out of range"
+# endif
+#endif
+
+#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL)
+# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL)
+# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL"
+# endif
+#endif
+
+#ifdef CURL_MT_MALLOC_FILL
+# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len))
+#else
+# define mt_malloc_fill(buf,len) Curl_nop_stmt
+#endif
+
+#ifdef CURL_MT_FREE_FILL
+# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len))
+#else
+# define mt_free_fill(buf,len) Curl_nop_stmt
+#endif
+
+struct memdebug {
+ size_t size;
+ union {
+ curl_off_t o;
+ double d;
+ void * p;
+ } mem[1];
+ /* I'm hoping this is the thing with the strictest alignment
+ * requirements. That also means we waste some space :-( */
+};
+
+/*
+ * Note that these debug functions are very simple and they are meant to
+ * remain so. For advanced analysis, record a log file and write perl scripts
+ * to analyze them!
+ *
+ * Don't use these with multithreaded test programs!
+ */
+
+#define logfile curl_debuglogfile
+FILE *curl_debuglogfile = NULL;
+static bool memlimit = FALSE; /* enable memory limit */
+static long memsize = 0; /* set number of mallocs allowed */
+
+/* this sets the log file name */
+void curl_memdebug(const char *logname)
+{
+ if(!logfile) {
+ if(logname && *logname)
+ logfile = fopen(logname, "w");
+ else
+ logfile = stderr;
+#ifdef MEMDEBUG_LOG_SYNC
+ /* Flush the log file after every line so the log isn't lost in a crash */
+ setvbuf(logfile, (char *)NULL, _IOLBF, 0);
+#endif
+ }
+}
+
+/* This function sets the number of malloc() calls that should return
+ successfully! */
+void curl_memlimit(long limit)
+{
+ if(!memlimit) {
+ memlimit = TRUE;
+ memsize = limit;
+ }
+}
+
+/* returns TRUE if this isn't allowed! */
+static bool countcheck(const char *func, int line, const char *source)
+{
+ /* if source is NULL, then the call is made internally and this check
+ should not be made */
+ if(memlimit && source) {
+ if(!memsize) {
+ if(source) {
+ /* log to file */
+ curl_memlog("LIMIT %s:%d %s reached memlimit\n",
+ source, line, func);
+ /* log to stderr also */
+ fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
+ source, line, func);
+ }
+ SET_ERRNO(ENOMEM);
+ return TRUE; /* RETURN ERROR! */
+ }
+ else
+ memsize--; /* countdown */
+
+ /* log the countdown */
+ if(source)
+ curl_memlog("LIMIT %s:%d %ld ALLOCS left\n",
+ source, line, memsize);
+
+ }
+
+ return FALSE; /* allow this */
+}
+
+void *curl_domalloc(size_t wantedsize, int line, const char *source)
+{
+ struct memdebug *mem;
+ size_t size;
+
+ assert(wantedsize != 0);
+
+ if(countcheck("malloc", line, source))
+ return NULL;
+
+ /* alloc at least 64 bytes */
+ size = sizeof(struct memdebug)+wantedsize;
+
+ mem = (Curl_cmalloc)(size);
+ if(mem) {
+ /* fill memory with junk */
+ mt_malloc_fill(mem->mem, wantedsize);
+ mem->size = wantedsize;
+ }
+
+ if(source)
+ curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
+ source, line, wantedsize,
+ mem ? (void *)mem->mem : (void *)0);
+
+ return (mem ? mem->mem : NULL);
+}
+
+void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
+ int line, const char *source)
+{
+ struct memdebug *mem;
+ size_t size, user_size;
+
+ assert(wanted_elements != 0);
+ assert(wanted_size != 0);
+
+ if(countcheck("calloc", line, source))
+ return NULL;
+
+ /* alloc at least 64 bytes */
+ user_size = wanted_size * wanted_elements;
+ size = sizeof(struct memdebug) + user_size;
+
+ mem = (Curl_ccalloc)(1, size);
+ if(mem)
+ mem->size = user_size;
+
+ if(source)
+ curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
+ source, line, wanted_elements, wanted_size,
+ mem ? (void *)mem->mem : (void *)0);
+
+ return (mem ? mem->mem : NULL);
+}
+
+char *curl_dostrdup(const char *str, int line, const char *source)
+{
+ char *mem;
+ size_t len;
+
+ assert(str != NULL);
+
+ if(countcheck("strdup", line, source))
+ return NULL;
+
+ len=strlen(str)+1;
+
+ mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
+ if(mem)
+ memcpy(mem, str, len);
+
+ if(source)
+ curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
+ source, line, (void *)str, len, (void *)mem);
+
+ return mem;
+}
+
+#if defined(WIN32) && defined(UNICODE)
+wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
+{
+ wchar_t *mem;
+ size_t wsiz, bsiz;
+
+ assert(str != NULL);
+
+ if(countcheck("wcsdup", line, source))
+ return NULL;
+
+ wsiz = wcslen(str) + 1;
+ bsiz = wsiz * sizeof(wchar_t);
+
+ mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
+ if(mem)
+ memcpy(mem, str, bsiz);
+
+ if(source)
+ curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
+ source, line, (void *)str, bsiz, (void *)mem);
+
+ return mem;
+}
+#endif
+
+/* We provide a realloc() that accepts a NULL as pointer, which then
+ performs a malloc(). In order to work with ares. */
+void *curl_dorealloc(void *ptr, size_t wantedsize,
+ int line, const char *source)
+{
+ struct memdebug *mem=NULL;
+
+ size_t size = sizeof(struct memdebug)+wantedsize;
+
+ assert(wantedsize != 0);
+
+ if(countcheck("realloc", line, source))
+ return NULL;
+
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:1684)
+ /* 1684: conversion from pointer to same-sized integral type */
+#endif
+
+ if(ptr)
+ mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+
+ mem = (Curl_crealloc)(mem, size);
+ if(source)
+ curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
+ source, line, (void *)ptr, wantedsize,
+ mem ? (void *)mem->mem : (void *)0);
+
+ if(mem) {
+ mem->size = wantedsize;
+ return mem->mem;
+ }
+
+ return NULL;
+}
+
+void curl_dofree(void *ptr, int line, const char *source)
+{
+ struct memdebug *mem;
+
+ if(ptr) {
+
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:1684)
+ /* 1684: conversion from pointer to same-sized integral type */
+#endif
+
+ mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+
+ /* destroy */
+ mt_free_fill(mem->mem, mem->size);
+
+ /* free for real */
+ (Curl_cfree)(mem);
+ }
+
+ if(source)
+ curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
+}
+
+curl_socket_t curl_socket(int domain, int type, int protocol,
+ int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d socket() = %d\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d socket() = %ld\n" :
+ "FD %s:%d socket() = %zd\n";
+
+ curl_socket_t sockfd = socket(domain, type, protocol);
+
+ if(source && (sockfd != CURL_SOCKET_BAD))
+ curl_memlog(fmt, source, line, sockfd);
+
+ return sockfd;
+}
+
+#ifdef HAVE_SOCKETPAIR
+int curl_socketpair(int domain, int type, int protocol,
+ curl_socket_t socket_vector[2],
+ int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d socketpair() = %d %d\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d socketpair() = %ld %ld\n" :
+ "FD %s:%d socketpair() = %zd %zd\n";
+
+ int res = socketpair(domain, type, protocol, socket_vector);
+
+ if(source && (0 == res))
+ curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
+
+ return res;
+}
+#endif
+
+curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
+ int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d accept() = %d\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d accept() = %ld\n" :
+ "FD %s:%d accept() = %zd\n";
+
+ struct sockaddr *addr = (struct sockaddr *)saddr;
+ curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
+
+ curl_socket_t sockfd = accept(s, addr, addrlen);
+
+ if(source && (sockfd != CURL_SOCKET_BAD))
+ curl_memlog(fmt, source, line, sockfd);
+
+ return sockfd;
+}
+
+/* separate function to allow libcurl to mark a "faked" close */
+void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d sclose(%d)\n":
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d sclose(%ld)\n":
+ "FD %s:%d sclose(%zd)\n";
+
+ if(source)
+ curl_memlog(fmt, source, line, sockfd);
+}
+
+/* this is our own defined way to close sockets on *ALL* platforms */
+int curl_sclose(curl_socket_t sockfd, int line, const char *source)
+{
+ int res=sclose(sockfd);
+ curl_mark_sclose(sockfd, line, source);
+ return res;
+}
+
+FILE *curl_fopen(const char *file, const char *mode,
+ int line, const char *source)
+{
+ FILE *res=fopen(file, mode);
+
+ if(source)
+ curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
+ source, line, file, mode, (void *)res);
+
+ return res;
+}
+
+#ifdef HAVE_FDOPEN
+FILE *curl_fdopen(int filedes, const char *mode,
+ int line, const char *source)
+{
+ FILE *res=fdopen(filedes, mode);
+
+ if(source)
+ curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
+ source, line, filedes, mode, (void *)res);
+
+ return res;
+}
+#endif
+
+int curl_fclose(FILE *file, int line, const char *source)
+{
+ int res;
+
+ assert(file != NULL);
+
+ res=fclose(file);
+
+ if(source)
+ curl_memlog("FILE %s:%d fclose(%p)\n",
+ source, line, (void *)file);
+
+ return res;
+}
+
+#define LOGLINE_BUFSIZE 1024
+
+/* this does the writting to the memory tracking log file */
+void curl_memlog(const char *format, ...)
+{
+ char *buf;
+ int nchars;
+ va_list ap;
+
+ if(!logfile)
+ return;
+
+ buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
+ if(!buf)
+ return;
+
+ va_start(ap, format);
+ nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
+ va_end(ap);
+
+ if(nchars > LOGLINE_BUFSIZE - 1)
+ nchars = LOGLINE_BUFSIZE - 1;
+
+ if(nchars > 0)
+ fwrite(buf, 1, nchars, logfile);
+
+ (Curl_cfree)(buf);
+}
+
+#endif /* CURLDEBUG */
diff --git a/libcurl/src/lib/memdebug.h b/libcurl/src/lib/memdebug.h
new file mode 100644
index 0000000..cfac1e0
--- /dev/null
+++ b/libcurl/src/lib/memdebug.h
@@ -0,0 +1,176 @@
+#ifndef HEADER_CURL_MEMDEBUG_H
+#define HEADER_CURL_MEMDEBUG_H
+#ifdef CURLDEBUG
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * CAUTION: this header is designed to work when included by the app-side
+ * as well as the library. Do not mix with library internals!
+ */
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#define CURL_MT_LOGFNAME_BUFSIZE 512
+
+#define logfile curl_debuglogfile
+
+extern FILE *logfile;
+
+/* memory functions */
+CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source);
+CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line,
+ const char *source);
+CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
+ const char *source);
+CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
+CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
+#if defined(WIN32) && defined(UNICODE)
+CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
+ const char *source);
+#endif
+
+CURL_EXTERN void curl_memdebug(const char *logname);
+CURL_EXTERN void curl_memlimit(long limit);
+CURL_EXTERN void curl_memlog(const char *format, ...);
+
+/* file descriptor manipulators */
+CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol,
+ int line , const char *source);
+CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd,
+ int line , const char *source);
+CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
+ int line , const char *source);
+CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
+ int line, const char *source);
+#ifdef HAVE_SOCKETPAIR
+CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
+ curl_socket_t socket_vector[2],
+ int line , const char *source);
+#endif
+
+/* FILE functions */
+CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
+ const char *source);
+#ifdef HAVE_FDOPEN
+CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line,
+ const char *source);
+#endif
+CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
+
+#ifndef MEMDEBUG_NODEFINES
+
+/* Set this symbol on the command-line, recompile all lib-sources */
+#undef strdup
+#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
+#define malloc(size) curl_domalloc(size, __LINE__, __FILE__)
+#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__)
+#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
+#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
+
+#ifdef WIN32
+# ifdef UNICODE
+# undef wcsdup
+# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+# undef _wcsdup
+# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+# undef _tcsdup
+# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+# else
+# undef _tcsdup
+# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
+# endif
+#endif
+
+#define socket(domain,type,protocol)\
+ curl_socket(domain, type, protocol, __LINE__, __FILE__)
+#undef accept /* for those with accept as a macro */
+#define accept(sock,addr,len)\
+ curl_accept(sock, addr, len, __LINE__, __FILE__)
+#ifdef HAVE_SOCKETPAIR
+#define socketpair(domain,type,protocol,socket_vector)\
+ curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__)
+#endif
+
+#ifdef HAVE_GETADDRINFO
+#if defined(getaddrinfo) && defined(__osf__)
+/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define
+ our macro as for other platforms. Instead, we redefine the new name they
+ define getaddrinfo to become! */
+#define ogetaddrinfo(host,serv,hint,res) \
+ curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+#else
+#undef getaddrinfo
+#define getaddrinfo(host,serv,hint,res) \
+ curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+#endif
+#endif /* HAVE_GETADDRINFO */
+
+#ifdef HAVE_GETNAMEINFO
+#undef getnameinfo
+#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
+ curl_dogetnameinfo(sa, salen, host, hostlen, serv, servlen, flags, \
+ __LINE__, __FILE__)
+#endif /* HAVE_GETNAMEINFO */
+
+#ifdef HAVE_FREEADDRINFO
+#undef freeaddrinfo
+#define freeaddrinfo(data) \
+ curl_dofreeaddrinfo(data, __LINE__, __FILE__)
+#endif /* HAVE_FREEADDRINFO */
+
+/* sclose is probably already defined, redefine it! */
+#undef sclose
+#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
+
+#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__)
+
+#undef fopen
+#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__)
+#undef fdopen
+#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__)
+#define fclose(file) curl_fclose(file,__LINE__,__FILE__)
+
+#endif /* MEMDEBUG_NODEFINES */
+
+#endif /* CURLDEBUG */
+
+/*
+** Following section applies even when CURLDEBUG is not defined.
+*/
+
+#ifndef fake_sclose
+#define fake_sclose(x) Curl_nop_stmt
+#endif
+
+/*
+ * Curl_safefree defined as a macro to allow MemoryTracking feature
+ * to log free() calls at same location where Curl_safefree is used.
+ * This macro also assigns NULL to given pointer when free'd.
+ */
+
+#define Curl_safefree(ptr) \
+ do { free((ptr)); (ptr) = NULL;} WHILE_FALSE
+
+#endif /* HEADER_CURL_MEMDEBUG_H */
diff --git a/libcurl/src/lib/mprintf.c b/libcurl/src/lib/mprintf.c
new file mode 100644
index 0000000..23070a7
--- /dev/null
+++ b/libcurl/src/lib/mprintf.c
@@ -0,0 +1,1142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1999 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ *
+ * Purpose:
+ * A merge of Bjorn Reese's format() function and Daniel's dsprintf()
+ * 1.0. A full blooded printf() clone with full support for <num>$
+ * everywhere (parameters, widths and precisions) including variabled
+ * sized parameters (like doubles, long longs, long doubles and even
+ * void * in 64-bit architectures).
+ *
+ * Current restrictions:
+ * - Max 128 parameters
+ * - No 'long double' support.
+ *
+ * If you ever want truly portable and good *printf() clones, the project that
+ * took on from here is named 'Trio' and you find more details on the trio web
+ * page at http://daniel.haxx.se/trio/
+ */
+
+#include "curl_setup.h"
+
+#if defined(DJGPP) && (DJGPP_MINOR < 4)
+#undef _MPRINTF_REPLACE /* don't use x_was_used() here */
+#endif
+
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef SIZEOF_LONG_DOUBLE
+#define SIZEOF_LONG_DOUBLE 0
+#endif
+
+/*
+ * If SIZEOF_SIZE_T has not been defined, default to the size of long.
+ */
+
+#ifndef SIZEOF_SIZE_T
+# define SIZEOF_SIZE_T CURL_SIZEOF_LONG
+#endif
+
+#ifdef HAVE_LONGLONG
+# define LONG_LONG_TYPE long long
+# define HAVE_LONG_LONG_TYPE
+#else
+# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define LONG_LONG_TYPE __int64
+# define HAVE_LONG_LONG_TYPE
+# else
+# undef LONG_LONG_TYPE
+# undef HAVE_LONG_LONG_TYPE
+# endif
+#endif
+
+/*
+ * Non-ANSI integer extensions
+ */
+
+#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
+ (defined(__WATCOMC__) && defined(__386__)) || \
+ (defined(__POCC__) && defined(_MSC_VER)) || \
+ (defined(_WIN32_WCE)) || \
+ (defined(__MINGW32__)) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
+# define MP_HAVE_INT_EXTENSIONS
+#endif
+
+/*
+ * Max integer data types that mprintf.c is capable
+ */
+
+#ifdef HAVE_LONG_LONG_TYPE
+# define mp_intmax_t LONG_LONG_TYPE
+# define mp_uintmax_t unsigned LONG_LONG_TYPE
+#else
+# define mp_intmax_t long
+# define mp_uintmax_t unsigned long
+#endif
+
+#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
+#define MAX_PARAMETERS 128 /* lame static limit */
+
+#ifdef __AMIGA__
+# undef FORMAT_INT
+#endif
+
+/* Lower-case digits. */
+static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+/* Upper-case digits. */
+static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+#define OUTCHAR(x) \
+ do{ \
+ if(stream((unsigned char)(x), (FILE *)data) != -1) \
+ done++; \
+ else \
+ return done; /* return immediately on failure */ \
+ } WHILE_FALSE
+
+/* Data type to read from the arglist */
+typedef enum {
+ FORMAT_UNKNOWN = 0,
+ FORMAT_STRING,
+ FORMAT_PTR,
+ FORMAT_INT,
+ FORMAT_INTPTR,
+ FORMAT_LONG,
+ FORMAT_LONGLONG,
+ FORMAT_DOUBLE,
+ FORMAT_LONGDOUBLE,
+ FORMAT_WIDTH /* For internal use */
+} FormatType;
+
+/* conversion and display flags */
+enum {
+ FLAGS_NEW = 0,
+ FLAGS_SPACE = 1<<0,
+ FLAGS_SHOWSIGN = 1<<1,
+ FLAGS_LEFT = 1<<2,
+ FLAGS_ALT = 1<<3,
+ FLAGS_SHORT = 1<<4,
+ FLAGS_LONG = 1<<5,
+ FLAGS_LONGLONG = 1<<6,
+ FLAGS_LONGDOUBLE = 1<<7,
+ FLAGS_PAD_NIL = 1<<8,
+ FLAGS_UNSIGNED = 1<<9,
+ FLAGS_OCTAL = 1<<10,
+ FLAGS_HEX = 1<<11,
+ FLAGS_UPPER = 1<<12,
+ FLAGS_WIDTH = 1<<13, /* '*' or '*<num>$' used */
+ FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */
+ FLAGS_PREC = 1<<15, /* precision was specified */
+ FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */
+ FLAGS_CHAR = 1<<17, /* %c story */
+ FLAGS_FLOATE = 1<<18, /* %e or %E */
+ FLAGS_FLOATG = 1<<19 /* %g or %G */
+};
+
+typedef struct {
+ FormatType type;
+ int flags;
+ long width; /* width OR width parameter number */
+ long precision; /* precision OR precision parameter number */
+ union {
+ char *str;
+ void *ptr;
+ union {
+ mp_intmax_t as_signed;
+ mp_uintmax_t as_unsigned;
+ } num;
+ double dnum;
+ } data;
+} va_stack_t;
+
+struct nsprintf {
+ char *buffer;
+ size_t length;
+ size_t max;
+};
+
+struct asprintf {
+ char *buffer; /* allocated buffer */
+ size_t len; /* length of string */
+ size_t alloc; /* length of alloc */
+ int fail; /* (!= 0) if an alloc has failed and thus
+ the output is not the complete data */
+};
+
+static long dprintf_DollarString(char *input, char **end)
+{
+ int number=0;
+ while(ISDIGIT(*input)) {
+ number *= 10;
+ number += *input-'0';
+ input++;
+ }
+ if(number && ('$'==*input++)) {
+ *end = input;
+ return number;
+ }
+ return 0;
+}
+
+static bool dprintf_IsQualifierNoDollar(const char *fmt)
+{
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
+ return TRUE;
+ }
+#endif
+
+ switch(*fmt) {
+ case '-': case '+': case ' ': case '#': case '.':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'h': case 'l': case 'L': case 'z': case 'q':
+ case '*': case 'O':
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ case 'I':
+#endif
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+/******************************************************************
+ *
+ * Pass 1:
+ * Create an index with the type of each parameter entry and its
+ * value (may vary in size)
+ *
+ ******************************************************************/
+
+static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
+ va_list arglist)
+{
+ char *fmt = (char *)format;
+ int param_num = 0;
+ long this_param;
+ long width;
+ long precision;
+ int flags;
+ long max_param=0;
+ long i;
+
+ while(*fmt) {
+ if(*fmt++ == '%') {
+ if(*fmt == '%') {
+ fmt++;
+ continue; /* while */
+ }
+
+ flags = FLAGS_NEW;
+
+ /* Handle the positional case (N$) */
+
+ param_num++;
+
+ this_param = dprintf_DollarString(fmt, &fmt);
+ if(0 == this_param)
+ /* we got no positional, get the next counter */
+ this_param = param_num;
+
+ if(this_param > max_param)
+ max_param = this_param;
+
+ /*
+ * The parameter with number 'i' should be used. Next, we need
+ * to get SIZE and TYPE of the parameter. Add the information
+ * to our array.
+ */
+
+ width = 0;
+ precision = 0;
+
+ /* Handle the flags */
+
+ while(dprintf_IsQualifierNoDollar(fmt)) {
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ if(!strncmp(fmt, "I32", 3)) {
+ flags |= FLAGS_LONG;
+ fmt += 3;
+ }
+ else if(!strncmp(fmt, "I64", 3)) {
+ flags |= FLAGS_LONGLONG;
+ fmt += 3;
+ }
+ else
+#endif
+
+ switch(*fmt++) {
+ case ' ':
+ flags |= FLAGS_SPACE;
+ break;
+ case '+':
+ flags |= FLAGS_SHOWSIGN;
+ break;
+ case '-':
+ flags |= FLAGS_LEFT;
+ flags &= ~FLAGS_PAD_NIL;
+ break;
+ case '#':
+ flags |= FLAGS_ALT;
+ break;
+ case '.':
+ flags |= FLAGS_PREC;
+ if('*' == *fmt) {
+ /* The precision is picked from a specified parameter */
+
+ flags |= FLAGS_PRECPARAM;
+ fmt++;
+ param_num++;
+
+ i = dprintf_DollarString(fmt, &fmt);
+ if(i)
+ precision = i;
+ else
+ precision = param_num;
+
+ if(precision > max_param)
+ max_param = precision;
+ }
+ else {
+ flags |= FLAGS_PREC;
+ precision = strtol(fmt, &fmt, 10);
+ }
+ break;
+ case 'h':
+ flags |= FLAGS_SHORT;
+ break;
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ case 'I':
+#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+#endif
+ case 'l':
+ if(flags & FLAGS_LONG)
+ flags |= FLAGS_LONGLONG;
+ else
+ flags |= FLAGS_LONG;
+ break;
+ case 'L':
+ flags |= FLAGS_LONGDOUBLE;
+ break;
+ case 'q':
+ flags |= FLAGS_LONGLONG;
+ break;
+ case 'z':
+ /* the code below generates a warning if -Wunreachable-code is
+ used */
+#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+ case 'O':
+#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+ case '0':
+ if(!(flags & FLAGS_LEFT))
+ flags |= FLAGS_PAD_NIL;
+ /* FALLTHROUGH */
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ flags |= FLAGS_WIDTH;
+ width = strtol(fmt-1, &fmt, 10);
+ break;
+ case '*': /* Special case */
+ flags |= FLAGS_WIDTHPARAM;
+ param_num++;
+
+ i = dprintf_DollarString(fmt, &fmt);
+ if(i)
+ width = i;
+ else
+ width = param_num;
+ if(width > max_param)
+ max_param=width;
+ break;
+ default:
+ break;
+ }
+ } /* switch */
+
+ /* Handle the specifier */
+
+ i = this_param - 1;
+
+ switch (*fmt) {
+ case 'S':
+ flags |= FLAGS_ALT;
+ /* FALLTHROUGH */
+ case 's':
+ vto[i].type = FORMAT_STRING;
+ break;
+ case 'n':
+ vto[i].type = FORMAT_INTPTR;
+ break;
+ case 'p':
+ vto[i].type = FORMAT_PTR;
+ break;
+ case 'd': case 'i':
+ vto[i].type = FORMAT_INT;
+ break;
+ case 'u':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_UNSIGNED;
+ break;
+ case 'o':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_OCTAL;
+ break;
+ case 'x':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_HEX|FLAGS_UNSIGNED;
+ break;
+ case 'X':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
+ break;
+ case 'c':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_CHAR;
+ break;
+ case 'f':
+ vto[i].type = FORMAT_DOUBLE;
+ break;
+ case 'e':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATE;
+ break;
+ case 'E':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATE|FLAGS_UPPER;
+ break;
+ case 'g':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATG;
+ break;
+ case 'G':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATG|FLAGS_UPPER;
+ break;
+ default:
+ vto[i].type = FORMAT_UNKNOWN;
+ break;
+ } /* switch */
+
+ vto[i].flags = flags;
+ vto[i].width = width;
+ vto[i].precision = precision;
+
+ if(flags & FLAGS_WIDTHPARAM) {
+ /* we have the width specified from a parameter, so we make that
+ parameter's info setup properly */
+ vto[i].width = width - 1;
+ i = width - 1;
+ vto[i].type = FORMAT_WIDTH;
+ vto[i].flags = FLAGS_NEW;
+ vto[i].precision = vto[i].width = 0; /* can't use width or precision
+ of width! */
+ }
+ if(flags & FLAGS_PRECPARAM) {
+ /* we have the precision specified from a parameter, so we make that
+ parameter's info setup properly */
+ vto[i].precision = precision - 1;
+ i = precision - 1;
+ vto[i].type = FORMAT_WIDTH;
+ vto[i].flags = FLAGS_NEW;
+ vto[i].precision = vto[i].width = 0; /* can't use width or precision
+ of width! */
+ }
+ *endpos++ = fmt + 1; /* end of this sequence */
+ }
+ }
+
+ /* Read the arg list parameters into our data list */
+ for(i=0; i<max_param; i++) {
+ if((i + 1 < max_param) && (vto[i + 1].type == FORMAT_WIDTH)) {
+ /* Width/precision arguments must be read before the main argument
+ * they are attached to
+ */
+ vto[i + 1].data.num.as_signed = (mp_intmax_t)va_arg(arglist, int);
+ }
+
+ switch (vto[i].type) {
+ case FORMAT_STRING:
+ vto[i].data.str = va_arg(arglist, char *);
+ break;
+
+ case FORMAT_INTPTR:
+ case FORMAT_UNKNOWN:
+ case FORMAT_PTR:
+ vto[i].data.ptr = va_arg(arglist, void *);
+ break;
+
+ case FORMAT_INT:
+#ifdef HAVE_LONG_LONG_TYPE
+ if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
+ vto[i].data.num.as_unsigned =
+ (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
+ else if(vto[i].flags & FLAGS_LONGLONG)
+ vto[i].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, mp_intmax_t);
+ else
+#endif
+ {
+ if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
+ vto[i].data.num.as_unsigned =
+ (mp_uintmax_t)va_arg(arglist, unsigned long);
+ else if(vto[i].flags & FLAGS_LONG)
+ vto[i].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, long);
+ else if(vto[i].flags & FLAGS_UNSIGNED)
+ vto[i].data.num.as_unsigned =
+ (mp_uintmax_t)va_arg(arglist, unsigned int);
+ else
+ vto[i].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, int);
+ }
+ break;
+
+ case FORMAT_DOUBLE:
+ vto[i].data.dnum = va_arg(arglist, double);
+ break;
+
+ case FORMAT_WIDTH:
+ /* Argument has been read. Silently convert it into an integer
+ * for later use
+ */
+ vto[i].type = FORMAT_INT;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return max_param;
+
+}
+
+static int dprintf_formatf(
+ void *data, /* untouched by format(), just sent to the stream() function in
+ the second argument */
+ /* function pointer called for each output character */
+ int (*stream)(int, FILE *),
+ const char *format, /* %-formatted string */
+ va_list ap_save) /* list of parameters */
+{
+ /* Base-36 digits for numbers. */
+ const char *digits = lower_digits;
+
+ /* Pointer into the format string. */
+ char *f;
+
+ /* Number of characters written. */
+ int done = 0;
+
+ long param; /* current parameter to read */
+ long param_num=0; /* parameter counter */
+
+ va_stack_t vto[MAX_PARAMETERS];
+ char *endpos[MAX_PARAMETERS];
+ char **end;
+
+ char work[BUFFSIZE];
+
+ va_stack_t *p;
+
+ /* Do the actual %-code parsing */
+ dprintf_Pass1(format, vto, endpos, ap_save);
+
+ end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
+ created for us */
+
+ f = (char *)format;
+ while(*f != '\0') {
+ /* Format spec modifiers. */
+ int is_alt;
+
+ /* Width of a field. */
+ long width;
+
+ /* Precision of a field. */
+ long prec;
+
+ /* Decimal integer is negative. */
+ int is_neg;
+
+ /* Base of a number to be written. */
+ long base;
+
+ /* Integral values to be written. */
+ mp_uintmax_t num;
+
+ /* Used to convert negative in positive. */
+ mp_intmax_t signed_num;
+
+ if(*f != '%') {
+ /* This isn't a format spec, so write everything out until the next one
+ OR end of string is reached. */
+ do {
+ OUTCHAR(*f);
+ } while(*++f && ('%' != *f));
+ continue;
+ }
+
+ ++f;
+
+ /* Check for "%%". Note that although the ANSI standard lists
+ '%' as a conversion specifier, it says "The complete format
+ specification shall be `%%'," so we can avoid all the width
+ and precision processing. */
+ if(*f == '%') {
+ ++f;
+ OUTCHAR('%');
+ continue;
+ }
+
+ /* If this is a positional parameter, the position must follow immediately
+ after the %, thus create a %<num>$ sequence */
+ param=dprintf_DollarString(f, &f);
+
+ if(!param)
+ param = param_num;
+ else
+ --param;
+
+ param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
+ third %s will pick the 3rd argument */
+
+ p = &vto[param];
+
+ /* pick up the specified width */
+ if(p->flags & FLAGS_WIDTHPARAM)
+ width = (long)vto[p->width].data.num.as_signed;
+ else
+ width = p->width;
+
+ /* pick up the specified precision */
+ if(p->flags & FLAGS_PRECPARAM) {
+ prec = (long)vto[p->precision].data.num.as_signed;
+ param_num++; /* since the precision is extraced from a parameter, we
+ must skip that to get to the next one properly */
+ }
+ else if(p->flags & FLAGS_PREC)
+ prec = p->precision;
+ else
+ prec = -1;
+
+ is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
+
+ switch (p->type) {
+ case FORMAT_INT:
+ num = p->data.num.as_unsigned;
+ if(p->flags & FLAGS_CHAR) {
+ /* Character. */
+ if(!(p->flags & FLAGS_LEFT))
+ while(--width > 0)
+ OUTCHAR(' ');
+ OUTCHAR((char) num);
+ if(p->flags & FLAGS_LEFT)
+ while(--width > 0)
+ OUTCHAR(' ');
+ break;
+ }
+ if(p->flags & FLAGS_OCTAL) {
+ /* Octal unsigned integer. */
+ base = 8;
+ goto unsigned_number;
+ }
+ else if(p->flags & FLAGS_HEX) {
+ /* Hexadecimal unsigned integer. */
+
+ digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+ base = 16;
+ goto unsigned_number;
+ }
+ else if(p->flags & FLAGS_UNSIGNED) {
+ /* Decimal unsigned integer. */
+ base = 10;
+ goto unsigned_number;
+ }
+
+ /* Decimal integer. */
+ base = 10;
+
+ is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
+ if(is_neg) {
+ /* signed_num might fail to hold absolute negative minimum by 1 */
+ signed_num = p->data.num.as_signed + (mp_intmax_t)1;
+ signed_num = -signed_num;
+ num = (mp_uintmax_t)signed_num;
+ num += (mp_uintmax_t)1;
+ }
+
+ goto number;
+
+ unsigned_number:
+ /* Unsigned number of base BASE. */
+ is_neg = 0;
+
+ number:
+ /* Number of base BASE. */
+ {
+ char *workend = &work[sizeof(work) - 1];
+ char *w;
+
+ /* Supply a default precision if none was given. */
+ if(prec == -1)
+ prec = 1;
+
+ /* Put the number in WORK. */
+ w = workend;
+ while(num > 0) {
+ *w-- = digits[num % base];
+ num /= base;
+ }
+ width -= (long)(workend - w);
+ prec -= (long)(workend - w);
+
+ if(is_alt && base == 8 && prec <= 0) {
+ *w-- = '0';
+ --width;
+ }
+
+ if(prec > 0) {
+ width -= prec;
+ while(prec-- > 0)
+ *w-- = '0';
+ }
+
+ if(is_alt && base == 16)
+ width -= 2;
+
+ if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
+ --width;
+
+ if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ if(is_neg)
+ OUTCHAR('-');
+ else if(p->flags & FLAGS_SHOWSIGN)
+ OUTCHAR('+');
+ else if(p->flags & FLAGS_SPACE)
+ OUTCHAR(' ');
+
+ if(is_alt && base == 16) {
+ OUTCHAR('0');
+ if(p->flags & FLAGS_UPPER)
+ OUTCHAR('X');
+ else
+ OUTCHAR('x');
+ }
+
+ if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
+ while(width-- > 0)
+ OUTCHAR('0');
+
+ /* Write the number. */
+ while(++w <= workend) {
+ OUTCHAR(*w);
+ }
+
+ if(p->flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+ }
+ break;
+
+ case FORMAT_STRING:
+ /* String. */
+ {
+ static const char null[] = "(nil)";
+ const char *str;
+ size_t len;
+
+ str = (char *) p->data.str;
+ if(str == NULL) {
+ /* Write null[] if there's space. */
+ if(prec == -1 || prec >= (long) sizeof(null) - 1) {
+ str = null;
+ len = sizeof(null) - 1;
+ /* Disable quotes around (nil) */
+ p->flags &= (~FLAGS_ALT);
+ }
+ else {
+ str = "";
+ len = 0;
+ }
+ }
+ else if(prec != -1)
+ len = (size_t)prec;
+ else
+ len = strlen(str);
+
+ width -= (long)len;
+
+ if(p->flags & FLAGS_ALT)
+ OUTCHAR('"');
+
+ if(!(p->flags&FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ while((len-- > 0) && *str)
+ OUTCHAR(*str++);
+ if(p->flags&FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ if(p->flags & FLAGS_ALT)
+ OUTCHAR('"');
+ }
+ break;
+
+ case FORMAT_PTR:
+ /* Generic pointer. */
+ {
+ void *ptr;
+ ptr = (void *) p->data.ptr;
+ if(ptr != NULL) {
+ /* If the pointer is not NULL, write it as a %#x spec. */
+ base = 16;
+ digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+ is_alt = 1;
+ num = (size_t) ptr;
+ is_neg = 0;
+ goto number;
+ }
+ else {
+ /* Write "(nil)" for a nil pointer. */
+ static const char strnil[] = "(nil)";
+ const char *point;
+
+ width -= (long)(sizeof(strnil) - 1);
+ if(p->flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+ for(point = strnil; *point != '\0'; ++point)
+ OUTCHAR(*point);
+ if(! (p->flags & FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
+ }
+ }
+ break;
+
+ case FORMAT_DOUBLE:
+ {
+ char formatbuf[32]="%";
+ char *fptr = &formatbuf[1];
+ size_t left = sizeof(formatbuf)-strlen(formatbuf);
+ int len;
+
+ width = -1;
+ if(p->flags & FLAGS_WIDTH)
+ width = p->width;
+ else if(p->flags & FLAGS_WIDTHPARAM)
+ width = (long)vto[p->width].data.num.as_signed;
+
+ prec = -1;
+ if(p->flags & FLAGS_PREC)
+ prec = p->precision;
+ else if(p->flags & FLAGS_PRECPARAM)
+ prec = (long)vto[p->precision].data.num.as_signed;
+
+ if(p->flags & FLAGS_LEFT)
+ *fptr++ = '-';
+ if(p->flags & FLAGS_SHOWSIGN)
+ *fptr++ = '+';
+ if(p->flags & FLAGS_SPACE)
+ *fptr++ = ' ';
+ if(p->flags & FLAGS_ALT)
+ *fptr++ = '#';
+
+ *fptr = 0;
+
+ if(width >= 0) {
+ /* RECURSIVE USAGE */
+ len = curl_msnprintf(fptr, left, "%ld", width);
+ fptr += len;
+ left -= len;
+ }
+ if(prec >= 0) {
+ /* RECURSIVE USAGE */
+ len = curl_msnprintf(fptr, left, ".%ld", prec);
+ fptr += len;
+ }
+ if(p->flags & FLAGS_LONG)
+ *fptr++ = 'l';
+
+ if(p->flags & FLAGS_FLOATE)
+ *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
+ else if(p->flags & FLAGS_FLOATG)
+ *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
+ else
+ *fptr++ = 'f';
+
+ *fptr = 0; /* and a final zero termination */
+
+ /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
+ output characters */
+ (sprintf)(work, formatbuf, p->data.dnum);
+
+ for(fptr=work; *fptr; fptr++)
+ OUTCHAR(*fptr);
+ }
+ break;
+
+ case FORMAT_INTPTR:
+ /* Answer the count of characters written. */
+#ifdef HAVE_LONG_LONG_TYPE
+ if(p->flags & FLAGS_LONGLONG)
+ *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
+ else
+#endif
+ if(p->flags & FLAGS_LONG)
+ *(long *) p->data.ptr = (long)done;
+ else if(!(p->flags & FLAGS_SHORT))
+ *(int *) p->data.ptr = (int)done;
+ else
+ *(short *) p->data.ptr = (short)done;
+ break;
+
+ default:
+ break;
+ }
+ f = *end++; /* goto end of %-code */
+
+ }
+ return done;
+}
+
+/* fputc() look-alike */
+static int addbyter(int output, FILE *data)
+{
+ struct nsprintf *infop=(struct nsprintf *)data;
+ unsigned char outc = (unsigned char)output;
+
+ if(infop->length < infop->max) {
+ /* only do this if we haven't reached max length yet */
+ infop->buffer[0] = outc; /* store */
+ infop->buffer++; /* increase pointer */
+ infop->length++; /* we are now one byte larger */
+ return outc; /* fputc() returns like this on success */
+ }
+ return -1;
+}
+
+int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
+ va_list ap_save)
+{
+ int retcode;
+ struct nsprintf info;
+
+ info.buffer = buffer;
+ info.length = 0;
+ info.max = maxlength;
+
+ retcode = dprintf_formatf(&info, addbyter, format, ap_save);
+ if(info.max) {
+ /* we terminate this with a zero byte */
+ if(info.max == info.length)
+ /* we're at maximum, scrap the last letter */
+ info.buffer[-1] = 0;
+ else
+ info.buffer[0] = 0;
+ }
+ return retcode;
+}
+
+int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
+{
+ int retcode;
+ va_list ap_save; /* argument pointer */
+ va_start(ap_save, format);
+ retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
+ va_end(ap_save);
+ return retcode;
+}
+
+/* fputc() look-alike */
+static int alloc_addbyter(int output, FILE *data)
+{
+ struct asprintf *infop=(struct asprintf *)data;
+ unsigned char outc = (unsigned char)output;
+
+ if(!infop->buffer) {
+ infop->buffer = malloc(32);
+ if(!infop->buffer) {
+ infop->fail = 1;
+ return -1; /* fail */
+ }
+ infop->alloc = 32;
+ infop->len =0;
+ }
+ else if(infop->len+1 >= infop->alloc) {
+ char *newptr;
+
+ newptr = realloc(infop->buffer, infop->alloc*2);
+
+ if(!newptr) {
+ infop->fail = 1;
+ return -1; /* fail */
+ }
+ infop->buffer = newptr;
+ infop->alloc *= 2;
+ }
+
+ infop->buffer[ infop->len ] = outc;
+
+ infop->len++;
+
+ return outc; /* fputc() returns like this on success */
+}
+
+char *curl_maprintf(const char *format, ...)
+{
+ va_list ap_save; /* argument pointer */
+ int retcode;
+ struct asprintf info;
+
+ info.buffer = NULL;
+ info.len = 0;
+ info.alloc = 0;
+ info.fail = 0;
+
+ va_start(ap_save, format);
+ retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ va_end(ap_save);
+ if((-1 == retcode) || info.fail) {
+ if(info.alloc)
+ free(info.buffer);
+ return NULL;
+ }
+ if(info.alloc) {
+ info.buffer[info.len] = 0; /* we terminate this with a zero byte */
+ return info.buffer;
+ }
+ else
+ return strdup("");
+}
+
+char *curl_mvaprintf(const char *format, va_list ap_save)
+{
+ int retcode;
+ struct asprintf info;
+
+ info.buffer = NULL;
+ info.len = 0;
+ info.alloc = 0;
+ info.fail = 0;
+
+ retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ if((-1 == retcode) || info.fail) {
+ if(info.alloc)
+ free(info.buffer);
+ return NULL;
+ }
+
+ if(info.alloc) {
+ info.buffer[info.len] = 0; /* we terminate this with a zero byte */
+ return info.buffer;
+ }
+ else
+ return strdup("");
+}
+
+static int storebuffer(int output, FILE *data)
+{
+ char **buffer = (char **)data;
+ unsigned char outc = (unsigned char)output;
+ **buffer = outc;
+ (*buffer)++;
+ return outc; /* act like fputc() ! */
+}
+
+int curl_msprintf(char *buffer, const char *format, ...)
+{
+ va_list ap_save; /* argument pointer */
+ int retcode;
+ va_start(ap_save, format);
+ retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+ va_end(ap_save);
+ *buffer=0; /* we terminate this with a zero byte */
+ return retcode;
+}
+
+int curl_mprintf(const char *format, ...)
+{
+ int retcode;
+ va_list ap_save; /* argument pointer */
+ va_start(ap_save, format);
+
+ retcode = dprintf_formatf(stdout, fputc, format, ap_save);
+ va_end(ap_save);
+ return retcode;
+}
+
+int curl_mfprintf(FILE *whereto, const char *format, ...)
+{
+ int retcode;
+ va_list ap_save; /* argument pointer */
+ va_start(ap_save, format);
+ retcode = dprintf_formatf(whereto, fputc, format, ap_save);
+ va_end(ap_save);
+ return retcode;
+}
+
+int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
+{
+ int retcode;
+ retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+ *buffer=0; /* we terminate this with a zero byte */
+ return retcode;
+}
+
+int curl_mvprintf(const char *format, va_list ap_save)
+{
+ return dprintf_formatf(stdout, fputc, format, ap_save);
+}
+
+int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
+{
+ return dprintf_formatf(whereto, fputc, format, ap_save);
+}
diff --git a/libcurl/src/lib/multi.c b/libcurl/src/lib/multi.c
new file mode 100644
index 0000000..cdba5a9
--- /dev/null
+++ b/libcurl/src/lib/multi.c
@@ -0,0 +1,2815 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "transfer.h"
+#include "url.h"
+#include "connect.h"
+#include "progress.h"
+#include "easyif.h"
+#include "share.h"
+#include "multiif.h"
+#include "sendf.h"
+#include "timeval.h"
+#include "http.h"
+#include "select.h"
+#include "warnless.h"
+#include "speedcheck.h"
+#include "conncache.h"
+#include "bundles.h"
+#include "multihandle.h"
+#include "pipeline.h"
+#include "sigpipe.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
+ to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
+ CURL handle takes 45-50 K memory, therefore this 3K are not significant.
+*/
+#ifndef CURL_SOCKET_HASH_TABLE_SIZE
+#define CURL_SOCKET_HASH_TABLE_SIZE 911
+#endif
+
+#define CURL_CONNECTION_HASH_SIZE 97
+
+#define CURL_MULTI_HANDLE 0x000bab1e
+
+#define GOOD_MULTI_HANDLE(x) \
+ ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
+#define GOOD_EASY_HANDLE(x) \
+ ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
+
+static void singlesocket(struct Curl_multi *multi,
+ struct SessionHandle *data);
+static int update_timer(struct Curl_multi *multi);
+
+static bool isHandleAtHead(struct SessionHandle *handle,
+ struct curl_llist *pipeline);
+static CURLMcode add_next_timeout(struct timeval now,
+ struct Curl_multi *multi,
+ struct SessionHandle *d);
+static CURLMcode multi_timeout(struct Curl_multi *multi,
+ long *timeout_ms);
+
+#ifdef DEBUGBUILD
+static const char * const statename[]={
+ "INIT",
+ "CONNECT_PEND",
+ "CONNECT",
+ "WAITRESOLVE",
+ "WAITCONNECT",
+ "WAITPROXYCONNECT",
+ "SENDPROTOCONNECT",
+ "PROTOCONNECT",
+ "WAITDO",
+ "DO",
+ "DOING",
+ "DO_MORE",
+ "DO_DONE",
+ "WAITPERFORM",
+ "PERFORM",
+ "TOOFAST",
+ "DONE",
+ "COMPLETED",
+ "MSGSENT",
+};
+#endif
+
+static void multi_freetimeout(void *a, void *b);
+
+/* always use this function to change state, to make debugging easier */
+static void mstate(struct SessionHandle *data, CURLMstate state
+#ifdef DEBUGBUILD
+ , int lineno
+#endif
+)
+{
+ CURLMstate oldstate = data->mstate;
+
+#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) lineno;
+#endif
+
+ if(oldstate == state)
+ /* don't bother when the new state is the same as the old state */
+ return;
+
+ data->mstate = state;
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
+ data->mstate < CURLM_STATE_COMPLETED) {
+ long connection_id = -5000;
+
+ if(data->easy_conn)
+ connection_id = data->easy_conn->connection_id;
+
+ infof(data,
+ "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
+ statename[oldstate], statename[data->mstate],
+ (void *)data, lineno, connection_id);
+ }
+#endif
+
+ if(state == CURLM_STATE_COMPLETED)
+ /* changing to COMPLETED means there's one less easy handle 'alive' */
+ data->multi->num_alive--;
+}
+
+#ifndef DEBUGBUILD
+#define multistate(x,y) mstate(x,y)
+#else
+#define multistate(x,y) mstate(x,y, __LINE__)
+#endif
+
+/*
+ * We add one of these structs to the sockhash for a particular socket
+ */
+
+struct Curl_sh_entry {
+ struct SessionHandle *easy;
+ int action; /* what action READ/WRITE this socket waits for */
+ curl_socket_t socket; /* mainly to ease debugging */
+ void *socketp; /* settable by users with curl_multi_assign() */
+};
+/* bits for 'action' having no bits means this socket is not expecting any
+ action */
+#define SH_READ 1
+#define SH_WRITE 2
+
+/* make sure this socket is present in the hash for this handle */
+static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
+ curl_socket_t s,
+ struct SessionHandle *data)
+{
+ struct Curl_sh_entry *there =
+ Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
+ struct Curl_sh_entry *check;
+
+ if(there)
+ /* it is present, return fine */
+ return there;
+
+ /* not present, add it */
+ check = calloc(1, sizeof(struct Curl_sh_entry));
+ if(!check)
+ return NULL; /* major failure */
+
+ check->easy = data;
+ check->socket = s;
+
+ /* make/add new hash entry */
+ if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
+ free(check);
+ return NULL; /* major failure */
+ }
+
+ return check; /* things are good in sockhash land */
+}
+
+
+/* delete the given socket + handle from the hash */
+static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
+{
+ struct Curl_sh_entry *there =
+ Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
+
+ if(there) {
+ /* this socket is in the hash */
+ /* We remove the hash entry. (This'll end up in a call to
+ sh_freeentry().) */
+ Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
+ }
+}
+
+/*
+ * free a sockhash entry
+ */
+static void sh_freeentry(void *freethis)
+{
+ struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
+
+ free(p);
+}
+
+static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
+{
+ (void) k1_len; (void) k2_len;
+
+ return (*((int *) k1)) == (*((int *) k2));
+}
+
+static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
+{
+ int fd = *((int *) key);
+ (void) key_length;
+
+ return (fd % (int)slots_num);
+}
+
+/*
+ * sh_init() creates a new socket hash and returns the handle for it.
+ *
+ * Quote from README.multi_socket:
+ *
+ * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
+ * is somewhat of a bottle neck. Its current implementation may be a bit too
+ * limiting. It simply has a fixed-size array, and on each entry in the array
+ * it has a linked list with entries. So the hash only checks which list to
+ * scan through. The code I had used so for used a list with merely 7 slots
+ * (as that is what the DNS hash uses) but with 7000 connections that would
+ * make an average of 1000 nodes in each list to run through. I upped that to
+ * 97 slots (I believe a prime is suitable) and noticed a significant speed
+ * increase. I need to reconsider the hash implementation or use a rather
+ * large default value like this. At 9000 connections I was still below 10us
+ * per call."
+ *
+ */
+static struct curl_hash *sh_init(int hashsize)
+{
+ return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
+ sh_freeentry);
+}
+
+/*
+ * multi_addmsg()
+ *
+ * Called when a transfer is completed. Adds the given msg pointer to
+ * the list kept in the multi handle.
+ */
+static CURLMcode multi_addmsg(struct Curl_multi *multi,
+ struct Curl_message *msg)
+{
+ if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
+ return CURLM_OUT_OF_MEMORY;
+
+ return CURLM_OK;
+}
+
+/*
+ * multi_freeamsg()
+ *
+ * Callback used by the llist system when a single list entry is destroyed.
+ */
+static void multi_freeamsg(void *a, void *b)
+{
+ (void)a;
+ (void)b;
+}
+
+struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
+ int chashsize) /* connection hash */
+{
+ struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
+
+ if(!multi)
+ return NULL;
+
+ multi->type = CURL_MULTI_HANDLE;
+
+ multi->hostcache = Curl_mk_dnscache();
+ if(!multi->hostcache)
+ goto error;
+
+ multi->sockhash = sh_init(hashsize);
+ if(!multi->sockhash)
+ goto error;
+
+ multi->conn_cache = Curl_conncache_init(chashsize);
+ if(!multi->conn_cache)
+ goto error;
+
+ multi->msglist = Curl_llist_alloc(multi_freeamsg);
+ if(!multi->msglist)
+ goto error;
+
+ multi->pending = Curl_llist_alloc(multi_freeamsg);
+ if(!multi->pending)
+ goto error;
+
+ /* allocate a new easy handle to use when closing cached connections */
+ multi->closure_handle = curl_easy_init();
+ if(!multi->closure_handle)
+ goto error;
+
+ multi->closure_handle->multi = multi;
+ multi->closure_handle->state.conn_cache = multi->conn_cache;
+
+ multi->max_pipeline_length = 5;
+
+ /* -1 means it not set by user, use the default value */
+ multi->maxconnects = -1;
+ return (CURLM *) multi;
+
+ error:
+
+ Curl_hash_destroy(multi->sockhash);
+ multi->sockhash = NULL;
+ Curl_hash_destroy(multi->hostcache);
+ multi->hostcache = NULL;
+ Curl_conncache_destroy(multi->conn_cache);
+ multi->conn_cache = NULL;
+ Curl_close(multi->closure_handle);
+ multi->closure_handle = NULL;
+ Curl_llist_destroy(multi->msglist, NULL);
+ Curl_llist_destroy(multi->pending, NULL);
+
+ free(multi);
+ return NULL;
+}
+
+CURLM *curl_multi_init(void)
+{
+ return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
+ CURL_CONNECTION_HASH_SIZE);
+}
+
+CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+ CURL *easy_handle)
+{
+ struct curl_llist *timeoutlist;
+ struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
+ struct SessionHandle *data = (struct SessionHandle *)easy_handle;
+
+ /* First, make some basic checks that the CURLM handle is a good handle */
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ /* Verify that we got a somewhat good easy handle too */
+ if(!GOOD_EASY_HANDLE(easy_handle))
+ return CURLM_BAD_EASY_HANDLE;
+
+ /* Prevent users from adding same easy handle more than once and prevent
+ adding to more than one multi stack */
+ if(data->multi)
+ return CURLM_ADDED_ALREADY;
+
+ /* Allocate and initialize timeout list for easy handle */
+ timeoutlist = Curl_llist_alloc(multi_freetimeout);
+ if(!timeoutlist)
+ return CURLM_OUT_OF_MEMORY;
+
+ /*
+ * No failure allowed in this function beyond this point. And no
+ * modification of easy nor multi handle allowed before this except for
+ * potential multi's connection cache growing which won't be undone in this
+ * function no matter what.
+ */
+
+ /* Make easy handle use timeout list initialized above */
+ data->state.timeoutlist = timeoutlist;
+ timeoutlist = NULL;
+
+ /* set the easy handle */
+ multistate(data, CURLM_STATE_INIT);
+
+ if((data->set.global_dns_cache) &&
+ (data->dns.hostcachetype != HCACHE_GLOBAL)) {
+ /* global dns cache was requested but still isn't */
+ struct curl_hash *global = Curl_global_host_cache_init();
+ if(global) {
+ /* only do this if the global cache init works */
+ data->dns.hostcache = global;
+ data->dns.hostcachetype = HCACHE_GLOBAL;
+ }
+ }
+ /* for multi interface connections, we share DNS cache automatically if the
+ easy handle's one is currently not set. */
+ else if(!data->dns.hostcache ||
+ (data->dns.hostcachetype == HCACHE_NONE)) {
+ data->dns.hostcache = multi->hostcache;
+ data->dns.hostcachetype = HCACHE_MULTI;
+ }
+
+ /* Point to the multi's connection cache */
+ data->state.conn_cache = multi->conn_cache;
+
+ data->state.infilesize = data->set.filesize;
+
+ /* This adds the new entry at the 'end' of the doubly-linked circular
+ list of SessionHandle structs to try and maintain a FIFO queue so
+ the pipelined requests are in order. */
+
+ /* We add this new entry last in the list. */
+
+ data->next = NULL; /* end of the line */
+ if(multi->easyp) {
+ struct SessionHandle *last = multi->easylp;
+ last->next = data;
+ data->prev = last;
+ multi->easylp = data; /* the new last node */
+ }
+ else {
+ /* first node, make both prev and next be NULL! */
+ data->next = NULL;
+ data->prev = NULL;
+ multi->easylp = multi->easyp = data; /* both first and last */
+ }
+
+ /* make the SessionHandle refer back to this multi handle */
+ data->multi = multi_handle;
+
+ /* Set the timeout for this handle to expire really soon so that it will
+ be taken care of even when this handle is added in the midst of operation
+ when only the curl_multi_socket() API is used. During that flow, only
+ sockets that time-out or have actions will be dealt with. Since this
+ handle has no action yet, we make sure it times out to get things to
+ happen. */
+ Curl_expire(data, 1);
+
+ /* increase the node-counter */
+ multi->num_easy++;
+
+ /* increase the alive-counter */
+ multi->num_alive++;
+
+ /* A somewhat crude work-around for a little glitch in update_timer() that
+ happens if the lastcall time is set to the same time when the handle is
+ removed as when the next handle is added, as then the check in
+ update_timer() that prevents calling the application multiple times with
+ the same timer infor will not trigger and then the new handle's timeout
+ will not be notified to the app.
+
+ The work-around is thus simply to clear the 'lastcall' variable to force
+ update_timer() to always trigger a callback to the app when a new easy
+ handle is added */
+ memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
+
+ update_timer(multi);
+ return CURLM_OK;
+}
+
+#if 0
+/* Debug-function, used like this:
+ *
+ * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
+ *
+ * Enable the hash print function first by editing hash.c
+ */
+static void debug_print_sock_hash(void *p)
+{
+ struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
+
+ fprintf(stderr, " [easy %p/magic %x/socket %d]",
+ (void *)sh->data, sh->data->magic, (int)sh->socket);
+}
+#endif
+
+CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+ CURL *curl_handle)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *easy = curl_handle;
+ struct SessionHandle *data = easy;
+ bool premature;
+ bool easy_owns_conn;
+ struct curl_llist_element *e;
+
+ /* First, make some basic checks that the CURLM handle is a good handle */
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ /* Verify that we got a somewhat good easy handle too */
+ if(!GOOD_EASY_HANDLE(curl_handle))
+ return CURLM_BAD_EASY_HANDLE;
+
+ /* Prevent users from trying to remove same easy handle more than once */
+ if(!data->multi)
+ return CURLM_OK; /* it is already removed so let's say it is fine! */
+
+ premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
+ easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
+ TRUE : FALSE;
+
+ /* If the 'state' is not INIT or COMPLETED, we might need to do something
+ nice to put the easy_handle in a good known state when this returns. */
+ if(premature) {
+ /* this handle is "alive" so we need to count down the total number of
+ alive connections when this is removed */
+ multi->num_alive--;
+
+ /* When this handle gets removed, other handles may be able to get the
+ connection */
+ Curl_multi_process_pending_handles(multi);
+ }
+
+ if(data->easy_conn &&
+ data->mstate > CURLM_STATE_DO &&
+ data->mstate < CURLM_STATE_COMPLETED) {
+ /* If the handle is in a pipeline and has started sending off its
+ request but not received its response yet, we need to close
+ connection. */
+ connclose(data->easy_conn, "Removed with partial response");
+ /* Set connection owner so that Curl_done() closes it.
+ We can safely do this here since connection is killed. */
+ data->easy_conn->data = easy;
+ easy_owns_conn = TRUE;
+ }
+
+ /* The timer must be shut down before data->multi is set to NULL,
+ else the timenode will remain in the splay tree after
+ curl_easy_cleanup is called. */
+ Curl_expire(data, 0);
+
+ /* destroy the timeout list that is held in the easy handle */
+ if(data->state.timeoutlist) {
+ Curl_llist_destroy(data->state.timeoutlist, NULL);
+ data->state.timeoutlist = NULL;
+ }
+
+ if(data->dns.hostcachetype == HCACHE_MULTI) {
+ /* stop using the multi handle's DNS cache */
+ data->dns.hostcache = NULL;
+ data->dns.hostcachetype = HCACHE_NONE;
+ }
+
+ if(data->easy_conn) {
+
+ /* we must call Curl_done() here (if we still "own it") so that we don't
+ leave a half-baked one around */
+ if(easy_owns_conn) {
+
+ /* Curl_done() clears the conn->data field to lose the association
+ between the easy handle and the connection
+
+ Note that this ignores the return code simply because there's
+ nothing really useful to do with it anyway! */
+ (void)Curl_done(&data->easy_conn, data->result, premature);
+ }
+ else
+ /* Clear connection pipelines, if Curl_done above was not called */
+ Curl_getoff_all_pipelines(data, data->easy_conn);
+ }
+
+ Curl_wildcard_dtor(&data->wildcard);
+
+ /* as this was using a shared connection cache we clear the pointer to that
+ since we're not part of that multi handle anymore */
+ data->state.conn_cache = NULL;
+
+ /* change state without using multistate(), only to make singlesocket() do
+ what we want */
+ data->mstate = CURLM_STATE_COMPLETED;
+ singlesocket(multi, easy); /* to let the application know what sockets that
+ vanish with this handle */
+
+ /* Remove the association between the connection and the handle */
+ if(data->easy_conn) {
+ data->easy_conn->data = NULL;
+ data->easy_conn = NULL;
+ }
+
+ data->multi = NULL; /* clear the association to this multi handle */
+
+ /* make sure there's no pending message in the queue sent from this easy
+ handle */
+
+ for(e = multi->msglist->head; e; e = e->next) {
+ struct Curl_message *msg = e->ptr;
+
+ if(msg->extmsg.easy_handle == easy) {
+ Curl_llist_remove(multi->msglist, e, NULL);
+ /* there can only be one from this specific handle */
+ break;
+ }
+ }
+
+ /* make the previous node point to our next */
+ if(data->prev)
+ data->prev->next = data->next;
+ else
+ multi->easyp = data->next; /* point to first node */
+
+ /* make our next point to our previous node */
+ if(data->next)
+ data->next->prev = data->prev;
+ else
+ multi->easylp = data->prev; /* point to last node */
+
+ /* NOTE NOTE NOTE
+ We do not touch the easy handle here! */
+ multi->num_easy--; /* one less to care about now */
+
+ update_timer(multi);
+ return CURLM_OK;
+}
+
+CURL_STATIC bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
+{
+ return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
+}
+
+CURL_STATIC void Curl_multi_handlePipeBreak(struct SessionHandle *data)
+{
+ data->easy_conn = NULL;
+}
+
+static int waitconnect_getsock(struct connectdata *conn,
+ curl_socket_t *sock,
+ int numsocks)
+{
+ int i;
+ int s=0;
+ int rc=0;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ for(i=0; i<2; i++) {
+ if(conn->tempsock[i] != CURL_SOCKET_BAD) {
+ sock[s] = conn->tempsock[i];
+ rc |= GETSOCK_WRITESOCK(s++);
+ }
+ }
+
+ return rc;
+}
+
+static int waitproxyconnect_getsock(struct connectdata *conn,
+ curl_socket_t *sock,
+ int numsocks)
+{
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ sock[0] = conn->sock[FIRSTSOCKET];
+
+ /* when we've sent a CONNECT to a proxy, we should rather wait for the
+ socket to become readable to be able to get the response headers */
+ if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ return GETSOCK_READSOCK(0);
+
+ return GETSOCK_WRITESOCK(0);
+}
+
+static int domore_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn && conn->handler->domore_getsock)
+ return conn->handler->domore_getsock(conn, socks, numsocks);
+ return GETSOCK_BLANK;
+}
+
+/* returns bitmapped flags for this handle and its sockets */
+static int multi_getsock(struct SessionHandle *data,
+ curl_socket_t *socks, /* points to numsocks number
+ of sockets */
+ int numsocks)
+{
+ /* If the pipe broke, or if there's no connection left for this easy handle,
+ then we MUST bail out now with no bitmask set. The no connection case can
+ happen when this is called from curl_multi_remove_handle() =>
+ singlesocket() => multi_getsock().
+ */
+ if(data->state.pipe_broke || !data->easy_conn)
+ return 0;
+
+ if(data->mstate > CURLM_STATE_CONNECT &&
+ data->mstate < CURLM_STATE_COMPLETED) {
+ /* Set up ownership correctly */
+ data->easy_conn->data = data;
+ }
+
+ switch(data->mstate) {
+ default:
+#if 0 /* switch back on these cases to get the compiler to check for all enums
+ to be present */
+ case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
+ case CURLM_STATE_COMPLETED:
+ case CURLM_STATE_MSGSENT:
+ case CURLM_STATE_INIT:
+ case CURLM_STATE_CONNECT:
+ case CURLM_STATE_WAITDO:
+ case CURLM_STATE_DONE:
+ case CURLM_STATE_LAST:
+ /* this will get called with CURLM_STATE_COMPLETED when a handle is
+ removed */
+#endif
+ return 0;
+
+ case CURLM_STATE_WAITRESOLVE:
+ return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_PROTOCONNECT:
+ case CURLM_STATE_SENDPROTOCONNECT:
+ return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_DO:
+ case CURLM_STATE_DOING:
+ return Curl_doing_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_WAITPROXYCONNECT:
+ return waitproxyconnect_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_WAITCONNECT:
+ return waitconnect_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_DO_MORE:
+ return domore_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
+ to waiting for the same as the *PERFORM
+ states */
+ case CURLM_STATE_PERFORM:
+ case CURLM_STATE_WAITPERFORM:
+ return Curl_single_getsock(data->easy_conn, socks, numsocks);
+ }
+
+}
+
+CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set, fd_set *write_fd_set,
+ fd_set *exc_fd_set, int *max_fd)
+{
+ /* Scan through all the easy handles to get the file descriptors set.
+ Some easy handles may not have connected to the remote host yet,
+ and then we must make sure that is done. */
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ int this_max_fd=-1;
+ curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
+ int bitmap;
+ int i;
+ (void)exc_fd_set; /* not used */
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ data=multi->easyp;
+ while(data) {
+ bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ curl_socket_t s = CURL_SOCKET_BAD;
+
+ if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+ FD_SET(sockbunch[i], read_fd_set);
+ s = sockbunch[i];
+ }
+ if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+ FD_SET(sockbunch[i], write_fd_set);
+ s = sockbunch[i];
+ }
+ if(s == CURL_SOCKET_BAD)
+ /* this socket is unused, break out of loop */
+ break;
+ else {
+ if((int)s > this_max_fd)
+ this_max_fd = (int)s;
+ }
+ }
+
+ data = data->next; /* check next handle */
+ }
+
+ *max_fd = this_max_fd;
+
+ return CURLM_OK;
+}
+
+CURLMcode curl_multi_wait(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
+ int bitmap;
+ unsigned int i;
+ unsigned int nfds = 0;
+ unsigned int curlfds;
+ struct pollfd *ufds = NULL;
+ long timeout_internal;
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ /* If the internally desired timeout is actually shorter than requested from
+ the outside, then use the shorter time! But only if the internal timer
+ is actually larger than -1! */
+ (void)multi_timeout(multi, &timeout_internal);
+ if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
+ timeout_ms = (int)timeout_internal;
+
+ /* Count up how many fds we have from the multi handle */
+ data=multi->easyp;
+ while(data) {
+ bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ curl_socket_t s = CURL_SOCKET_BAD;
+
+ if(bitmap & GETSOCK_READSOCK(i)) {
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(bitmap & GETSOCK_WRITESOCK(i)) {
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(s == CURL_SOCKET_BAD) {
+ break;
+ }
+ }
+
+ data = data->next; /* check next handle */
+ }
+
+ curlfds = nfds; /* number of internal file descriptors */
+ nfds += extra_nfds; /* add the externally provided ones */
+
+ if(nfds || extra_nfds) {
+ ufds = malloc(nfds * sizeof(struct pollfd));
+ if(!ufds)
+ return CURLM_OUT_OF_MEMORY;
+ }
+ nfds = 0;
+
+ /* only do the second loop if we found descriptors in the first stage run
+ above */
+
+ if(curlfds) {
+ /* Add the curl handles to our pollfds first */
+ data=multi->easyp;
+ while(data) {
+ bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ curl_socket_t s = CURL_SOCKET_BAD;
+
+ if(bitmap & GETSOCK_READSOCK(i)) {
+ ufds[nfds].fd = sockbunch[i];
+ ufds[nfds].events = POLLIN;
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(bitmap & GETSOCK_WRITESOCK(i)) {
+ ufds[nfds].fd = sockbunch[i];
+ ufds[nfds].events = POLLOUT;
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(s == CURL_SOCKET_BAD) {
+ break;
+ }
+ }
+
+ data = data->next; /* check next handle */
+ }
+ }
+
+ /* Add external file descriptions from poll-like struct curl_waitfd */
+ for(i = 0; i < extra_nfds; i++) {
+ ufds[nfds].fd = extra_fds[i].fd;
+ ufds[nfds].events = 0;
+ if(extra_fds[i].events & CURL_WAIT_POLLIN)
+ ufds[nfds].events |= POLLIN;
+ if(extra_fds[i].events & CURL_WAIT_POLLPRI)
+ ufds[nfds].events |= POLLPRI;
+ if(extra_fds[i].events & CURL_WAIT_POLLOUT)
+ ufds[nfds].events |= POLLOUT;
+ ++nfds;
+ }
+
+ if(nfds) {
+ /* wait... */
+ infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms);
+ i = Curl_poll(ufds, nfds, timeout_ms);
+
+ if(i) {
+ unsigned int j;
+ /* copy revents results from the poll to the curl_multi_wait poll
+ struct, the bit values of the actual underlying poll() implementation
+ may not be the same as the ones in the public libcurl API! */
+ for(j = 0; j < extra_nfds; j++) {
+ unsigned short mask = 0;
+ unsigned r = ufds[curlfds + j].revents;
+
+ if(r & POLLIN)
+ mask |= CURL_WAIT_POLLIN;
+ if(r & POLLOUT)
+ mask |= CURL_WAIT_POLLOUT;
+ if(r & POLLPRI)
+ mask |= CURL_WAIT_POLLPRI;
+
+ extra_fds[j].revents = mask;
+ }
+ }
+ }
+ else
+ i = 0;
+
+ free(ufds);
+ if(ret)
+ *ret = i;
+ return CURLM_OK;
+}
+
+static CURLMcode multi_runsingle(struct Curl_multi *multi,
+ struct timeval now,
+ struct SessionHandle *data)
+{
+ struct Curl_message *msg = NULL;
+ bool connected;
+ bool async;
+ bool protocol_connect = FALSE;
+ bool dophase_done = FALSE;
+ bool done = FALSE;
+ CURLMcode rc;
+ CURLcode result = CURLE_OK;
+ struct SingleRequest *k;
+ long timeout_ms;
+ int control;
+
+ if(!GOOD_EASY_HANDLE(data))
+ return CURLM_BAD_EASY_HANDLE;
+
+ do {
+ bool disconnect_conn = FALSE;
+ rc = CURLM_OK;
+
+ /* Handle the case when the pipe breaks, i.e., the connection
+ we're using gets cleaned up and we're left with nothing. */
+ if(data->state.pipe_broke) {
+ infof(data, "Pipe broke: handle %p, url = %s\n",
+ (void *)data, data->state.path);
+
+ if(data->mstate < CURLM_STATE_COMPLETED) {
+ /* Head back to the CONNECT state */
+ multistate(data, CURLM_STATE_CONNECT);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ result = CURLE_OK;
+ }
+
+ data->state.pipe_broke = FALSE;
+ data->easy_conn = NULL;
+ continue;
+ }
+
+ if(!data->easy_conn &&
+ data->mstate > CURLM_STATE_CONNECT &&
+ data->mstate < CURLM_STATE_DONE) {
+ /* In all these states, the code will blindly access 'data->easy_conn'
+ so this is precaution that it isn't NULL. And it silences static
+ analyzers. */
+ failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
+ return CURLM_INTERNAL_ERROR;
+ }
+
+ if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
+ data->mstate < CURLM_STATE_COMPLETED)
+ /* Make sure we set the connection's current owner */
+ data->easy_conn->data = data;
+
+ if(data->easy_conn &&
+ (data->mstate >= CURLM_STATE_CONNECT) &&
+ (data->mstate < CURLM_STATE_COMPLETED)) {
+ /* we need to wait for the connect state as only then is the start time
+ stored, but we must not check already completed handles */
+
+ timeout_ms = Curl_timeleft(data, &now,
+ (data->mstate <= CURLM_STATE_WAITDO)?
+ TRUE:FALSE);
+
+ if(timeout_ms < 0) {
+ /* Handle timed out */
+ if(data->mstate == CURLM_STATE_WAITRESOLVE)
+ failf(data, "Resolving timed out after %ld milliseconds",
+ Curl_tvdiff(now, data->progress.t_startsingle));
+ else if(data->mstate == CURLM_STATE_WAITCONNECT)
+ failf(data, "Connection timed out after %ld milliseconds",
+ Curl_tvdiff(now, data->progress.t_startsingle));
+ else {
+ k = &data->req;
+ if(k->size != -1) {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " out of %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(k->now, data->progress.t_startsingle),
+ k->bytecount, k->size);
+ }
+ else {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(now, data->progress.t_startsingle),
+ k->bytecount);
+ }
+ }
+
+ /* Force connection closed if the connection has indeed been used */
+ if(data->mstate > CURLM_STATE_DO) {
+ connclose(data->easy_conn, "Disconnected with pending data");
+ disconnect_conn = TRUE;
+ }
+ result = CURLE_OPERATION_TIMEDOUT;
+ (void)Curl_done(&data->easy_conn, result, TRUE);
+ /* Skip the statemachine and go directly to error handling section. */
+ goto statemachine_end;
+ }
+ }
+
+ switch(data->mstate) {
+ case CURLM_STATE_INIT:
+ /* init this transfer. */
+ result=Curl_pretransfer(data);
+
+ if(!result) {
+ /* after init, go CONNECT */
+ multistate(data, CURLM_STATE_CONNECT);
+ Curl_pgrsTime(data, TIMER_STARTOP);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ break;
+
+ case CURLM_STATE_CONNECT_PEND:
+ /* We will stay here until there is a connection available. Then
+ we try again in the CURLM_STATE_CONNECT state. */
+ break;
+
+ case CURLM_STATE_CONNECT:
+ /* Connect. We want to get a connection identifier filled in. */
+ Curl_pgrsTime(data, TIMER_STARTSINGLE);
+ result = Curl_connect(data, &data->easy_conn,
+ &async, &protocol_connect);
+ if(CURLE_NO_CONNECTION_AVAILABLE == result) {
+ /* There was no connection available. We will go to the pending
+ state and wait for an available connection. */
+ multistate(data, CURLM_STATE_CONNECT_PEND);
+
+ /* add this handle to the list of connect-pending handles */
+ if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data))
+ result = CURLE_OUT_OF_MEMORY;
+ else
+ result = CURLE_OK;
+ break;
+ }
+
+ if(!result) {
+ /* Add this handle to the send or pend pipeline */
+ result = Curl_add_handle_to_pipeline(data, data->easy_conn);
+ if(result)
+ disconnect_conn = TRUE;
+ else {
+ if(async)
+ /* We're now waiting for an asynchronous name lookup */
+ multistate(data, CURLM_STATE_WAITRESOLVE);
+ else {
+ /* after the connect has been sent off, go WAITCONNECT unless the
+ protocol connect is already done and we can go directly to
+ WAITDO or DO! */
+ rc = CURLM_CALL_MULTI_PERFORM;
+
+ if(protocol_connect)
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ else {
+#ifndef CURL_DISABLE_HTTP
+ if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ else
+#endif
+ multistate(data, CURLM_STATE_WAITCONNECT);
+ }
+ }
+ }
+ }
+ break;
+
+ case CURLM_STATE_WAITRESOLVE:
+ /* awaiting an asynch name resolve to complete */
+ {
+ struct Curl_dns_entry *dns = NULL;
+ struct connectdata *conn = data->easy_conn;
+
+ /* check if we have the name resolved by now */
+ dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port);
+
+ if(dns) {
+#ifdef CURLRES_ASYNCH
+ conn->async.dns = dns;
+ conn->async.done = TRUE;
+#endif
+ result = CURLE_OK;
+ infof(data, "Hostname was found in DNS cache\n");
+ }
+
+ if(!dns)
+ result = Curl_resolver_is_resolved(data->easy_conn, &dns);
+
+ /* Update sockets here, because the socket(s) may have been
+ closed and the application thus needs to be told, even if it
+ is likely that the same socket(s) will again be used further
+ down. If the name has not yet been resolved, it is likely
+ that new sockets have been opened in an attempt to contact
+ another resolver. */
+ singlesocket(multi, data);
+
+ if(dns) {
+ /* Perform the next step in the connection phase, and then move on
+ to the WAITCONNECT state */
+ result = Curl_async_resolved(data->easy_conn, &protocol_connect);
+
+ if(result)
+ /* if Curl_async_resolved() returns failure, the connection struct
+ is already freed and gone */
+ data->easy_conn = NULL; /* no more connection */
+ else {
+ /* call again please so that we get the next socket setup */
+ rc = CURLM_CALL_MULTI_PERFORM;
+ if(protocol_connect)
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ else {
+#ifndef CURL_DISABLE_HTTP
+ if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ else
+#endif
+ multistate(data, CURLM_STATE_WAITCONNECT);
+ }
+ }
+ }
+
+ if(result) {
+ /* failure detected */
+ disconnect_conn = TRUE;
+ break;
+ }
+ }
+ break;
+
+#ifndef CURL_DISABLE_HTTP
+ case CURLM_STATE_WAITPROXYCONNECT:
+ /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
+ result = Curl_http_connect(data->easy_conn, &protocol_connect);
+
+ rc = CURLM_CALL_MULTI_PERFORM;
+ if(data->easy_conn->bits.proxy_connect_closed) {
+ /* connect back to proxy again */
+ result = CURLE_OK;
+ multistate(data, CURLM_STATE_CONNECT);
+ }
+ else if(!result) {
+ if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
+ /* initiate protocol connect phase */
+ multistate(data, CURLM_STATE_SENDPROTOCONNECT);
+ }
+ break;
+#endif
+
+ case CURLM_STATE_WAITCONNECT:
+ /* awaiting a completion of an asynch TCP connect */
+ result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
+ if(connected && !result) {
+ rc = CURLM_CALL_MULTI_PERFORM;
+ multistate(data, data->easy_conn->bits.tunnel_proxy?
+ CURLM_STATE_WAITPROXYCONNECT:
+ CURLM_STATE_SENDPROTOCONNECT);
+ }
+ else if(result) {
+ /* failure detected */
+ /* Just break, the cleaning up is handled all in one place */
+ disconnect_conn = TRUE;
+ break;
+ }
+ break;
+
+ case CURLM_STATE_SENDPROTOCONNECT:
+ result = Curl_protocol_connect(data->easy_conn, &protocol_connect);
+ if(!protocol_connect)
+ /* switch to waiting state */
+ multistate(data, CURLM_STATE_PROTOCONNECT);
+ else if(!result) {
+ /* protocol connect has completed, go WAITDO or DO */
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ else if(result) {
+ /* failure detected */
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, result, TRUE);
+ disconnect_conn = TRUE;
+ }
+ break;
+
+ case CURLM_STATE_PROTOCONNECT:
+ /* protocol-specific connect phase */
+ result = Curl_protocol_connecting(data->easy_conn, &protocol_connect);
+ if(!result && protocol_connect) {
+ /* after the connect has completed, go WAITDO or DO */
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ else if(result) {
+ /* failure detected */
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, result, TRUE);
+ disconnect_conn = TRUE;
+ }
+ break;
+
+ case CURLM_STATE_WAITDO:
+ /* Wait for our turn to DO when we're pipelining requests */
+#ifdef DEBUGBUILD
+ infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
+ data->easy_conn->connection_id,
+ data->easy_conn->send_pipe->size,
+ data->easy_conn->writechannel_inuse?"TRUE":"FALSE",
+ isHandleAtHead(data,
+ data->easy_conn->send_pipe)?"TRUE":"FALSE");
+#endif
+ if(!data->easy_conn->writechannel_inuse &&
+ isHandleAtHead(data,
+ data->easy_conn->send_pipe)) {
+ /* Grab the channel */
+ data->easy_conn->writechannel_inuse = TRUE;
+ multistate(data, CURLM_STATE_DO);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ break;
+
+ case CURLM_STATE_DO:
+ if(data->set.connect_only) {
+ /* keep connection open for application to use the socket */
+ connkeep(data->easy_conn, "CONNECT_ONLY");
+ multistate(data, CURLM_STATE_DONE);
+ result = CURLE_OK;
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ else {
+ /* Perform the protocol's DO action */
+ result = Curl_do(&data->easy_conn, &dophase_done);
+
+ /* When Curl_do() returns failure, data->easy_conn might be NULL! */
+
+ if(!result) {
+ if(!dophase_done) {
+ /* some steps needed for wildcard matching */
+ if(data->set.wildcardmatch) {
+ struct WildcardData *wc = &data->wildcard;
+ if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
+ /* skip some states if it is important */
+ Curl_done(&data->easy_conn, CURLE_OK, FALSE);
+ multistate(data, CURLM_STATE_DONE);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ break;
+ }
+ }
+ /* DO was not completed in one function call, we must continue
+ DOING... */
+ multistate(data, CURLM_STATE_DOING);
+ rc = CURLM_OK;
+ }
+
+ /* after DO, go DO_DONE... or DO_MORE */
+ else if(data->easy_conn->bits.do_more) {
+ /* we're supposed to do more, but we need to sit down, relax
+ and wait a little while first */
+ multistate(data, CURLM_STATE_DO_MORE);
+ rc = CURLM_OK;
+ }
+ else {
+ /* we're done with the DO, now DO_DONE */
+ multistate(data, CURLM_STATE_DO_DONE);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+ else if((CURLE_SEND_ERROR == result) &&
+ data->easy_conn->bits.reuse) {
+ /*
+ * In this situation, a connection that we were trying to use
+ * may have unexpectedly died. If possible, send the connection
+ * back to the CONNECT phase so we can try again.
+ */
+ char *newurl = NULL;
+ followtype follow=FOLLOW_NONE;
+ CURLcode drc;
+ bool retry = FALSE;
+
+ drc = Curl_retry_request(data->easy_conn, &newurl);
+ if(drc) {
+ /* a failure here pretty much implies an out of memory */
+ result = drc;
+ disconnect_conn = TRUE;
+ }
+ else
+ retry = (newurl)?TRUE:FALSE;
+
+ Curl_posttransfer(data);
+ drc = Curl_done(&data->easy_conn, result, FALSE);
+
+ /* When set to retry the connection, we must to go back to
+ * the CONNECT state */
+ if(retry) {
+ if(!drc || (drc == CURLE_SEND_ERROR)) {
+ follow = FOLLOW_RETRY;
+ drc = Curl_follow(data, newurl, follow);
+ if(!drc) {
+ multistate(data, CURLM_STATE_CONNECT);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ result = CURLE_OK;
+ }
+ else {
+ /* Follow failed */
+ result = drc;
+ free(newurl);
+ }
+ }
+ else {
+ /* done didn't return OK or SEND_ERROR */
+ result = drc;
+ free(newurl);
+ }
+ }
+ else {
+ /* Have error handler disconnect conn if we can't retry */
+ disconnect_conn = TRUE;
+ free(newurl);
+ }
+ }
+ else {
+ /* failure detected */
+ Curl_posttransfer(data);
+ if(data->easy_conn)
+ Curl_done(&data->easy_conn, result, FALSE);
+ disconnect_conn = TRUE;
+ }
+ }
+ break;
+
+ case CURLM_STATE_DOING:
+ /* we continue DOING until the DO phase is complete */
+ result = Curl_protocol_doing(data->easy_conn,
+ &dophase_done);
+ if(!result) {
+ if(dophase_done) {
+ /* after DO, go DO_DONE or DO_MORE */
+ multistate(data, data->easy_conn->bits.do_more?
+ CURLM_STATE_DO_MORE:
+ CURLM_STATE_DO_DONE);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ } /* dophase_done */
+ }
+ else {
+ /* failure detected */
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, result, FALSE);
+ disconnect_conn = TRUE;
+ }
+ break;
+
+ case CURLM_STATE_DO_MORE:
+ /*
+ * When we are connected, DO MORE and then go DO_DONE
+ */
+ result = Curl_do_more(data->easy_conn, &control);
+
+ /* No need to remove this handle from the send pipeline here since that
+ is done in Curl_done() */
+ if(!result) {
+ if(control) {
+ /* if positive, advance to DO_DONE
+ if negative, go back to DOING */
+ multistate(data, control==1?
+ CURLM_STATE_DO_DONE:
+ CURLM_STATE_DOING);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ else
+ /* stay in DO_MORE */
+ rc = CURLM_OK;
+ }
+ else {
+ /* failure detected */
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, result, FALSE);
+ disconnect_conn = TRUE;
+ }
+ break;
+
+ case CURLM_STATE_DO_DONE:
+ /* Move ourselves from the send to recv pipeline */
+ Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ /* Only perform the transfer if there's a good socket to work with.
+ Having both BAD is a signal to skip immediately to DONE */
+ if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
+ (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
+ multistate(data, CURLM_STATE_WAITPERFORM);
+ else
+ multistate(data, CURLM_STATE_DONE);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ break;
+
+ case CURLM_STATE_WAITPERFORM:
+ /* Wait for our turn to PERFORM */
+ if(!data->easy_conn->readchannel_inuse &&
+ isHandleAtHead(data,
+ data->easy_conn->recv_pipe)) {
+ /* Grab the channel */
+ data->easy_conn->readchannel_inuse = TRUE;
+ multistate(data, CURLM_STATE_PERFORM);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+#ifdef DEBUGBUILD
+ else {
+ infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
+ data->easy_conn->connection_id,
+ data->easy_conn->recv_pipe->size,
+ data->easy_conn->readchannel_inuse?"TRUE":"FALSE",
+ isHandleAtHead(data,
+ data->easy_conn->recv_pipe)?"TRUE":"FALSE");
+ }
+#endif
+ break;
+
+ case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
+ /* if both rates are within spec, resume transfer */
+ if(Curl_pgrsUpdate(data->easy_conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(data, now);
+
+ if(( (data->set.max_send_speed == 0) ||
+ (data->progress.ulspeed < data->set.max_send_speed )) &&
+ ( (data->set.max_recv_speed == 0) ||
+ (data->progress.dlspeed < data->set.max_recv_speed)))
+ multistate(data, CURLM_STATE_PERFORM);
+ break;
+
+ case CURLM_STATE_PERFORM:
+ {
+ char *newurl = NULL;
+ bool retry = FALSE;
+
+ /* check if over send speed */
+ if((data->set.max_send_speed > 0) &&
+ (data->progress.ulspeed > data->set.max_send_speed)) {
+ int buffersize;
+
+ multistate(data, CURLM_STATE_TOOFAST);
+
+ /* calculate upload rate-limitation timeout. */
+ buffersize = (int)(data->set.buffer_size ?
+ data->set.buffer_size : BUFSIZE);
+ timeout_ms = Curl_sleep_time(data->set.max_send_speed,
+ data->progress.ulspeed, buffersize);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
+
+ /* check if over recv speed */
+ if((data->set.max_recv_speed > 0) &&
+ (data->progress.dlspeed > data->set.max_recv_speed)) {
+ int buffersize;
+
+ multistate(data, CURLM_STATE_TOOFAST);
+
+ /* Calculate download rate-limitation timeout. */
+ buffersize = (int)(data->set.buffer_size ?
+ data->set.buffer_size : BUFSIZE);
+ timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
+ data->progress.dlspeed, buffersize);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
+
+ /* read/write data if it is ready to do so */
+ result = Curl_readwrite(data->easy_conn, &done);
+
+ k = &data->req;
+
+ if(!(k->keepon & KEEP_RECV)) {
+ /* We're done receiving */
+ data->easy_conn->readchannel_inuse = FALSE;
+ }
+
+ if(!(k->keepon & KEEP_SEND)) {
+ /* We're done sending */
+ data->easy_conn->writechannel_inuse = FALSE;
+ }
+
+ if(done || (result == CURLE_RECV_ERROR)) {
+ /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
+ * condition and the server closed the re-used connection exactly when
+ * we wanted to use it, so figure out if that is indeed the case.
+ */
+ CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
+ if(!ret)
+ retry = (newurl)?TRUE:FALSE;
+
+ if(retry) {
+ /* if we are to retry, set the result to OK and consider the
+ request as done */
+ result = CURLE_OK;
+ done = TRUE;
+ }
+ }
+
+ if(result) {
+ /*
+ * The transfer phase returned error, we mark the connection to get
+ * closed to prevent being re-used. This is because we can't possibly
+ * know if the connection is in a good shape or not now. Unless it is
+ * a protocol which uses two "channels" like FTP, as then the error
+ * happened in the data connection.
+ */
+
+ if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
+ connclose(data->easy_conn, "Transfer returned error");
+
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, result, FALSE);
+ }
+ else if(done) {
+ followtype follow=FOLLOW_NONE;
+
+ /* call this even if the readwrite function returned error */
+ Curl_posttransfer(data);
+
+ /* we're no longer receiving */
+ Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+
+ /* expire the new receiving pipeline head */
+ if(data->easy_conn->recv_pipe->head)
+ Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
+
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ /* When we follow redirects or is set to retry the connection, we must
+ to go back to the CONNECT state */
+ if(data->req.newurl || retry) {
+ if(!retry) {
+ /* if the URL is a follow-location and not just a retried request
+ then figure out the URL here */
+ free(newurl);
+ newurl = data->req.newurl;
+ data->req.newurl = NULL;
+ follow = FOLLOW_REDIR;
+ }
+ else
+ follow = FOLLOW_RETRY;
+ result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
+ if(!result) {
+ result = Curl_follow(data, newurl, follow);
+ if(!result) {
+ multistate(data, CURLM_STATE_CONNECT);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ newurl = NULL; /* handed over the memory ownership to
+ Curl_follow(), make sure we don't free() it
+ here */
+ }
+ }
+ }
+ else {
+ /* after the transfer is done, go DONE */
+
+ /* but first check to see if we got a location info even though we're
+ not following redirects */
+ if(data->req.location) {
+ free(newurl);
+ newurl = data->req.location;
+ data->req.location = NULL;
+ result = Curl_follow(data, newurl, FOLLOW_FAKE);
+ if(!result)
+ newurl = NULL; /* allocation was handed over Curl_follow() */
+ else
+ disconnect_conn = TRUE;
+ }
+
+ multistate(data, CURLM_STATE_DONE);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+
+ free(newurl);
+ break;
+ }
+
+ case CURLM_STATE_DONE:
+ /* this state is highly transient, so run another loop after this */
+ rc = CURLM_CALL_MULTI_PERFORM;
+
+ if(data->easy_conn) {
+ CURLcode res;
+
+ /* Remove ourselves from the receive pipeline, if we are there. */
+ Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ /* post-transfer command */
+ res = Curl_done(&data->easy_conn, result, FALSE);
+
+ /* allow a previously set error code take precedence */
+ if(!result)
+ result = res;
+
+ /*
+ * If there are other handles on the pipeline, Curl_done won't set
+ * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
+ * access free'd data, if the connection is free'd and the handle
+ * removed before we perform the processing in CURLM_STATE_COMPLETED
+ */
+ if(data->easy_conn)
+ data->easy_conn = NULL;
+ }
+
+ if(data->set.wildcardmatch) {
+ if(data->wildcard.state != CURLWC_DONE) {
+ /* if a wildcard is set and we are not ending -> lets start again
+ with CURLM_STATE_INIT */
+ multistate(data, CURLM_STATE_INIT);
+ break;
+ }
+ }
+
+ /* after we have DONE what we're supposed to do, go COMPLETED, and
+ it doesn't matter what the Curl_done() returned! */
+ multistate(data, CURLM_STATE_COMPLETED);
+ break;
+
+ case CURLM_STATE_COMPLETED:
+ /* this is a completed transfer, it is likely to still be connected */
+
+ /* This node should be delinked from the list now and we should post
+ an information message that we are complete. */
+
+ /* Important: reset the conn pointer so that we don't point to memory
+ that could be freed anytime */
+ data->easy_conn = NULL;
+
+ Curl_expire(data, 0); /* stop all timers */
+ break;
+
+ case CURLM_STATE_MSGSENT:
+ data->result = result;
+ return CURLM_OK; /* do nothing */
+
+ default:
+ return CURLM_INTERNAL_ERROR;
+ }
+ statemachine_end:
+
+ if(data->mstate < CURLM_STATE_COMPLETED) {
+ if(result) {
+ /*
+ * If an error was returned, and we aren't in completed state now,
+ * then we go to completed and consider this transfer aborted.
+ */
+
+ /* NOTE: no attempt to disconnect connections must be made
+ in the case blocks above - cleanup happens only here */
+
+ data->state.pipe_broke = FALSE;
+
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ if(data->easy_conn) {
+ /* if this has a connection, unsubscribe from the pipelines */
+ data->easy_conn->writechannel_inuse = FALSE;
+ data->easy_conn->readchannel_inuse = FALSE;
+ Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe);
+ Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+
+ if(disconnect_conn) {
+ /* Don't attempt to send data over a connection that timed out */
+ bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
+ /* disconnect properly */
+ Curl_disconnect(data->easy_conn, dead_connection);
+
+ /* This is where we make sure that the easy_conn pointer is reset.
+ We don't have to do this in every case block above where a
+ failure is detected */
+ data->easy_conn = NULL;
+ }
+ }
+ else if(data->mstate == CURLM_STATE_CONNECT) {
+ /* Curl_connect() failed */
+ (void)Curl_posttransfer(data);
+ }
+
+ multistate(data, CURLM_STATE_COMPLETED);
+ }
+ /* if there's still a connection to use, call the progress function */
+ else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
+ /* aborted due to progress callback return code must close the
+ connection */
+ result = CURLE_ABORTED_BY_CALLBACK;
+ connclose(data->easy_conn, "Aborted by callback");
+
+ /* if not yet in DONE state, go there, otherwise COMPLETED */
+ multistate(data, (data->mstate < CURLM_STATE_DONE)?
+ CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+
+ if(CURLM_STATE_COMPLETED == data->mstate) {
+ /* now fill in the Curl_message with this info */
+ msg = &data->msg;
+
+ msg->extmsg.msg = CURLMSG_DONE;
+ msg->extmsg.easy_handle = data;
+ msg->extmsg.data.result = result;
+
+ rc = multi_addmsg(multi, msg);
+
+ multistate(data, CURLM_STATE_MSGSENT);
+ }
+ } while(rc == CURLM_CALL_MULTI_PERFORM);
+
+ data->result = result;
+
+
+ return rc;
+}
+
+
+CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ CURLMcode returncode=CURLM_OK;
+ struct Curl_tree *t;
+ struct timeval now = Curl_tvnow();
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ data=multi->easyp;
+ while(data) {
+ CURLMcode result;
+ struct WildcardData *wc = &data->wildcard;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ if(data->set.wildcardmatch) {
+ if(!wc->filelist) {
+ CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
+ if(ret)
+ return CURLM_OUT_OF_MEMORY;
+ }
+ }
+
+ sigpipe_ignore(data, &pipe_st);
+ result = multi_runsingle(multi, now, data);
+ sigpipe_restore(&pipe_st);
+
+ if(data->set.wildcardmatch) {
+ /* destruct wildcard structures if it is needed */
+ if(wc->state == CURLWC_DONE || result)
+ Curl_wildcard_dtor(wc);
+ }
+
+ if(result)
+ returncode = result;
+
+ data = data->next; /* operate on next handle */
+ }
+
+ /*
+ * Simply remove all expired timers from the splay since handles are dealt
+ * with unconditionally by this function and curl_multi_timeout() requires
+ * that already passed/handled expire times are removed from the splay.
+ *
+ * It is important that the 'now' value is set at the entry of this function
+ * and not for the current time as it may have ticked a little while since
+ * then and then we risk this loop to remove timers that actually have not
+ * been handled!
+ */
+ do {
+ multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
+ if(t)
+ /* the removed may have another timeout in queue */
+ (void)add_next_timeout(now, multi, t->payload);
+
+ } while(t);
+
+ *running_handles = multi->num_alive;
+
+ if(CURLM_OK >= returncode)
+ update_timer(multi);
+
+ return returncode;
+}
+
+static void close_all_connections(struct Curl_multi *multi)
+{
+ struct connectdata *conn;
+
+ conn = Curl_conncache_find_first_connection(multi->conn_cache);
+ while(conn) {
+ SIGPIPE_VARIABLE(pipe_st);
+ conn->data = multi->closure_handle;
+
+ sigpipe_ignore(conn->data, &pipe_st);
+ /* This will remove the connection from the cache */
+ (void)Curl_disconnect(conn, FALSE);
+ sigpipe_restore(&pipe_st);
+
+ conn = Curl_conncache_find_first_connection(multi->conn_cache);
+ }
+}
+
+CURLMcode curl_multi_cleanup(CURLM *multi_handle)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ struct SessionHandle *nextdata;
+
+ if(GOOD_MULTI_HANDLE(multi)) {
+ bool restore_pipe = FALSE;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ multi->type = 0; /* not good anymore */
+
+ /* Close all the connections in the connection cache */
+ close_all_connections(multi);
+
+ if(multi->closure_handle) {
+ sigpipe_ignore(multi->closure_handle, &pipe_st);
+ restore_pipe = TRUE;
+
+ multi->closure_handle->dns.hostcache = multi->hostcache;
+ Curl_hostcache_clean(multi->closure_handle,
+ multi->closure_handle->dns.hostcache);
+
+ Curl_close(multi->closure_handle);
+ }
+
+ Curl_hash_destroy(multi->sockhash);
+ Curl_conncache_destroy(multi->conn_cache);
+ Curl_llist_destroy(multi->msglist, NULL);
+ Curl_llist_destroy(multi->pending, NULL);
+
+ /* remove all easy handles */
+ data = multi->easyp;
+ while(data) {
+ nextdata=data->next;
+ if(data->dns.hostcachetype == HCACHE_MULTI) {
+ /* clear out the usage of the shared DNS cache */
+ Curl_hostcache_clean(data, data->dns.hostcache);
+ data->dns.hostcache = NULL;
+ data->dns.hostcachetype = HCACHE_NONE;
+ }
+
+ /* Clear the pointer to the connection cache */
+ data->state.conn_cache = NULL;
+ data->multi = NULL; /* clear the association */
+
+ data = nextdata;
+ }
+
+ Curl_hash_destroy(multi->hostcache);
+
+ /* Free the blacklists by setting them to NULL */
+ Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
+ Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
+
+ free(multi);
+ if(restore_pipe)
+ sigpipe_restore(&pipe_st);
+
+ return CURLM_OK;
+ }
+ else
+ return CURLM_BAD_HANDLE;
+}
+
+/*
+ * curl_multi_info_read()
+ *
+ * This function is the primary way for a multi/multi_socket application to
+ * figure out if a transfer has ended. We MUST make this function as fast as
+ * possible as it will be polled frequently and we MUST NOT scan any lists in
+ * here to figure out things. We must scale fine to thousands of handles and
+ * beyond. The current design is fully O(1).
+ */
+
+CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct Curl_message *msg;
+
+ *msgs_in_queue = 0; /* default to none */
+
+ if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
+ /* there is one or more messages in the list */
+ struct curl_llist_element *e;
+
+ /* extract the head of the list to return */
+ e = multi->msglist->head;
+
+ msg = e->ptr;
+
+ /* remove the extracted entry */
+ Curl_llist_remove(multi->msglist, e, NULL);
+
+ *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
+
+ return &msg->extmsg;
+ }
+ else
+ return NULL;
+}
+
+/*
+ * singlesocket() checks what sockets we deal with and their "action state"
+ * and if we have a different state in any of those sockets from last time we
+ * call the callback accordingly.
+ */
+static void singlesocket(struct Curl_multi *multi,
+ struct SessionHandle *data)
+{
+ curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
+ int i;
+ struct Curl_sh_entry *entry;
+ curl_socket_t s;
+ int num;
+ unsigned int curraction;
+ bool remove_sock_from_hash;
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
+ socks[i] = CURL_SOCKET_BAD;
+
+ /* Fill in the 'current' struct with the state as it is now: what sockets to
+ supervise and for what actions */
+ curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE);
+
+ /* We have 0 .. N sockets already and we get to know about the 0 .. M
+ sockets we should have from now on. Detect the differences, remove no
+ longer supervised ones and add new ones */
+
+ /* walk over the sockets we got right now */
+ for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
+ (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
+ i++) {
+ int action = CURL_POLL_NONE;
+
+ s = socks[i];
+
+ /* get it from the hash */
+ entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ if(curraction & GETSOCK_READSOCK(i))
+ action |= CURL_POLL_IN;
+ if(curraction & GETSOCK_WRITESOCK(i))
+ action |= CURL_POLL_OUT;
+
+ if(entry) {
+ /* yeps, already present so check if it has the same action set */
+ if(entry->action == action)
+ /* same, continue */
+ continue;
+ }
+ else {
+ /* this is a socket we didn't have before, add it! */
+ entry = sh_addentry(multi->sockhash, s, data);
+ if(!entry)
+ /* fatal */
+ return;
+ }
+
+ /* we know (entry != NULL) at this point, see the logic above */
+ if(multi->socket_cb)
+ multi->socket_cb(data,
+ s,
+ action,
+ multi->socket_userp,
+ entry->socketp);
+
+ entry->action = action; /* store the current action state */
+ }
+
+ num = i; /* number of sockets */
+
+ /* when we've walked over all the sockets we should have right now, we must
+ make sure to detect sockets that are removed */
+ for(i=0; i< data->numsocks; i++) {
+ int j;
+ s = data->sockets[i];
+ for(j=0; j<num; j++) {
+ if(s == socks[j]) {
+ /* this is still supervised */
+ s = CURL_SOCKET_BAD;
+ break;
+ }
+ }
+ if(s != CURL_SOCKET_BAD) {
+
+ /* this socket has been removed. Tell the app to remove it */
+ remove_sock_from_hash = TRUE;
+
+ entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+ if(entry) {
+ /* check if the socket to be removed serves a connection which has
+ other easy-s in a pipeline. In this case the socket should not be
+ removed. */
+ struct connectdata *easy_conn = data->easy_conn;
+ if(easy_conn) {
+ if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
+ /* the handle should not be removed from the pipe yet */
+ remove_sock_from_hash = FALSE;
+
+ /* Update the sockhash entry to instead point to the next in line
+ for the recv_pipe, or the first (in case this particular easy
+ isn't already) */
+ if(entry->easy == data) {
+ if(isHandleAtHead(data, easy_conn->recv_pipe))
+ entry->easy = easy_conn->recv_pipe->head->next->ptr;
+ else
+ entry->easy = easy_conn->recv_pipe->head->ptr;
+ }
+ }
+ if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
+ /* the handle should not be removed from the pipe yet */
+ remove_sock_from_hash = FALSE;
+
+ /* Update the sockhash entry to instead point to the next in line
+ for the send_pipe, or the first (in case this particular easy
+ isn't already) */
+ if(entry->easy == data) {
+ if(isHandleAtHead(data, easy_conn->send_pipe))
+ entry->easy = easy_conn->send_pipe->head->next->ptr;
+ else
+ entry->easy = easy_conn->send_pipe->head->ptr;
+ }
+ }
+ /* Don't worry about overwriting recv_pipe head with send_pipe_head,
+ when action will be asked on the socket (see multi_socket()), the
+ head of the correct pipe will be taken according to the
+ action. */
+ }
+ }
+ else
+ /* just a precaution, this socket really SHOULD be in the hash already
+ but in case it isn't, we don't have to tell the app to remove it
+ either since it never got to know about it */
+ remove_sock_from_hash = FALSE;
+
+ if(remove_sock_from_hash) {
+ /* in this case 'entry' is always non-NULL */
+ if(multi->socket_cb)
+ multi->socket_cb(data,
+ s,
+ CURL_POLL_REMOVE,
+ multi->socket_userp,
+ entry->socketp);
+ sh_delentry(multi->sockhash, s);
+ }
+
+ }
+ }
+
+ memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
+ data->numsocks = num;
+}
+
+/*
+ * Curl_multi_closed()
+ *
+ * Used by the connect code to tell the multi_socket code that one of the
+ * sockets we were using is about to be closed. This function will then
+ * remove it from the sockethash for this handle to make the multi_socket API
+ * behave properly, especially for the case when libcurl will create another
+ * socket again and it gets the same file descriptor number.
+ */
+
+CURL_STATIC void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
+{
+ struct Curl_multi *multi = conn->data->multi;
+ if(multi) {
+ /* this is set if this connection is part of a handle that is added to
+ a multi handle, and only then this is necessary */
+ struct Curl_sh_entry *entry =
+ Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ if(entry) {
+ if(multi->socket_cb)
+ multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+ multi->socket_userp,
+ entry->socketp);
+
+ /* now remove it from the socket hash */
+ sh_delentry(multi->sockhash, s);
+ }
+ }
+}
+
+
+
+/*
+ * add_next_timeout()
+ *
+ * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
+ * when it has just been removed from the splay tree because the timeout has
+ * expired. This function is then to advance in the list to pick the next
+ * timeout to use (skip the already expired ones) and add this node back to
+ * the splay tree again.
+ *
+ * The splay tree only has each sessionhandle as a single node and the nearest
+ * timeout is used to sort it on.
+ */
+static CURLMcode add_next_timeout(struct timeval now,
+ struct Curl_multi *multi,
+ struct SessionHandle *d)
+{
+ struct timeval *tv = &d->state.expiretime;
+ struct curl_llist *list = d->state.timeoutlist;
+ struct curl_llist_element *e;
+
+ /* move over the timeout list for this specific handle and remove all
+ timeouts that are now passed tense and store the next pending
+ timeout in *tv */
+ for(e = list->head; e; ) {
+ struct curl_llist_element *n = e->next;
+ long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
+ if(diff <= 0)
+ /* remove outdated entry */
+ Curl_llist_remove(list, e, NULL);
+ else
+ /* the list is sorted so get out on the first mismatch */
+ break;
+ e = n;
+ }
+ e = list->head;
+ if(!e) {
+ /* clear the expire times within the handles that we remove from the
+ splay tree */
+ tv->tv_sec = 0;
+ tv->tv_usec = 0;
+ }
+ else {
+ /* copy the first entry to 'tv' */
+ memcpy(tv, e->ptr, sizeof(*tv));
+
+ /* remove first entry from list */
+ Curl_llist_remove(list, e, NULL);
+
+ /* insert this node again into the splay */
+ multi->timetree = Curl_splayinsert(*tv, multi->timetree,
+ &d->state.timenode);
+ }
+ return CURLM_OK;
+}
+
+static CURLMcode multi_socket(struct Curl_multi *multi,
+ bool checkall,
+ curl_socket_t s,
+ int ev_bitmask,
+ int *running_handles)
+{
+ CURLMcode result = CURLM_OK;
+ struct SessionHandle *data = NULL;
+ struct Curl_tree *t;
+ struct timeval now = Curl_tvnow();
+
+ if(checkall) {
+ /* *perform() deals with running_handles on its own */
+ result = curl_multi_perform(multi, running_handles);
+
+ /* walk through each easy handle and do the socket state change magic
+ and callbacks */
+ if(result != CURLM_BAD_HANDLE) {
+ data=multi->easyp;
+ while(data) {
+ singlesocket(multi, data);
+ data = data->next;
+ }
+ }
+
+ /* or should we fall-through and do the timer-based stuff? */
+ return result;
+ }
+ else if(s != CURL_SOCKET_TIMEOUT) {
+
+ struct Curl_sh_entry *entry =
+ Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ if(!entry)
+ /* Unmatched socket, we can't act on it but we ignore this fact. In
+ real-world tests it has been proved that libevent can in fact give
+ the application actions even though the socket was just previously
+ asked to get removed, so thus we better survive stray socket actions
+ and just move on. */
+ ;
+ else {
+ SIGPIPE_VARIABLE(pipe_st);
+
+ data = entry->easy;
+
+ if(data->magic != CURLEASY_MAGIC_NUMBER)
+ /* bad bad bad bad bad bad bad */
+ return CURLM_INTERNAL_ERROR;
+
+ /* If the pipeline is enabled, take the handle which is in the head of
+ the pipeline. If we should write into the socket, take the send_pipe
+ head. If we should read from the socket, take the recv_pipe head. */
+ if(data->easy_conn) {
+ if((ev_bitmask & CURL_POLL_OUT) &&
+ data->easy_conn->send_pipe &&
+ data->easy_conn->send_pipe->head)
+ data = data->easy_conn->send_pipe->head->ptr;
+ else if((ev_bitmask & CURL_POLL_IN) &&
+ data->easy_conn->recv_pipe &&
+ data->easy_conn->recv_pipe->head)
+ data = data->easy_conn->recv_pipe->head->ptr;
+ }
+
+ if(data->easy_conn &&
+ !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
+ /* set socket event bitmask if they're not locked */
+ data->easy_conn->cselect_bits = ev_bitmask;
+
+ sigpipe_ignore(data, &pipe_st);
+ result = multi_runsingle(multi, now, data);
+ sigpipe_restore(&pipe_st);
+
+ if(data->easy_conn &&
+ !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
+ /* clear the bitmask only if not locked */
+ data->easy_conn->cselect_bits = 0;
+
+ if(CURLM_OK >= result)
+ /* get the socket(s) and check if the state has been changed since
+ last */
+ singlesocket(multi, data);
+
+ /* Now we fall-through and do the timer-based stuff, since we don't want
+ to force the user to have to deal with timeouts as long as at least
+ one connection in fact has traffic. */
+
+ data = NULL; /* set data to NULL again to avoid calling
+ multi_runsingle() in case there's no need to */
+ now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop
+ may have taken some time */
+ }
+ }
+ else {
+ /* Asked to run due to time-out. Clear the 'lastcall' variable to force
+ update_timer() to trigger a callback to the app again even if the same
+ timeout is still the one to run after this call. That handles the case
+ when the application asks libcurl to run the timeout prematurely. */
+ memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
+ }
+
+ /*
+ * The loop following here will go on as long as there are expire-times left
+ * to process in the splay and 'data' will be re-assigned for every expired
+ * handle we deal with.
+ */
+ do {
+ /* the first loop lap 'data' can be NULL */
+ if(data) {
+ SIGPIPE_VARIABLE(pipe_st);
+
+ sigpipe_ignore(data, &pipe_st);
+ result = multi_runsingle(multi, now, data);
+ sigpipe_restore(&pipe_st);
+
+ if(CURLM_OK >= result)
+ /* get the socket(s) and check if the state has been changed since
+ last */
+ singlesocket(multi, data);
+ }
+
+ /* Check if there's one (more) expired timer to deal with! This function
+ extracts a matching node if there is one */
+
+ multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
+ if(t) {
+ data = t->payload; /* assign this for next loop */
+ (void)add_next_timeout(now, multi, t->payload);
+ }
+
+ } while(t);
+
+ *running_handles = multi->num_alive;
+ return result;
+}
+
+//#undef curl_multi_setopt
+CURLMcode curl_multi_setopt(CURLM *multi_handle,
+ CURLMoption option, ...)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ CURLMcode res = CURLM_OK;
+ va_list param;
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ va_start(param, option);
+
+ switch(option) {
+ case CURLMOPT_SOCKETFUNCTION:
+ multi->socket_cb = va_arg(param, curl_socket_callback);
+ break;
+ case CURLMOPT_SOCKETDATA:
+ multi->socket_userp = va_arg(param, void *);
+ break;
+ case CURLMOPT_PIPELINING:
+ multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLMOPT_TIMERFUNCTION:
+ multi->timer_cb = va_arg(param, curl_multi_timer_callback);
+ break;
+ case CURLMOPT_TIMERDATA:
+ multi->timer_userp = va_arg(param, void *);
+ break;
+ case CURLMOPT_MAXCONNECTS:
+ multi->maxconnects = va_arg(param, long);
+ break;
+ case CURLMOPT_MAX_HOST_CONNECTIONS:
+ multi->max_host_connections = va_arg(param, long);
+ break;
+ case CURLMOPT_MAX_PIPELINE_LENGTH:
+ multi->max_pipeline_length = va_arg(param, long);
+ break;
+ case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
+ multi->content_length_penalty_size = va_arg(param, long);
+ break;
+ case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
+ multi->chunk_length_penalty_size = va_arg(param, long);
+ break;
+ case CURLMOPT_PIPELINING_SITE_BL:
+ res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
+ &multi->pipelining_site_bl);
+ break;
+ case CURLMOPT_PIPELINING_SERVER_BL:
+ res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
+ &multi->pipelining_server_bl);
+ break;
+ case CURLMOPT_MAX_TOTAL_CONNECTIONS:
+ multi->max_total_connections = va_arg(param, long);
+ break;
+ default:
+ res = CURLM_UNKNOWN_OPTION;
+ break;
+ }
+ va_end(param);
+ return res;
+}
+
+/* we define curl_multi_socket() in the public multi.h header */
+//#undef curl_multi_socket
+
+CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+ int *running_handles)
+{
+ CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
+ 0, running_handles);
+ if(CURLM_OK >= result)
+ update_timer((struct Curl_multi *)multi_handle);
+ return result;
+}
+
+CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
+ int ev_bitmask, int *running_handles)
+{
+ CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
+ ev_bitmask, running_handles);
+ if(CURLM_OK >= result)
+ update_timer((struct Curl_multi *)multi_handle);
+ return result;
+}
+
+CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
+
+{
+ CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
+ TRUE, CURL_SOCKET_BAD, 0, running_handles);
+ if(CURLM_OK >= result)
+ update_timer((struct Curl_multi *)multi_handle);
+ return result;
+}
+
+static CURLMcode multi_timeout(struct Curl_multi *multi,
+ long *timeout_ms)
+{
+ static struct timeval tv_zero = {0, 0};
+
+ if(multi->timetree) {
+ /* we have a tree of expire times */
+ struct timeval now = Curl_tvnow();
+
+ /* splay the lowest to the bottom */
+ multi->timetree = Curl_splay(tv_zero, multi->timetree);
+
+ if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
+ /* some time left before expiration */
+ *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
+ if(!*timeout_ms)
+ /*
+ * Since we only provide millisecond resolution on the returned value
+ * and the diff might be less than one millisecond here, we don't
+ * return zero as that may cause short bursts of busyloops on fast
+ * processors while the diff is still present but less than one
+ * millisecond! instead we return 1 until the time is ripe.
+ */
+ *timeout_ms=1;
+ }
+ else
+ /* 0 means immediately */
+ *timeout_ms = 0;
+ }
+ else
+ *timeout_ms = -1;
+
+ return CURLM_OK;
+}
+
+CURLMcode curl_multi_timeout(CURLM *multi_handle,
+ long *timeout_ms)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+
+ /* First, make some basic checks that the CURLM handle is a good handle */
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ return multi_timeout(multi, timeout_ms);
+}
+
+/*
+ * Tell the application it should update its timers, if it subscribes to the
+ * update timer callback.
+ */
+static int update_timer(struct Curl_multi *multi)
+{
+ long timeout_ms;
+
+ if(!multi->timer_cb)
+ return 0;
+ if(multi_timeout(multi, &timeout_ms)) {
+ return -1;
+ }
+ if(timeout_ms < 0) {
+ static const struct timeval none={0, 0};
+ if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
+ multi->timer_lastcall = none;
+ /* there's no timeout now but there was one previously, tell the app to
+ disable it */
+ return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
+ }
+ return 0;
+ }
+
+ /* When multi_timeout() is done, multi->timetree points to the node with the
+ * timeout we got the (relative) time-out time for. We can thus easily check
+ * if this is the same (fixed) time as we got in a previous call and then
+ * avoid calling the callback again. */
+ if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
+ return 0;
+
+ multi->timer_lastcall = multi->timetree->key;
+
+ return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
+}
+
+static bool isHandleAtHead(struct SessionHandle *handle,
+ struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr = pipeline->head;
+ if(curr)
+ return (curr->ptr == handle) ? TRUE : FALSE;
+
+ return FALSE;
+}
+
+/*
+ * multi_freetimeout()
+ *
+ * Callback used by the llist system when a single timeout list entry is
+ * destroyed.
+ */
+static void multi_freetimeout(void *user, void *entryptr)
+{
+ (void)user;
+
+ /* the entry was plain malloc()'ed */
+ free(entryptr);
+}
+
+/*
+ * multi_addtimeout()
+ *
+ * Add a timestamp to the list of timeouts. Keep the list sorted so that head
+ * of list is always the timeout nearest in time.
+ *
+ */
+static CURLMcode
+multi_addtimeout(struct curl_llist *timeoutlist,
+ struct timeval *stamp)
+{
+ struct curl_llist_element *e;
+ struct timeval *timedup;
+ struct curl_llist_element *prev = NULL;
+
+ timedup = malloc(sizeof(*timedup));
+ if(!timedup)
+ return CURLM_OUT_OF_MEMORY;
+
+ /* copy the timestamp */
+ memcpy(timedup, stamp, sizeof(*timedup));
+
+ if(Curl_llist_count(timeoutlist)) {
+ /* find the correct spot in the list */
+ for(e = timeoutlist->head; e; e = e->next) {
+ struct timeval *checktime = e->ptr;
+ long diff = curlx_tvdiff(*checktime, *timedup);
+ if(diff > 0)
+ break;
+ prev = e;
+ }
+
+ }
+ /* else
+ this is the first timeout on the list */
+
+ if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
+ free(timedup);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ return CURLM_OK;
+}
+
+/*
+ * Curl_expire()
+ *
+ * given a number of milliseconds from now to use to set the 'act before
+ * this'-time for the transfer, to be extracted by curl_multi_timeout()
+ *
+ * Note that the timeout will be added to a queue of timeouts if it defines a
+ * moment in time that is later than the current head of queue.
+ *
+ * Pass zero to clear all timeout values for this handle.
+*/
+CURL_STATIC void Curl_expire(struct SessionHandle *data, long milli)
+{
+ struct Curl_multi *multi = data->multi;
+ struct timeval *nowp = &data->state.expiretime;
+ int rc;
+
+ /* this is only interesting while there is still an associated multi struct
+ remaining! */
+ if(!multi)
+ return;
+
+ if(!milli) {
+ /* No timeout, clear the time data. */
+ if(nowp->tv_sec || nowp->tv_usec) {
+ /* Since this is an cleared time, we must remove the previous entry from
+ the splay tree */
+ struct curl_llist *list = data->state.timeoutlist;
+
+ rc = Curl_splayremovebyaddr(multi->timetree,
+ &data->state.timenode,
+ &multi->timetree);
+ if(rc)
+ infof(data, "Internal error clearing splay node = %d\n", rc);
+
+ /* flush the timeout list too */
+ while(list->size > 0)
+ Curl_llist_remove(list, list->tail, NULL);
+
+#ifdef DEBUGBUILD
+ infof(data, "Expire cleared\n");
+#endif
+ nowp->tv_sec = 0;
+ nowp->tv_usec = 0;
+ }
+ }
+ else {
+ struct timeval set;
+
+ set = Curl_tvnow();
+ set.tv_sec += milli/1000;
+ set.tv_usec += (milli%1000)*1000;
+
+ if(set.tv_usec >= 1000000) {
+ set.tv_sec++;
+ set.tv_usec -= 1000000;
+ }
+
+ if(nowp->tv_sec || nowp->tv_usec) {
+ /* This means that the struct is added as a node in the splay tree.
+ Compare if the new time is earlier, and only remove-old/add-new if it
+ is. */
+ long diff = curlx_tvdiff(set, *nowp);
+ if(diff > 0) {
+ /* the new expire time was later so just add it to the queue
+ and get out */
+ multi_addtimeout(data->state.timeoutlist, &set);
+ return;
+ }
+
+ /* the new time is newer than the presently set one, so add the current
+ to the queue and update the head */
+ multi_addtimeout(data->state.timeoutlist, nowp);
+
+ /* Since this is an updated time, we must remove the previous entry from
+ the splay tree first and then re-add the new value */
+ rc = Curl_splayremovebyaddr(multi->timetree,
+ &data->state.timenode,
+ &multi->timetree);
+ if(rc)
+ infof(data, "Internal error removing splay node = %d\n", rc);
+ }
+
+ *nowp = set;
+ data->state.timenode.payload = data;
+ multi->timetree = Curl_splayinsert(*nowp,
+ multi->timetree,
+ &data->state.timenode);
+ }
+#if 0
+ Curl_splayprint(multi->timetree, 0, TRUE);
+#endif
+}
+
+/*
+ * Curl_expire_latest()
+ *
+ * This is like Curl_expire() but will only add a timeout node to the list of
+ * timers if there is no timeout that will expire before the given time.
+ *
+ * Use this function if the code logic risks calling this function many times
+ * or if there's no particular conditional wait in the code for this specific
+ * time-out period to expire.
+ *
+ */
+CURL_STATIC void Curl_expire_latest(struct SessionHandle *data, long milli)
+{
+ struct timeval *expire = &data->state.expiretime;
+
+ struct timeval set;
+
+ set = Curl_tvnow();
+ set.tv_sec += milli / 1000;
+ set.tv_usec += (milli % 1000) * 1000;
+
+ if(set.tv_usec >= 1000000) {
+ set.tv_sec++;
+ set.tv_usec -= 1000000;
+ }
+
+ if(expire->tv_sec || expire->tv_usec) {
+ /* This means that the struct is added as a node in the splay tree.
+ Compare if the new time is earlier, and only remove-old/add-new if it
+ is. */
+ long diff = curlx_tvdiff(set, *expire);
+ if(diff > 0)
+ /* the new expire time was later than the top time, so just skip this */
+ return;
+ }
+
+ /* Just add the timeout like normal */
+ Curl_expire(data, milli);
+}
+
+CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t s, void *hashp)
+{
+ struct Curl_sh_entry *there = NULL;
+ struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
+
+ if(s != CURL_SOCKET_BAD)
+ there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
+
+ if(!there)
+ return CURLM_BAD_SOCKET;
+
+ there->socketp = hashp;
+
+ return CURLM_OK;
+}
+
+CURL_STATIC size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
+{
+ return multi ? multi->max_host_connections : 0;
+}
+
+CURL_STATIC size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
+{
+ return multi ? multi->max_total_connections : 0;
+}
+
+CURL_STATIC size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
+{
+ return multi ? multi->max_pipeline_length : 0;
+}
+
+CURL_STATIC curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
+{
+ return multi ? multi->content_length_penalty_size : 0;
+}
+
+CURL_STATIC curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
+{
+ return multi ? multi->chunk_length_penalty_size : 0;
+}
+
+CURL_STATIC struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
+{
+ return multi->pipelining_site_bl;
+}
+
+CURL_STATIC struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
+{
+ return multi->pipelining_server_bl;
+}
+
+CURL_STATIC void Curl_multi_process_pending_handles(struct Curl_multi *multi)
+{
+ struct curl_llist_element *e = multi->pending->head;
+
+ while(e) {
+ struct SessionHandle *data = e->ptr;
+ struct curl_llist_element *next = e->next;
+
+ if(data->mstate == CURLM_STATE_CONNECT_PEND) {
+ multistate(data, CURLM_STATE_CONNECT);
+
+ /* Remove this node from the list */
+ Curl_llist_remove(multi->pending, e, NULL);
+
+ /* Make sure that the handle will be processed soonish. */
+ Curl_expire_latest(data, 1);
+ }
+
+ e = next; /* operate on next handle */
+ }
+}
+
+#ifdef DEBUGBUILD
+CURL_STATIC void Curl_multi_dump(const struct Curl_multi *multi_handle)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ int i;
+ fprintf(stderr, "* Multi status: %d handles, %d alive\n",
+ multi->num_easy, multi->num_alive);
+ for(data=multi->easyp; data; data = data->next) {
+ if(data->mstate < CURLM_STATE_COMPLETED) {
+ /* only display handles that are not completed */
+ fprintf(stderr, "handle %p, state %s, %d sockets\n",
+ (void *)data,
+ statename[data->mstate], data->numsocks);
+ for(i=0; i < data->numsocks; i++) {
+ curl_socket_t s = data->sockets[i];
+ struct Curl_sh_entry *entry =
+ Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ fprintf(stderr, "%d ", (int)s);
+ if(!entry) {
+ fprintf(stderr, "INTERNAL CONFUSION\n");
+ continue;
+ }
+ fprintf(stderr, "[%s %s] ",
+ entry->action&CURL_POLL_IN?"RECVING":"",
+ entry->action&CURL_POLL_OUT?"SENDING":"");
+ }
+ if(data->numsocks)
+ fprintf(stderr, "\n");
+ }
+ }
+}
+#endif
diff --git a/libcurl/src/lib/multihandle.h b/libcurl/src/lib/multihandle.h
new file mode 100644
index 0000000..d8b9d88
--- /dev/null
+++ b/libcurl/src/lib/multihandle.h
@@ -0,0 +1,143 @@
+#ifndef HEADER_CURL_MULTIHANDLE_H
+#define HEADER_CURL_MULTIHANDLE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct Curl_message {
+ /* the 'CURLMsg' is the part that is visible to the external user */
+ struct CURLMsg extmsg;
+};
+
+/* NOTE: if you add a state here, add the name to the statename[] array as
+ well!
+*/
+typedef enum {
+ CURLM_STATE_INIT, /* 0 - start in this state */
+ CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */
+ CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
+ CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
+ CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */
+ CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */
+ CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
+ CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
+ phase */
+ CURLM_STATE_WAITDO, /* 8 - wait for our turn to send the request */
+ CURLM_STATE_DO, /* 9 - start send off the request (part 1) */
+ CURLM_STATE_DOING, /* 10 - sending off the request (part 1) */
+ CURLM_STATE_DO_MORE, /* 11 - send off the request (part 2) */
+ CURLM_STATE_DO_DONE, /* 12 - done sending off request */
+ CURLM_STATE_WAITPERFORM, /* 13 - wait for our turn to read the response */
+ CURLM_STATE_PERFORM, /* 14 - transfer data */
+ CURLM_STATE_TOOFAST, /* 15 - wait because limit-rate exceeded */
+ CURLM_STATE_DONE, /* 16 - post data transfer operation */
+ CURLM_STATE_COMPLETED, /* 17 - operation complete */
+ CURLM_STATE_MSGSENT, /* 18 - the operation complete message is sent */
+ CURLM_STATE_LAST /* 19 - not a true state, never use this */
+} CURLMstate;
+
+/* we support N sockets per easy handle. Set the corresponding bit to what
+ action we should wait for */
+#define MAX_SOCKSPEREASYHANDLE 5
+#define GETSOCK_READABLE (0x00ff)
+#define GETSOCK_WRITABLE (0xff00)
+
+/* This is the struct known as CURLM on the outside */
+struct Curl_multi {
+ /* First a simple identifier to easier detect if a user mix up
+ this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
+ long type;
+
+ /* We have a doubly-linked circular list with easy handles */
+ struct SessionHandle *easyp;
+ struct SessionHandle *easylp; /* last node */
+
+ int num_easy; /* amount of entries in the linked list above. */
+ int num_alive; /* amount of easy handles that are added but have not yet
+ reached COMPLETE state */
+
+ struct curl_llist *msglist; /* a list of messages from completed transfers */
+
+ struct curl_llist *pending; /* SessionHandles that are in the
+ CURLM_STATE_CONNECT_PEND state */
+
+ /* callback function and user data pointer for the *socket() API */
+ curl_socket_callback socket_cb;
+ void *socket_userp;
+
+ /* Hostname cache */
+ struct curl_hash *hostcache;
+
+ /* timetree points to the splay-tree of time nodes to figure out expire
+ times of all currently set timers */
+ struct Curl_tree *timetree;
+
+ /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
+ the pluralis form, there can be more than one easy handle waiting on the
+ same actual socket) */
+ struct curl_hash *sockhash;
+
+ /* Whether pipelining is enabled for this multi handle */
+ bool pipelining_enabled;
+
+ /* Shared connection cache (bundles)*/
+ struct conncache *conn_cache;
+
+ /* This handle will be used for closing the cached connections in
+ curl_multi_cleanup() */
+ struct SessionHandle *closure_handle;
+
+ long maxconnects; /* if >0, a fixed limit of the maximum number of entries
+ we're allowed to grow the connection cache to */
+
+ long max_host_connections; /* if >0, a fixed limit of the maximum number
+ of connections per host */
+
+ long max_total_connections; /* if >0, a fixed limit of the maximum number
+ of connections in total */
+
+ long max_pipeline_length; /* if >0, maximum number of requests in a
+ pipeline */
+
+ long content_length_penalty_size; /* a connection with a
+ content-length bigger than
+ this is not considered
+ for pipelining */
+
+ long chunk_length_penalty_size; /* a connection with a chunk length
+ bigger than this is not
+ considered for pipelining */
+
+ struct curl_llist *pipelining_site_bl; /* List of sites that are blacklisted
+ from pipelining */
+
+ struct curl_llist *pipelining_server_bl; /* List of server types that are
+ blacklisted from pipelining */
+
+ /* timer callback and user data pointer for the *socket() API */
+ curl_multi_timer_callback timer_cb;
+ void *timer_userp;
+ struct timeval timer_lastcall; /* the fixed time for the timeout for the
+ previous callback */
+};
+
+#endif /* HEADER_CURL_MULTIHANDLE_H */
+
diff --git a/libcurl/src/lib/multiif.h b/libcurl/src/lib/multiif.h
new file mode 100644
index 0000000..10aab3e
--- /dev/null
+++ b/libcurl/src/lib/multiif.h
@@ -0,0 +1,93 @@
+#ifndef HEADER_CURL_MULTIIF_H
+#define HEADER_CURL_MULTIIF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Prototypes for library-wide functions provided by multi.c
+ */
+CURL_STATIC void Curl_expire(struct SessionHandle *data, long milli);
+CURL_STATIC void Curl_expire_latest(struct SessionHandle *data, long milli);
+
+CURL_STATIC bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
+CURL_STATIC void Curl_multi_handlePipeBreak(struct SessionHandle *data);
+
+/* Internal version of curl_multi_init() accepts size parameters for the
+ socket and connection hashes */
+CURL_STATIC struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
+
+/* the write bits start at bit 16 for the *getsock() bitmap */
+#define GETSOCK_WRITEBITSTART 16
+
+#define GETSOCK_BLANK 0 /* no bits set */
+
+/* set the bit for the given sock number to make the bitmap for writable */
+#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x)))
+
+/* set the bit for the given sock number to make the bitmap for readable */
+#define GETSOCK_READSOCK(x) (1 << (x))
+
+#ifdef DEBUGBUILD
+ /*
+ * Curl_multi_dump is not a stable public function, this is only meant to
+ * allow easier tracking of the internal handle's state and what sockets
+ * they use. Only for research and development DEBUGBUILD enabled builds.
+ */
+CURL_STATIC void Curl_multi_dump(const struct Curl_multi *multi_handle);
+#endif
+
+CURL_STATIC void Curl_multi_process_pending_handles(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
+CURL_STATIC size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_MAX_PIPELINE_LENGTH option */
+CURL_STATIC size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */
+CURL_STATIC curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE option */
+CURL_STATIC curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_PIPELINING_SITE_BL option */
+CURL_STATIC struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_PIPELINING_SERVER_BL option */
+CURL_STATIC struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
+CURL_STATIC size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
+
+/*
+ * Curl_multi_closed()
+ *
+ * Used by the connect code to tell the multi_socket code that one of the
+ * sockets we were using is about to be closed. This function will then
+ * remove it from the sockethash for this handle to make the multi_socket API
+ * behave properly, especially for the case when libcurl will create another
+ * socket again and it gets the same file descriptor number.
+ */
+
+CURL_STATIC void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
+
+#endif /* HEADER_CURL_MULTIIF_H */
diff --git a/libcurl/src/lib/netrc.c b/libcurl/src/lib/netrc.c
new file mode 100644
index 0000000..ce907c6
--- /dev/null
+++ b/libcurl/src/lib/netrc.c
@@ -0,0 +1,199 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include <curl/curl.h>
+#include "netrc.h"
+
+#include "strequal.h"
+#include "strtok.h"
+#include "rawstr.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* Get user and password from .netrc when given a machine name */
+
+enum host_lookup_state {
+ NOTHING,
+ HOSTFOUND, /* the 'machine' keyword was found */
+ HOSTVALID /* this is "our" machine! */
+};
+
+/*
+ * @unittest: 1304
+ *
+ * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
+ * in.
+ */
+CURL_STATIC int Curl_parsenetrc(const char *host,
+ char **loginp,
+ char **passwordp,
+ char *netrcfile)
+{
+ FILE *file;
+ int retcode=1;
+ int specific_login = (*loginp && **loginp != 0);
+ bool netrc_alloc = FALSE;
+ enum host_lookup_state state=NOTHING;
+
+ char state_login=0; /* Found a login keyword */
+ char state_password=0; /* Found a password keyword */
+ int state_our_login=FALSE; /* With specific_login, found *our* login name */
+
+#define NETRC DOT_CHAR "netrc"
+
+ if(!netrcfile) {
+ bool home_alloc = FALSE;
+ char *home = curl_getenv("HOME"); /* portable environment reader */
+ if(home) {
+ home_alloc = TRUE;
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
+ }
+ else {
+ struct passwd pw, *pw_res;
+ char pwbuf[1024];
+ if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
+ && pw_res) {
+ home = strdup(pw.pw_dir);
+ if(!home)
+ return CURLE_OUT_OF_MEMORY;
+ home_alloc = TRUE;
+ }
+#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
+ }
+ else {
+ struct passwd *pw;
+ pw= getpwuid(geteuid());
+ if(pw) {
+ home = pw->pw_dir;
+ }
+#endif
+ }
+
+ if(!home)
+ return retcode; /* no home directory found (or possibly out of memory) */
+
+ netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
+ if(home_alloc)
+ free(home);
+ if(!netrcfile) {
+ return -1;
+ }
+ netrc_alloc = TRUE;
+ }
+
+ file = fopen(netrcfile, "r");
+ if(netrc_alloc)
+ free(netrcfile);
+ if(file) {
+ char *tok;
+ char *tok_buf;
+ bool done=FALSE;
+ char netrcbuffer[256];
+ int netrcbuffsize = (int)sizeof(netrcbuffer);
+
+ while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
+ tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
+ while(!done && tok) {
+
+ if((*loginp && **loginp) && (*passwordp && **passwordp)) {
+ done=TRUE;
+ break;
+ }
+
+ switch(state) {
+ case NOTHING:
+ if(Curl_raw_equal("machine", tok)) {
+ /* the next tok is the machine name, this is in itself the
+ delimiter that starts the stuff entered for this machine,
+ after this we need to search for 'login' and
+ 'password'. */
+ state=HOSTFOUND;
+ }
+ break;
+ case HOSTFOUND:
+ if(Curl_raw_equal(host, tok)) {
+ /* and yes, this is our host! */
+ state=HOSTVALID;
+ retcode=0; /* we did find our host */
+ }
+ else
+ /* not our host */
+ state=NOTHING;
+ break;
+ case HOSTVALID:
+ /* we are now parsing sub-keywords concerning "our" host */
+ if(state_login) {
+ if(specific_login) {
+ state_our_login = Curl_raw_equal(*loginp, tok);
+ }
+ else {
+ free(*loginp);
+ *loginp = strdup(tok);
+ if(!*loginp) {
+ retcode = -1; /* allocation failed */
+ goto out;
+ }
+ }
+ state_login=0;
+ }
+ else if(state_password) {
+ if(state_our_login || !specific_login) {
+ free(*passwordp);
+ *passwordp = strdup(tok);
+ if(!*passwordp) {
+ retcode = -1; /* allocation failed */
+ goto out;
+ }
+ }
+ state_password=0;
+ }
+ else if(Curl_raw_equal("login", tok))
+ state_login=1;
+ else if(Curl_raw_equal("password", tok))
+ state_password=1;
+ else if(Curl_raw_equal("machine", tok)) {
+ /* ok, there's machine here go => */
+ state = HOSTFOUND;
+ state_our_login = FALSE;
+ }
+ break;
+ } /* switch (state) */
+
+ tok = strtok_r(NULL, " \t\n", &tok_buf);
+ } /* while(tok) */
+ } /* while fgets() */
+
+ out:
+ fclose(file);
+ }
+
+ return retcode;
+}
diff --git a/libcurl/src/lib/netrc.h b/libcurl/src/lib/netrc.h
new file mode 100644
index 0000000..6bd54dd
--- /dev/null
+++ b/libcurl/src/lib/netrc.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_NETRC_H
+#define HEADER_CURL_NETRC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
+CURL_STATIC int Curl_parsenetrc(const char *host,
+ char **loginp,
+ char **passwordp,
+ char *filename);
+ /* Assume: (*passwordp)[0]=0, host[0] != 0.
+ * If (*loginp)[0] = 0, search for login and password within a machine
+ * section in the netrc.
+ * If (*loginp)[0] != 0, search for password within machine and login.
+ */
+
+#endif /* HEADER_CURL_NETRC_H */
diff --git a/libcurl/src/lib/non-ascii.c b/libcurl/src/lib/non-ascii.c
new file mode 100644
index 0000000..d4673c5
--- /dev/null
+++ b/libcurl/src/lib/non-ascii.c
@@ -0,0 +1,338 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+#include <curl/curl.h>
+
+#include "non-ascii.h"
+#include "formdata.h"
+#include "sendf.h"
+#include "urldata.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef HAVE_ICONV
+#include <iconv.h>
+/* set default codesets for iconv */
+#ifndef CURL_ICONV_CODESET_OF_NETWORK
+#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
+#endif
+#ifndef CURL_ICONV_CODESET_FOR_UTF8
+#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
+#endif
+#define ICONV_ERROR (size_t)-1
+#endif /* HAVE_ICONV */
+
+/*
+ * Curl_convert_clone() returns a malloced copy of the source string (if
+ * returning CURLE_OK), with the data converted to network format.
+ */
+CURL_STATIC CURLcode Curl_convert_clone(struct SessionHandle *data,
+ const char *indata,
+ size_t insize,
+ char **outbuf)
+{
+ char *convbuf;
+ CURLcode result;
+
+ convbuf = malloc(insize);
+ if(!convbuf)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(convbuf, indata, insize);
+ result = Curl_convert_to_network(data, convbuf, insize);
+ if(result) {
+ free(convbuf);
+ return result;
+ }
+
+ *outbuf = convbuf; /* return the converted buffer */
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_convert_to_network() is an internal function for performing ASCII
+ * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ */
+CURL_STATIC CURLcode Curl_convert_to_network(struct SessionHandle *data,
+ char *buffer, size_t length)
+{
+ if(data->set.convtonetwork) {
+ /* use translation callback */
+ CURLcode result = data->set.convtonetwork(buffer, length);
+ if(result) {
+ failf(data,
+ "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
+ (int)result, curl_easy_strerror(result));
+ }
+
+ return result;
+ }
+ else {
+#ifdef HAVE_ICONV
+ /* do the translation ourselves */
+ char *input_ptr, *output_ptr;
+ size_t in_bytes, out_bytes, rc;
+ int error;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(data->outbound_cd == (iconv_t)-1) {
+ data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST);
+ if(data->outbound_cd == (iconv_t)-1) {
+ error = ERRNO;
+ failf(data,
+ "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
+ CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST,
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ error = ERRNO;
+ failf(data,
+ "The Curl_convert_to_network iconv call failed with errno %i: %s",
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+#else
+ failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
+ return CURLE_CONV_REQD;
+#endif /* HAVE_ICONV */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_convert_from_network() is an internal function for performing ASCII
+ * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ */
+CURL_STATIC CURLcode Curl_convert_from_network(struct SessionHandle *data,
+ char *buffer, size_t length)
+{
+ if(data->set.convfromnetwork) {
+ /* use translation callback */
+ CURLcode result = data->set.convfromnetwork(buffer, length);
+ if(result) {
+ failf(data,
+ "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
+ (int)result, curl_easy_strerror(result));
+ }
+
+ return result;
+ }
+ else {
+#ifdef HAVE_ICONV
+ /* do the translation ourselves */
+ char *input_ptr, *output_ptr;
+ size_t in_bytes, out_bytes, rc;
+ int error;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(data->inbound_cd == (iconv_t)-1) {
+ data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK);
+ if(data->inbound_cd == (iconv_t)-1) {
+ error = ERRNO;
+ failf(data,
+ "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
+ CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK,
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ error = ERRNO;
+ failf(data,
+ "Curl_convert_from_network iconv call failed with errno %i: %s",
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+#else
+ failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
+ return CURLE_CONV_REQD;
+#endif /* HAVE_ICONV */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_convert_from_utf8() is an internal function for performing UTF-8
+ * conversions on non-ASCII platforms.
+ */
+CURL_STATIC CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
+ char *buffer, size_t length)
+{
+ if(data->set.convfromutf8) {
+ /* use translation callback */
+ CURLcode result = data->set.convfromutf8(buffer, length);
+ if(result) {
+ failf(data,
+ "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
+ (int)result, curl_easy_strerror(result));
+ }
+
+ return result;
+ }
+ else {
+#ifdef HAVE_ICONV
+ /* do the translation ourselves */
+ const char *input_ptr;
+ char *output_ptr;
+ size_t in_bytes, out_bytes, rc;
+ int error;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(data->utf8_cd == (iconv_t)-1) {
+ data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_FOR_UTF8);
+ if(data->utf8_cd == (iconv_t)-1) {
+ error = ERRNO;
+ failf(data,
+ "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
+ CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_FOR_UTF8,
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ error = ERRNO;
+ failf(data,
+ "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ if(output_ptr < input_ptr) {
+ /* null terminate the now shorter output string */
+ *output_ptr = 0x00;
+ }
+#else
+ failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
+ return CURLE_CONV_REQD;
+#endif /* HAVE_ICONV */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Init conversion stuff for a SessionHandle
+ */
+CURL_STATIC void Curl_convert_init(struct SessionHandle *data)
+{
+#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
+ /* conversion descriptors for iconv calls */
+ data->outbound_cd = (iconv_t)-1;
+ data->inbound_cd = (iconv_t)-1;
+ data->utf8_cd = (iconv_t)-1;
+#else
+ (void)data;
+#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
+}
+
+/*
+ * Setup conversion stuff for a SessionHandle
+ */
+CURL_STATIC void Curl_convert_setup(struct SessionHandle *data)
+{
+ data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK);
+ data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST);
+ data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_FOR_UTF8);
+}
+
+/*
+ * Close conversion stuff for a SessionHandle
+ */
+
+CURL_STATIC void Curl_convert_close(struct SessionHandle *data)
+{
+#ifdef HAVE_ICONV
+ /* close iconv conversion descriptors */
+ if(data->inbound_cd != (iconv_t)-1) {
+ iconv_close(data->inbound_cd);
+ }
+ if(data->outbound_cd != (iconv_t)-1) {
+ iconv_close(data->outbound_cd);
+ }
+ if(data->utf8_cd != (iconv_t)-1) {
+ iconv_close(data->utf8_cd);
+ }
+#else
+ (void)data;
+#endif /* HAVE_ICONV */
+}
+
+/*
+ * Curl_convert_form() is used from http.c, this converts any form items that
+ need to be sent in the network encoding. Returns CURLE_OK on success.
+ */
+CURL_STATIC CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form)
+{
+ CURLcode result;
+
+ if(!data)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ while(form) {
+ if(form->type == FORM_DATA) {
+ result = Curl_convert_to_network(data, form->line, form->length);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result)
+ return result;
+ }
+
+ form = form->next;
+ }
+
+ return CURLE_OK;
+}
+
+#endif /* CURL_DOES_CONVERSIONS */
diff --git a/libcurl/src/lib/non-ascii.h b/libcurl/src/lib/non-ascii.h
new file mode 100644
index 0000000..fa0bf7b
--- /dev/null
+++ b/libcurl/src/lib/non-ascii.h
@@ -0,0 +1,63 @@
+#ifndef HEADER_CURL_NON_ASCII_H
+#define HEADER_CURL_NON_ASCII_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+#include "urldata.h"
+
+/*
+ * Curl_convert_clone() returns a malloced copy of the source string (if
+ * returning CURLE_OK), with the data converted to network format.
+ *
+ * If no conversion was needed *outbuf may be NULL.
+ */
+CURL_STATIC CURLcode Curl_convert_clone(struct SessionHandle *data,
+ const char *indata,
+ size_t insize,
+ char **outbuf);
+
+CURL_STATIC void Curl_convert_init(struct SessionHandle *data);
+CURL_STATIC void Curl_convert_setup(struct SessionHandle *data);
+CURL_STATIC void Curl_convert_close(struct SessionHandle *data);
+
+CURL_STATIC CURLcode Curl_convert_to_network(struct SessionHandle *data,
+ char *buffer, size_t length);
+CURL_STATIC CURLcode Curl_convert_from_network(struct SessionHandle *data,
+ char *buffer, size_t length);
+CURL_STATIC CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
+ char *buffer, size_t length);
+CURL_STATIC CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form);
+#else
+#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK)
+#define Curl_convert_init(x) Curl_nop_stmt
+#define Curl_convert_setup(x) Curl_nop_stmt
+#define Curl_convert_close(x) Curl_nop_stmt
+#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK)
+#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK)
+#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK)
+#define Curl_convert_form(a,b) CURLE_OK
+#endif
+
+#endif /* HEADER_CURL_NON_ASCII_H */
diff --git a/libcurl/src/lib/nonblock.c b/libcurl/src/lib/nonblock.c
new file mode 100644
index 0000000..dd5237a
--- /dev/null
+++ b/libcurl/src/lib/nonblock.c
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
+#include <sys/filio.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#include "nonblock.h"
+
+/*
+ * curlx_nonblock() set the given socket to either blocking or non-blocking
+ * mode based on the 'nonblock' boolean argument. This function is highly
+ * portable.
+ */
+CURL_STATIC int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
+ int nonblock /* TRUE or FALSE */)
+{
+#if defined(USE_BLOCKING_SOCKETS)
+
+ return 0; /* returns success */
+
+#elif defined(HAVE_FCNTL_O_NONBLOCK)
+
+ /* most recent unix versions */
+ int flags;
+ flags = sfcntl(sockfd, F_GETFL, 0);
+ if(nonblock)
+ return sfcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+ else
+ return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
+
+#elif defined(HAVE_IOCTL_FIONBIO)
+
+ /* older unix versions */
+ int flags = nonblock ? 1 : 0;
+ return ioctl(sockfd, FIONBIO, &flags);
+
+#elif defined(HAVE_IOCTLSOCKET_FIONBIO)
+
+ /* Windows */
+ unsigned long flags = nonblock ? 1UL : 0UL;
+ return ioctlsocket(sockfd, FIONBIO, &flags);
+
+#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
+
+ /* Amiga */
+ long flags = nonblock ? 1L : 0L;
+ return IoctlSocket(sockfd, FIONBIO, flags);
+
+#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
+
+ /* BeOS */
+ long b = nonblock ? 1L : 0L;
+ return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
+
+#else
+# error "no non-blocking method was found/used/set"
+#endif
+}
diff --git a/libcurl/src/lib/nonblock.h b/libcurl/src/lib/nonblock.h
new file mode 100644
index 0000000..52e0390
--- /dev/null
+++ b/libcurl/src/lib/nonblock.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_NONBLOCK_H
+#define HEADER_CURL_NONBLOCK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h> /* for curl_socket_t */
+
+CURL_STATIC int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
+ int nonblock /* TRUE or FALSE */);
+
+#endif /* HEADER_CURL_NONBLOCK_H */
+
diff --git a/libcurl/src/lib/nwlib.c b/libcurl/src/lib/nwlib.c
new file mode 100644
index 0000000..bd3f27e
--- /dev/null
+++ b/libcurl/src/lib/nwlib.c
@@ -0,0 +1,325 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef NETWARE /* Novell NetWare */
+
+#ifdef __NOVELL_LIBC__
+/* For native LibC-based NLM we need to register as a real lib. */
+#include <library.h>
+#include <netware.h>
+#include <screen.h>
+#include <nks/thread.h>
+#include <nks/synch.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef struct
+{
+ int _errno;
+ void *twentybytes;
+} libthreaddata_t;
+
+typedef struct
+{
+ int x;
+ int y;
+ int z;
+ void *tenbytes;
+ NXKey_t perthreadkey; /* if -1, no key obtained... */
+ NXMutex_t *lock;
+} libdata_t;
+
+int gLibId = -1;
+void *gLibHandle = (void *) NULL;
+rtag_t gAllocTag = (rtag_t) NULL;
+NXMutex_t *gLibLock = (NXMutex_t *) NULL;
+
+/* internal library function prototypes... */
+int DisposeLibraryData( void * );
+void DisposeThreadData( void * );
+int GetOrSetUpData( int id, libdata_t **data, libthreaddata_t **threaddata );
+
+
+int _NonAppStart( void *NLMHandle,
+ void *errorScreen,
+ const char *cmdLine,
+ const char *loadDirPath,
+ size_t uninitializedDataLength,
+ void *NLMFileHandle,
+ int (*readRoutineP)( int conn,
+ void *fileHandle, size_t offset,
+ size_t nbytes,
+ size_t *bytesRead,
+ void *buffer ),
+ size_t customDataOffset,
+ size_t customDataSize,
+ int messageCount,
+ const char **messages )
+{
+ NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
+
+#ifndef __GNUC__
+#pragma unused(cmdLine)
+#pragma unused(loadDirPath)
+#pragma unused(uninitializedDataLength)
+#pragma unused(NLMFileHandle)
+#pragma unused(readRoutineP)
+#pragma unused(customDataOffset)
+#pragma unused(customDataSize)
+#pragma unused(messageCount)
+#pragma unused(messages)
+#endif
+
+ /*
+ * Here we process our command line, post errors (to the error screen),
+ * perform initializations and anything else we need to do before being able
+ * to accept calls into us. If we succeed, we return non-zero and the NetWare
+ * Loader will leave us up, otherwise we fail to load and get dumped.
+ */
+ gAllocTag = AllocateResourceTag(NLMHandle,
+ "<library-name> memory allocations",
+ AllocSignature);
+
+ if(!gAllocTag) {
+ OutputToScreen(errorScreen, "Unable to allocate resource tag for "
+ "library memory allocations.\n");
+ return -1;
+ }
+
+ gLibId = register_library(DisposeLibraryData);
+
+ if(gLibId < -1) {
+ OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
+ return -1;
+ }
+
+ gLibHandle = NLMHandle;
+
+ gLibLock = NXMutexAlloc(0, 0, &liblock);
+
+ if(!gLibLock) {
+ OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Here we clean up any resources we allocated. Resource tags is a big part
+ * of what we created, but NetWare doesn't ask us to free those.
+ */
+void _NonAppStop( void )
+{
+ (void) unregister_library(gLibId);
+ NXMutexFree(gLibLock);
+}
+
+/*
+ * This function cannot be the first in the file for if the file is linked
+ * first, then the check-unload function's offset will be nlmname.nlm+0
+ * which is how to tell that there isn't one. When the check function is
+ * first in the linked objects, it is ambiguous. For this reason, we will
+ * put it inside this file after the stop function.
+ *
+ * Here we check to see if it's alright to ourselves to be unloaded. If not,
+ * we return a non-zero value. Right now, there isn't any reason not to allow
+ * it.
+ */
+int _NonAppCheckUnload( void )
+{
+ return 0;
+}
+
+int GetOrSetUpData(int id, libdata_t **appData,
+ libthreaddata_t **threadData )
+{
+ int err;
+ libdata_t *app_data;
+ libthreaddata_t *thread_data;
+ NXKey_t key;
+ NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
+
+ err = 0;
+ thread_data = (libthreaddata_t *) NULL;
+
+ /*
+ * Attempt to get our data for the application calling us. This is where we
+ * store whatever application-specific information we need to carry in
+ * support of calling applications.
+ */
+ app_data = (libdata_t *) get_app_data(id);
+
+ if(!app_data) {
+ /*
+ * This application hasn't called us before; set up application AND
+ * per-thread data. Of course, just in case a thread from this same
+ * application is calling us simultaneously, we better lock our application
+ * data-creation mutex. We also need to recheck for data after we acquire
+ * the lock because WE might be that other thread that was too late to
+ * create the data and the first thread in will have created it.
+ */
+ NXLock(gLibLock);
+
+ if(!(app_data = (libdata_t *) get_app_data(id))) {
+ app_data = malloc(sizeof(libdata_t));
+
+ if(app_data) {
+ memset(app_data, 0, sizeof(libdata_t));
+
+ app_data->tenbytes = malloc(10);
+ app_data->lock = NXMutexAlloc(0, 0, &liblock);
+
+ if(!app_data->tenbytes || !app_data->lock) {
+ if(app_data->lock)
+ NXMutexFree(app_data->lock);
+
+ free(app_data);
+ app_data = (libdata_t *) NULL;
+ err = ENOMEM;
+ }
+
+ if(app_data) {
+ /*
+ * Here we burn in the application data that we were trying to get
+ * by calling get_app_data(). Next time we call the first function,
+ * we'll get this data we're just now setting. We also go on here to
+ * establish the per-thread data for the calling thread, something
+ * we'll have to do on each application thread the first time
+ * it calls us.
+ */
+ err = set_app_data(gLibId, app_data);
+
+ if(err) {
+ free(app_data);
+ app_data = (libdata_t *) NULL;
+ err = ENOMEM;
+ }
+ else {
+ /* create key for thread-specific data... */
+ err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
+
+ if(err) /* (no more keys left?) */
+ key = -1;
+
+ app_data->perthreadkey = key;
+ }
+ }
+ }
+ }
+
+ NXUnlock(gLibLock);
+ }
+
+ if(app_data) {
+ key = app_data->perthreadkey;
+
+ if(key != -1 /* couldn't create a key? no thread data */
+ && !(err = NXKeyGetValue(key, (void **) &thread_data))
+ && !thread_data) {
+ /*
+ * Allocate the per-thread data for the calling thread. Regardless of
+ * whether there was already application data or not, this may be the
+ * first call by a new thread. The fact that we allocation 20 bytes on
+ * a pointer is not very important, this just helps to demonstrate that
+ * we can have arbitrarily complex per-thread data.
+ */
+ thread_data = malloc(sizeof(libthreaddata_t));
+
+ if(thread_data) {
+ thread_data->_errno = 0;
+ thread_data->twentybytes = malloc(20);
+
+ if(!thread_data->twentybytes) {
+ free(thread_data);
+ thread_data = (libthreaddata_t *) NULL;
+ err = ENOMEM;
+ }
+
+ if((err = NXKeySetValue(key, thread_data))) {
+ free(thread_data->twentybytes);
+ free(thread_data);
+ thread_data = (libthreaddata_t *) NULL;
+ }
+ }
+ }
+ }
+
+ if(appData)
+ *appData = app_data;
+
+ if(threadData)
+ *threadData = thread_data;
+
+ return err;
+}
+
+int DisposeLibraryData( void *data )
+{
+ if(data) {
+ void *tenbytes = ((libdata_t *) data)->tenbytes;
+
+ free(tenbytes);
+ free(data);
+ }
+
+ return 0;
+}
+
+void DisposeThreadData( void *data )
+{
+ if(data) {
+ void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
+
+ free(twentybytes);
+ free(data);
+ }
+}
+
+#else /* __NOVELL_LIBC__ */
+/* For native CLib-based NLM seems we can do a bit more simple. */
+#include <nwthread.h>
+
+int main ( void )
+{
+ /* initialize any globals here... */
+
+ /* do this if any global initializing was done
+ SynchronizeStart();
+ */
+ ExitThread (TSR_THREAD, 0);
+ return 0;
+}
+
+#endif /* __NOVELL_LIBC__ */
+
+#else /* NETWARE */
+
+#ifdef __POCC__
+# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */
+#endif
+
+#endif /* NETWARE */
diff --git a/libcurl/src/lib/nwos.c b/libcurl/src/lib/nwos.c
new file mode 100644
index 0000000..23ff2a7
--- /dev/null
+++ b/libcurl/src/lib/nwos.c
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef NETWARE /* Novell NetWare */
+
+#ifdef __NOVELL_LIBC__
+/* For native LibC-based NLM we need to do nothing. */
+int netware_init ( void )
+{
+ return 0;
+}
+
+#else /* __NOVELL_LIBC__ */
+
+/* For native CLib-based NLM we need to initialize the LONG namespace. */
+#include <nwnspace.h>
+#include <nwthread.h>
+#include <nwadv.h>
+/* Make the CLIB Ctx stuff link */
+#include <netdb.h>
+NETDB_DEFINE_CONTEXT
+/* Make the CLIB Inet stuff link */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+NETINET_DEFINE_CONTEXT
+
+int netware_init ( void )
+{
+ int rc = 0;
+ unsigned int myHandle = GetNLMHandle();
+ /* import UnAugmentAsterisk dynamically for NW4.x compatibility */
+ void (*pUnAugmentAsterisk)(int) = (void(*)(int))
+ ImportSymbol(myHandle, "UnAugmentAsterisk");
+ /* import UseAccurateCaseForPaths dynamically for NW3.x compatibility */
+ void (*pUseAccurateCaseForPaths)(int) = (void(*)(int))
+ ImportSymbol(myHandle, "UseAccurateCaseForPaths");
+ if(pUnAugmentAsterisk)
+ pUnAugmentAsterisk(1);
+ if(pUseAccurateCaseForPaths)
+ pUseAccurateCaseForPaths(1);
+ UnimportSymbol(myHandle, "UnAugmentAsterisk");
+ UnimportSymbol(myHandle, "UseAccurateCaseForPaths");
+ /* set long name space */
+ if((SetCurrentNameSpace(4) == 255)) {
+ rc = 1;
+ }
+ if((SetTargetNameSpace(4) == 255)) {
+ rc = rc + 2;
+ }
+ return rc;
+}
+
+/* dummy function to satisfy newer prelude */
+int __init_environment ( void )
+{
+ return 0;
+}
+
+/* dummy function to satisfy newer prelude */
+int __deinit_environment ( void )
+{
+ return 0;
+}
+
+#endif /* __NOVELL_LIBC__ */
+
+#endif /* NETWARE */
diff --git a/libcurl/src/lib/openldap.c b/libcurl/src/lib/openldap.c
new file mode 100644
index 0000000..bee552f
--- /dev/null
+++ b/libcurl/src/lib/openldap.c
@@ -0,0 +1,684 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
+ * Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)
+
+/*
+ * Notice that USE_OPENLDAP is only a source code selection switch. When
+ * libcurl is built with USE_OPENLDAP defined the libcurl source code that
+ * gets compiled is the code from openldap.c, otherwise the code that gets
+ * compiled is the code from ldap.c.
+ *
+ * When USE_OPENLDAP is defined a recent version of the OpenLDAP library
+ * might be required for compilation and runtime. In order to use ancient
+ * OpenLDAP library versions, USE_OPENLDAP shall not be defined.
+ */
+
+#include <ldap.h>
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "sendf.h"
+#include "vtls/vtls.h"
+#include "transfer.h"
+#include "curl_ldap.h"
+#include "curl_base64.h"
+#include "connect.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef _LDAP_PVT_H
+extern int ldap_pvt_url_scheme2proto(const char *);
+extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
+ LDAP **ld);
+#endif
+
+static CURLcode ldap_setup_connection(struct connectdata *conn);
+static CURLcode ldap_do(struct connectdata *conn, bool *done);
+static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
+static CURLcode ldap_connect(struct connectdata *conn, bool *done);
+static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
+static CURLcode ldap_disconnect(struct connectdata *conn, bool dead);
+
+static Curl_recv ldap_recv;
+
+/*
+ * LDAP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldap = {
+ "LDAP", /* scheme */
+ ldap_setup_connection, /* setup_connection */
+ ldap_do, /* do_it */
+ ldap_done, /* done */
+ ZERO_NULL, /* do_more */
+ ldap_connect, /* connect_it */
+ ldap_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ldap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAP, /* defport */
+ CURLPROTO_LDAP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * LDAPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldaps = {
+ "LDAPS", /* scheme */
+ ldap_setup_connection, /* setup_connection */
+ ldap_do, /* do_it */
+ ldap_done, /* done */
+ ZERO_NULL, /* do_more */
+ ldap_connect, /* connect_it */
+ ldap_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ldap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAPS, /* defport */
+ CURLPROTO_LDAP, /* protocol */
+ PROTOPT_SSL /* flags */
+};
+#endif
+
+static const char *url_errs[] = {
+ "success",
+ "out of memory",
+ "bad parameter",
+ "unrecognized scheme",
+ "unbalanced delimiter",
+ "bad URL",
+ "bad host or port",
+ "bad or missing attributes",
+ "bad or missing scope",
+ "bad or missing filter",
+ "bad or missing extensions"
+};
+
+typedef struct ldapconninfo {
+ LDAP *ld;
+ Curl_recv *recv; /* for stacking SSL handler */
+ Curl_send *send;
+ int proto;
+ int msgid;
+ bool ssldone;
+ bool sslinst;
+ bool didbind;
+} ldapconninfo;
+
+typedef struct ldapreqinfo {
+ int msgid;
+ int nument;
+} ldapreqinfo;
+
+static CURLcode ldap_setup_connection(struct connectdata *conn)
+{
+ ldapconninfo *li;
+ LDAPURLDesc *lud;
+ struct SessionHandle *data=conn->data;
+ int rc, proto;
+ CURLcode status;
+
+ rc = ldap_url_parse(data->change.url, &lud);
+ if(rc != LDAP_URL_SUCCESS) {
+ const char *msg = "url parsing problem";
+ status = CURLE_URL_MALFORMAT;
+ if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
+ if(rc == LDAP_URL_ERR_MEM)
+ status = CURLE_OUT_OF_MEMORY;
+ msg = url_errs[rc];
+ }
+ failf(conn->data, "LDAP local: %s", msg);
+ return status;
+ }
+ proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
+ ldap_free_urldesc(lud);
+
+ li = calloc(1, sizeof(ldapconninfo));
+ if(!li)
+ return CURLE_OUT_OF_MEMORY;
+ li->proto = proto;
+ conn->proto.generic = li;
+ connkeep(conn, "OpenLDAP default");
+ /* TODO:
+ * - provide option to choose SASL Binds instead of Simple
+ */
+ return CURLE_OK;
+}
+
+#ifdef USE_SSL
+static Sockbuf_IO ldapsb_tls;
+#endif
+
+static CURLcode ldap_connect(struct connectdata *conn, bool *done)
+{
+ ldapconninfo *li = conn->proto.generic;
+ struct SessionHandle *data = conn->data;
+ int rc, proto = LDAP_VERSION3;
+ char hosturl[1024];
+ char *ptr;
+
+ (void)done;
+
+ strcpy(hosturl, "ldap");
+ ptr = hosturl+4;
+ if(conn->handler->flags & PROTOPT_SSL)
+ *ptr++ = 's';
+ snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
+ conn->host.name, conn->remote_port);
+
+ rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
+ if(rc) {
+ failf(data, "LDAP local: Cannot connect to %s, %s",
+ hosturl, ldap_err2string(rc));
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
+
+#ifdef USE_SSL
+ if(conn->handler->flags & PROTOPT_SSL) {
+ CURLcode result;
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
+ if(result)
+ return result;
+ }
+#endif
+
+ return CURLE_OK;
+}
+
+static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
+{
+ ldapconninfo *li = conn->proto.generic;
+ struct SessionHandle *data = conn->data;
+ LDAPMessage *msg = NULL;
+ struct timeval tv = {0, 1}, *tvp;
+ int rc, err;
+ char *info = NULL;
+
+#ifdef USE_SSL
+ if(conn->handler->flags & PROTOPT_SSL) {
+ /* Is the SSL handshake complete yet? */
+ if(!li->ssldone) {
+ CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ &li->ssldone);
+ if(result || !li->ssldone)
+ return result;
+ }
+
+ /* Have we installed the libcurl SSL handlers into the sockbuf yet? */
+ if(!li->sslinst) {
+ Sockbuf *sb;
+ ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
+ ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn);
+ li->sslinst = TRUE;
+ li->recv = conn->recv[FIRSTSOCKET];
+ li->send = conn->send[FIRSTSOCKET];
+ }
+ }
+#endif
+
+ tvp = &tv;
+
+retry:
+ if(!li->didbind) {
+ char *binddn;
+ struct berval passwd;
+
+ if(conn->bits.user_passwd) {
+ binddn = conn->user;
+ passwd.bv_val = conn->passwd;
+ passwd.bv_len = strlen(passwd.bv_val);
+ }
+ else {
+ binddn = NULL;
+ passwd.bv_val = NULL;
+ passwd.bv_len = 0;
+ }
+ rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
+ NULL, NULL, &li->msgid);
+ if(rc)
+ return CURLE_LDAP_CANNOT_BIND;
+ li->didbind = TRUE;
+ if(tvp)
+ return CURLE_OK;
+ }
+
+ rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &msg);
+ if(rc < 0) {
+ failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc));
+ return CURLE_LDAP_CANNOT_BIND;
+ }
+ if(rc == 0) {
+ /* timed out */
+ return CURLE_OK;
+ }
+
+ rc = ldap_parse_result(li->ld, msg, &err, NULL, &info, NULL, NULL, 1);
+ if(rc) {
+ failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc));
+ return CURLE_LDAP_CANNOT_BIND;
+ }
+
+ /* Try to fallback to LDAPv2? */
+ if(err == LDAP_PROTOCOL_ERROR) {
+ int proto;
+ ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
+ if(proto == LDAP_VERSION3) {
+ if(info) {
+ ldap_memfree(info);
+ info = NULL;
+ }
+ proto = LDAP_VERSION2;
+ ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
+ li->didbind = FALSE;
+ goto retry;
+ }
+ }
+
+ if(err) {
+ failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc),
+ info ? info : "");
+ if(info)
+ ldap_memfree(info);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ if(info)
+ ldap_memfree(info);
+ conn->recv[FIRSTSOCKET] = ldap_recv;
+ *done = TRUE;
+
+ return CURLE_OK;
+}
+
+static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ ldapconninfo *li = conn->proto.generic;
+ (void) dead_connection;
+
+ if(li) {
+ if(li->ld) {
+ ldap_unbind_ext(li->ld, NULL, NULL);
+ li->ld = NULL;
+ }
+ conn->proto.generic = NULL;
+ free(li);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ldap_do(struct connectdata *conn, bool *done)
+{
+ ldapconninfo *li = conn->proto.generic;
+ ldapreqinfo *lr;
+ CURLcode status = CURLE_OK;
+ int rc = 0;
+ LDAPURLDesc *ludp = NULL;
+ int msgid;
+ struct SessionHandle *data=conn->data;
+
+ connkeep(conn, "OpenLDAP do");
+
+ infof(data, "LDAP local: %s\n", data->change.url);
+
+ rc = ldap_url_parse(data->change.url, &ludp);
+ if(rc != LDAP_URL_SUCCESS) {
+ const char *msg = "url parsing problem";
+ status = CURLE_URL_MALFORMAT;
+ if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
+ if(rc == LDAP_URL_ERR_MEM)
+ status = CURLE_OUT_OF_MEMORY;
+ msg = url_errs[rc];
+ }
+ failf(conn->data, "LDAP local: %s", msg);
+ return status;
+ }
+
+ rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope,
+ ludp->lud_filter, ludp->lud_attrs, 0,
+ NULL, NULL, NULL, 0, &msgid);
+ ldap_free_urldesc(ludp);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
+ return CURLE_LDAP_SEARCH_FAILED;
+ }
+ lr = calloc(1, sizeof(ldapreqinfo));
+ if(!lr)
+ return CURLE_OUT_OF_MEMORY;
+ lr->msgid = msgid;
+ data->req.protop = lr;
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+ *done = TRUE;
+ return CURLE_OK;
+}
+
+static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
+ bool premature)
+{
+ ldapreqinfo *lr = conn->data->req.protop;
+
+ (void)res;
+ (void)premature;
+
+ if(lr) {
+ /* if there was a search in progress, abandon it */
+ if(lr->msgid) {
+ ldapconninfo *li = conn->proto.generic;
+ ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
+ lr->msgid = 0;
+ }
+ conn->data->req.protop = NULL;
+ free(lr);
+ }
+
+ return CURLE_OK;
+}
+
+static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
+ size_t len, CURLcode *err)
+{
+ ldapconninfo *li = conn->proto.generic;
+ struct SessionHandle *data = conn->data;
+ ldapreqinfo *lr = data->req.protop;
+ int rc, ret;
+ LDAPMessage *msg = NULL;
+ LDAPMessage *ent;
+ BerElement *ber = NULL;
+ struct timeval tv = {0, 1};
+
+ (void)len;
+ (void)buf;
+ (void)sockindex;
+
+ rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg);
+ if(rc < 0) {
+ failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ *err = CURLE_AGAIN;
+ ret = -1;
+
+ /* timed out */
+ if(!msg)
+ return ret;
+
+ for(ent = ldap_first_message(li->ld, msg); ent;
+ ent = ldap_next_message(li->ld, ent)) {
+ struct berval bv, *bvals, **bvp = &bvals;
+ int binary = 0, msgtype;
+
+ msgtype = ldap_msgtype(ent);
+ if(msgtype == LDAP_RES_SEARCH_RESULT) {
+ int code;
+ char *info = NULL;
+ rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0);
+ if(rc) {
+ failf(data, "LDAP local: search ldap_parse_result %s",
+ ldap_err2string(rc));
+ *err = CURLE_LDAP_SEARCH_FAILED;
+ }
+ else if(code && code != LDAP_SIZELIMIT_EXCEEDED) {
+ failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc),
+ info ? info : "");
+ *err = CURLE_LDAP_SEARCH_FAILED;
+ }
+ else {
+ /* successful */
+ if(code == LDAP_SIZELIMIT_EXCEEDED)
+ infof(data, "There are more than %d entries\n", lr->nument);
+ data->req.size = data->req.bytecount;
+ *err = CURLE_OK;
+ ret = 0;
+ }
+ lr->msgid = 0;
+ ldap_memfree(info);
+ break;
+ }
+ else if(msgtype != LDAP_RES_SEARCH_ENTRY)
+ continue;
+
+ lr->nument++;
+ rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
+ if(rc < 0) {
+ /* TODO: verify that this is really how this return code should be
+ handled */
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ if(*err)
+ return -1;
+
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(*err)
+ return -1;
+
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ if(*err)
+ return -1;
+ data->req.bytecount += bv.bv_len + 5;
+
+ for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
+ rc == LDAP_SUCCESS;
+ rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
+ int i;
+
+ if(bv.bv_val == NULL) break;
+
+ if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
+ binary = 1;
+ else
+ binary = 0;
+
+ for(i=0; bvals[i].bv_val != NULL; i++) {
+ int binval = 0;
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ if(*err)
+ return -1;
+
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(*err)
+ return -1;
+
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
+ if(*err)
+ return -1;
+ data->req.bytecount += bv.bv_len + 2;
+
+ if(!binary) {
+ /* check for leading or trailing whitespace */
+ if(ISSPACE(bvals[i].bv_val[0]) ||
+ ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
+ binval = 1;
+ else {
+ /* check for unprintable characters */
+ unsigned int j;
+ for(j=0; j<bvals[i].bv_len; j++)
+ if(!ISPRINT(bvals[i].bv_val[j])) {
+ binval = 1;
+ break;
+ }
+ }
+ }
+ if(binary || binval) {
+ char *val_b64 = NULL;
+ size_t val_b64_sz = 0;
+ /* Binary value, encode to base64. */
+ CURLcode error = Curl_base64_encode(data,
+ bvals[i].bv_val,
+ bvals[i].bv_len,
+ &val_b64,
+ &val_b64_sz);
+ if(error) {
+ ber_memfree(bvals);
+ ber_free(ber, 0);
+ ldap_msgfree(msg);
+ *err = error;
+ return -1;
+ }
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
+ if(*err)
+ return -1;
+
+ data->req.bytecount += 2;
+ if(val_b64_sz > 0) {
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
+ val_b64_sz);
+ if(*err)
+ return -1;
+ free(val_b64);
+ data->req.bytecount += val_b64_sz;
+ }
+ }
+ else {
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
+ if(*err)
+ return -1;
+
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
+ bvals[i].bv_len);
+ if(*err)
+ return -1;
+
+ data->req.bytecount += bvals[i].bv_len + 1;
+ }
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ if(*err)
+ return -1;
+
+ data->req.bytecount++;
+ }
+ ber_memfree(bvals);
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ if(*err)
+ return -1;
+ data->req.bytecount++;
+ }
+ *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ if(*err)
+ return -1;
+ data->req.bytecount++;
+ ber_free(ber, 0);
+ }
+ ldap_msgfree(msg);
+ return ret;
+}
+
+#ifdef USE_SSL
+static int
+ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg)
+{
+ sbiod->sbiod_pvt = arg;
+ return 0;
+}
+
+static int
+ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod)
+{
+ sbiod->sbiod_pvt = NULL;
+ return 0;
+}
+
+/* We don't need to do anything because libcurl does it already */
+static int
+ldapsb_tls_close(Sockbuf_IO_Desc *sbiod)
+{
+ (void)sbiod;
+ return 0;
+}
+
+static int
+ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
+{
+ (void)arg;
+ if(opt == LBER_SB_OPT_DATA_READY) {
+ struct connectdata *conn = sbiod->sbiod_pvt;
+ return Curl_ssl_data_pending(conn, FIRSTSOCKET);
+ }
+ return 0;
+}
+
+static ber_slen_t
+ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct connectdata *conn = sbiod->sbiod_pvt;
+ ldapconninfo *li = conn->proto.generic;
+ ber_slen_t ret;
+ CURLcode err = CURLE_RECV_ERROR;
+
+ ret = li->recv(conn, FIRSTSOCKET, buf, len, &err);
+ if(ret < 0 && err == CURLE_AGAIN) {
+ SET_SOCKERRNO(EWOULDBLOCK);
+ }
+ return ret;
+}
+
+static ber_slen_t
+ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct connectdata *conn = sbiod->sbiod_pvt;
+ ldapconninfo *li = conn->proto.generic;
+ ber_slen_t ret;
+ CURLcode err = CURLE_SEND_ERROR;
+
+ ret = li->send(conn, FIRSTSOCKET, buf, len, &err);
+ if(ret < 0 && err == CURLE_AGAIN) {
+ SET_SOCKERRNO(EWOULDBLOCK);
+ }
+ return ret;
+}
+
+static Sockbuf_IO ldapsb_tls =
+{
+ ldapsb_tls_setup,
+ ldapsb_tls_remove,
+ ldapsb_tls_ctrl,
+ ldapsb_tls_read,
+ ldapsb_tls_write,
+ ldapsb_tls_close
+};
+#endif /* USE_SSL */
+
+#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */
diff --git a/libcurl/src/lib/parsedate.c b/libcurl/src/lib/parsedate.c
new file mode 100644
index 0000000..4297696
--- /dev/null
+++ b/libcurl/src/lib/parsedate.c
@@ -0,0 +1,583 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ A brief summary of the date string formats this parser groks:
+
+ RFC 2616 3.3.1
+
+ Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+
+ we support dates without week day name:
+
+ 06 Nov 1994 08:49:37 GMT
+ 06-Nov-94 08:49:37 GMT
+ Nov 6 08:49:37 1994
+
+ without the time zone:
+
+ 06 Nov 1994 08:49:37
+ 06-Nov-94 08:49:37
+
+ weird order:
+
+ 1994 Nov 6 08:49:37 (GNU date fails)
+ GMT 08:49:37 06-Nov-94 Sunday
+ 94 6 Nov 08:49:37 (GNU date fails)
+
+ time left out:
+
+ 1994 Nov 6
+ 06-Nov-94
+ Sun Nov 6 94
+
+ unusual separators:
+
+ 1994.Nov.6
+ Sun/Nov/6/94/GMT
+
+ commonly used time zone names:
+
+ Sun, 06 Nov 1994 08:49:37 CET
+ 06 Nov 1994 08:49:37 EST
+
+ time zones specified using RFC822 style:
+
+ Sun, 12 Sep 2004 15:05:58 -0700
+ Sat, 11 Sep 2004 21:32:11 +0200
+
+ compact numerical date strings:
+
+ 20040912 15:05:58 -0700
+ 20040911 +0200
+
+*/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <curl/curl.h>
+#include "rawstr.h"
+#include "warnless.h"
+#include "parsedate.h"
+
+static const char * const Curl_wkday[] =
+{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+static const char * const weekday[] =
+{ "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday", "Sunday" };
+static const char * const Curl_month[]=
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+struct tzinfo {
+ char name[5];
+ int offset; /* +/- in minutes */
+};
+
+/*
+ * parsedate()
+ *
+ * Returns:
+ *
+ * PARSEDATE_OK - a fine conversion
+ * PARSEDATE_FAIL - failed to convert
+ * PARSEDATE_LATER - time overflow at the far end of time_t
+ * PARSEDATE_SOONER - time underflow at the low end of time_t
+ */
+
+static int parsedate(const char *date, time_t *output);
+
+#define PARSEDATE_OK 0
+#define PARSEDATE_FAIL -1
+#define PARSEDATE_LATER 1
+#define PARSEDATE_SOONER 2
+
+/* Here's a bunch of frequently used time zone names. These were supported
+ by the old getdate parser. */
+#define tDAYZONE -60 /* offset for daylight savings time */
+static const struct tzinfo tz[]= {
+ {"GMT", 0}, /* Greenwich Mean */
+ {"UTC", 0}, /* Universal (Coordinated) */
+ {"WET", 0}, /* Western European */
+ {"BST", 0 tDAYZONE}, /* British Summer */
+ {"WAT", 60}, /* West Africa */
+ {"AST", 240}, /* Atlantic Standard */
+ {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */
+ {"EST", 300}, /* Eastern Standard */
+ {"EDT", 300 tDAYZONE}, /* Eastern Daylight */
+ {"CST", 360}, /* Central Standard */
+ {"CDT", 360 tDAYZONE}, /* Central Daylight */
+ {"MST", 420}, /* Mountain Standard */
+ {"MDT", 420 tDAYZONE}, /* Mountain Daylight */
+ {"PST", 480}, /* Pacific Standard */
+ {"PDT", 480 tDAYZONE}, /* Pacific Daylight */
+ {"YST", 540}, /* Yukon Standard */
+ {"YDT", 540 tDAYZONE}, /* Yukon Daylight */
+ {"HST", 600}, /* Hawaii Standard */
+ {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */
+ {"CAT", 600}, /* Central Alaska */
+ {"AHST", 600}, /* Alaska-Hawaii Standard */
+ {"NT", 660}, /* Nome */
+ {"IDLW", 720}, /* International Date Line West */
+ {"CET", -60}, /* Central European */
+ {"MET", -60}, /* Middle European */
+ {"MEWT", -60}, /* Middle European Winter */
+ {"MEST", -60 tDAYZONE}, /* Middle European Summer */
+ {"CEST", -60 tDAYZONE}, /* Central European Summer */
+ {"MESZ", -60 tDAYZONE}, /* Middle European Summer */
+ {"FWT", -60}, /* French Winter */
+ {"FST", -60 tDAYZONE}, /* French Summer */
+ {"EET", -120}, /* Eastern Europe, USSR Zone 1 */
+ {"WAST", -420}, /* West Australian Standard */
+ {"WADT", -420 tDAYZONE}, /* West Australian Daylight */
+ {"CCT", -480}, /* China Coast, USSR Zone 7 */
+ {"JST", -540}, /* Japan Standard, USSR Zone 8 */
+ {"EAST", -600}, /* Eastern Australian Standard */
+ {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */
+ {"GST", -600}, /* Guam Standard, USSR Zone 9 */
+ {"NZT", -720}, /* New Zealand */
+ {"NZST", -720}, /* New Zealand Standard */
+ {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */
+ {"IDLE", -720}, /* International Date Line East */
+ /* Next up: Military timezone names. RFC822 allowed these, but (as noted in
+ RFC 1123) had their signs wrong. Here we use the correct signs to match
+ actual military usage.
+ */
+ {"A", +1 * 60}, /* Alpha */
+ {"B", +2 * 60}, /* Bravo */
+ {"C", +3 * 60}, /* Charlie */
+ {"D", +4 * 60}, /* Delta */
+ {"E", +5 * 60}, /* Echo */
+ {"F", +6 * 60}, /* Foxtrot */
+ {"G", +7 * 60}, /* Golf */
+ {"H", +8 * 60}, /* Hotel */
+ {"I", +9 * 60}, /* India */
+ /* "J", Juliet is not used as a timezone, to indicate the observer's local
+ time */
+ {"K", +10 * 60}, /* Kilo */
+ {"L", +11 * 60}, /* Lima */
+ {"M", +12 * 60}, /* Mike */
+ {"N", -1 * 60}, /* November */
+ {"O", -2 * 60}, /* Oscar */
+ {"P", -3 * 60}, /* Papa */
+ {"Q", -4 * 60}, /* Quebec */
+ {"R", -5 * 60}, /* Romeo */
+ {"S", -6 * 60}, /* Sierra */
+ {"T", -7 * 60}, /* Tango */
+ {"U", -8 * 60}, /* Uniform */
+ {"V", -9 * 60}, /* Victor */
+ {"W", -10 * 60}, /* Whiskey */
+ {"X", -11 * 60}, /* X-ray */
+ {"Y", -12 * 60}, /* Yankee */
+ {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */
+};
+
+/* returns:
+ -1 no day
+ 0 monday - 6 sunday
+*/
+
+static int checkday(const char *check, size_t len)
+{
+ int i;
+ const char * const *what;
+ bool found= FALSE;
+ if(len > 3)
+ what = &weekday[0];
+ else
+ what = &Curl_wkday[0];
+ for(i=0; i<7; i++) {
+ if(Curl_raw_equal(check, what[0])) {
+ found=TRUE;
+ break;
+ }
+ what++;
+ }
+ return found?i:-1;
+}
+
+static int checkmonth(const char *check)
+{
+ int i;
+ const char * const *what;
+ bool found= FALSE;
+
+ what = &Curl_month[0];
+ for(i=0; i<12; i++) {
+ if(Curl_raw_equal(check, what[0])) {
+ found=TRUE;
+ break;
+ }
+ what++;
+ }
+ return found?i:-1; /* return the offset or -1, no real offset is -1 */
+}
+
+/* return the time zone offset between GMT and the input one, in number
+ of seconds or -1 if the timezone wasn't found/legal */
+
+static int checktz(const char *check)
+{
+ unsigned int i;
+ const struct tzinfo *what;
+ bool found= FALSE;
+
+ what = tz;
+ for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
+ if(Curl_raw_equal(check, what->name)) {
+ found=TRUE;
+ break;
+ }
+ what++;
+ }
+ return found?what->offset*60:-1;
+}
+
+static void skip(const char **date)
+{
+ /* skip everything that aren't letters or digits */
+ while(**date && !ISALNUM(**date))
+ (*date)++;
+}
+
+enum assume {
+ DATE_MDAY,
+ DATE_YEAR,
+ DATE_TIME
+};
+
+/* this is a clone of 'struct tm' but with all fields we don't need or use
+ cut out */
+struct my_tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+};
+
+/* struct tm to time since epoch in GMT time zone.
+ * This is similar to the standard mktime function but for GMT only, and
+ * doesn't suffer from the various bugs and portability problems that
+ * some systems' implementations have.
+ */
+static time_t my_timegm(struct my_tm *tm)
+{
+ static const int month_days_cumulative [12] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ int month, year, leap_days;
+
+ if(tm->tm_year < 70)
+ /* we don't support years before 1970 as they will cause this function
+ to return a negative value */
+ return -1;
+
+ year = tm->tm_year + 1900;
+ month = tm->tm_mon;
+ if(month < 0) {
+ year += (11 - month) / 12;
+ month = 11 - (11 - month) % 12;
+ }
+ else if(month >= 12) {
+ year -= month / 12;
+ month = month % 12;
+ }
+
+ leap_days = year - (tm->tm_mon <= 1);
+ leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
+ - (1969 / 4) + (1969 / 100) - (1969 / 400));
+
+ return ((((time_t) (year - 1970) * 365
+ + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24
+ + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+}
+
+/*
+ * parsedate()
+ *
+ * Returns:
+ *
+ * PARSEDATE_OK - a fine conversion
+ * PARSEDATE_FAIL - failed to convert
+ * PARSEDATE_LATER - time overflow at the far end of time_t
+ * PARSEDATE_SOONER - time underflow at the low end of time_t
+ */
+
+static int parsedate(const char *date, time_t *output)
+{
+ time_t t = 0;
+ int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */
+ int monnum=-1; /* month of the year number, 0-11 */
+ int mdaynum=-1; /* day of month, 1 - 31 */
+ int hournum=-1;
+ int minnum=-1;
+ int secnum=-1;
+ int yearnum=-1;
+ int tzoff=-1;
+ struct my_tm tm;
+ enum assume dignext = DATE_MDAY;
+ const char *indate = date; /* save the original pointer */
+ int part = 0; /* max 6 parts */
+
+ while(*date && (part < 6)) {
+ bool found=FALSE;
+
+ skip(&date);
+
+ if(ISALPHA(*date)) {
+ /* a name coming up */
+ char buf[32]="";
+ size_t len;
+ if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz]", buf))
+ len = strlen(buf);
+ else
+ len = 0;
+
+ if(wdaynum == -1) {
+ wdaynum = checkday(buf, len);
+ if(wdaynum != -1)
+ found = TRUE;
+ }
+ if(!found && (monnum == -1)) {
+ monnum = checkmonth(buf);
+ if(monnum != -1)
+ found = TRUE;
+ }
+
+ if(!found && (tzoff == -1)) {
+ /* this just must be a time zone string */
+ tzoff = checktz(buf);
+ if(tzoff != -1)
+ found = TRUE;
+ }
+
+ if(!found)
+ return PARSEDATE_FAIL; /* bad string */
+
+ date += len;
+ }
+ else if(ISDIGIT(*date)) {
+ /* a digit */
+ int val;
+ char *end;
+ if((secnum == -1) &&
+ (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
+ /* time stamp! */
+ date += 8;
+ }
+ else if((secnum == -1) &&
+ (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) {
+ /* time stamp without seconds */
+ date += 5;
+ secnum = 0;
+ }
+ else {
+ long lval;
+ int error;
+ int old_errno;
+
+ old_errno = ERRNO;
+ SET_ERRNO(0);
+ lval = strtol(date, &end, 10);
+ error = ERRNO;
+ if(error != old_errno)
+ SET_ERRNO(old_errno);
+
+ if(error)
+ return PARSEDATE_FAIL;
+
+#if LONG_MAX != INT_MAX
+ if((lval > (long)INT_MAX) || (lval < (long)INT_MIN))
+ return PARSEDATE_FAIL;
+#endif
+
+ val = curlx_sltosi(lval);
+
+ if((tzoff == -1) &&
+ ((end - date) == 4) &&
+ (val <= 1400) &&
+ (indate< date) &&
+ ((date[-1] == '+' || date[-1] == '-'))) {
+ /* four digits and a value less than or equal to 1400 (to take into
+ account all sorts of funny time zone diffs) and it is preceded
+ with a plus or minus. This is a time zone indication. 1400 is
+ picked since +1300 is frequently used and +1400 is mentioned as
+ an edge number in the document "ISO C 200X Proposal: Timezone
+ Functions" at http://david.tribble.com/text/c0xtimezone.html If
+ anyone has a more authoritative source for the exact maximum time
+ zone offsets, please speak up! */
+ found = TRUE;
+ tzoff = (val/100 * 60 + val%100)*60;
+
+ /* the + and - prefix indicates the local time compared to GMT,
+ this we need ther reversed math to get what we want */
+ tzoff = date[-1]=='+'?-tzoff:tzoff;
+ }
+
+ if(((end - date) == 8) &&
+ (yearnum == -1) &&
+ (monnum == -1) &&
+ (mdaynum == -1)) {
+ /* 8 digits, no year, month or day yet. This is YYYYMMDD */
+ found = TRUE;
+ yearnum = val/10000;
+ monnum = (val%10000)/100-1; /* month is 0 - 11 */
+ mdaynum = val%100;
+ }
+
+ if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) {
+ if((val > 0) && (val<32)) {
+ mdaynum = val;
+ found = TRUE;
+ }
+ dignext = DATE_YEAR;
+ }
+
+ if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) {
+ yearnum = val;
+ found = TRUE;
+ if(yearnum < 1900) {
+ if(yearnum > 70)
+ yearnum += 1900;
+ else
+ yearnum += 2000;
+ }
+ if(mdaynum == -1)
+ dignext = DATE_MDAY;
+ }
+
+ if(!found)
+ return PARSEDATE_FAIL;
+
+ date = end;
+ }
+ }
+
+ part++;
+ }
+
+ if(-1 == secnum)
+ secnum = minnum = hournum = 0; /* no time, make it zero */
+
+ if((-1 == mdaynum) ||
+ (-1 == monnum) ||
+ (-1 == yearnum))
+ /* lacks vital info, fail */
+ return PARSEDATE_FAIL;
+
+#if SIZEOF_TIME_T < 5
+ /* 32 bit time_t can only hold dates to the beginning of 2038 */
+ if(yearnum > 2037) {
+ *output = 0x7fffffff;
+ return PARSEDATE_LATER;
+ }
+#endif
+
+ if(yearnum < 1970) {
+ *output = 0;
+ return PARSEDATE_SOONER;
+ }
+
+ if((mdaynum > 31) || (monnum > 11) ||
+ (hournum > 23) || (minnum > 59) || (secnum > 60))
+ return PARSEDATE_FAIL; /* clearly an illegal date */
+
+ tm.tm_sec = secnum;
+ tm.tm_min = minnum;
+ tm.tm_hour = hournum;
+ tm.tm_mday = mdaynum;
+ tm.tm_mon = monnum;
+ tm.tm_year = yearnum - 1900;
+
+ /* my_timegm() returns a time_t. time_t is often 32 bits, even on many
+ architectures that feature 64 bit 'long'.
+
+ Some systems have 64 bit time_t and deal with years beyond 2038. However,
+ even on some of the systems with 64 bit time_t mktime() returns -1 for
+ dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
+ */
+ t = my_timegm(&tm);
+
+ /* time zone adjust (cast t to int to compare to negative one) */
+ if(-1 != (int)t) {
+
+ /* Add the time zone diff between local time zone and GMT. */
+ long delta = (long)(tzoff!=-1?tzoff:0);
+
+ if((delta>0) && (t > LONG_MAX - delta)) {
+ *output = 0x7fffffff;
+ return PARSEDATE_LATER; /* time_t overflow */
+ }
+
+ t += delta;
+ }
+
+ *output = t;
+
+ return PARSEDATE_OK;
+}
+
+time_t curl_getdate(const char *p, const time_t *now)
+{
+ time_t parsed = -1;
+ int rc = parsedate(p, &parsed);
+ (void)now; /* legacy argument from the past that we ignore */
+
+ switch(rc) {
+ case PARSEDATE_OK:
+ case PARSEDATE_LATER:
+ case PARSEDATE_SOONER:
+ return parsed;
+ }
+ /* everything else is fail */
+ return -1;
+}
+
+/*
+ * Curl_gmtime() is a gmtime() replacement for portability. Do not use the
+ * gmtime_r() or gmtime() functions anywhere else but here.
+ *
+ */
+
+CURL_STATIC CURLcode Curl_gmtime(time_t intime, struct tm *store)
+{
+ const struct tm *tm;
+#ifdef HAVE_GMTIME_R
+ /* thread-safe version */
+ tm = (struct tm *)gmtime_r(&intime, store);
+#else
+ tm = gmtime(&intime);
+ if(tm)
+ *store = *tm; /* copy the pointed struct to the local copy */
+#endif
+
+ if(!tm)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_OK;
+}
diff --git a/libcurl/src/lib/parsedate.h b/libcurl/src/lib/parsedate.h
new file mode 100644
index 0000000..c845e55
--- /dev/null
+++ b/libcurl/src/lib/parsedate.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_PARSEDATE_H
+#define HEADER_CURL_PARSEDATE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+//extern const char * const Curl_wkday[7];
+//extern const char * const Curl_month[12];
+
+CURL_STATIC CURLcode Curl_gmtime(time_t intime, struct tm *store);
+
+#endif /* HEADER_CURL_PARSEDATE_H */
+
diff --git a/libcurl/src/lib/pingpong.c b/libcurl/src/lib/pingpong.c
new file mode 100644
index 0000000..d521319
--- /dev/null
+++ b/libcurl/src/lib/pingpong.c
@@ -0,0 +1,507 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * 'pingpong' is for generic back-and-forth support functions used by FTP,
+ * IMAP, POP3, SMTP and whatever more that likes them.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "urldata.h"
+#include "sendf.h"
+#include "select.h"
+#include "progress.h"
+#include "speedcheck.h"
+#include "pingpong.h"
+#include "multiif.h"
+#include "non-ascii.h"
+#include "vtls/vtls.h"
+#include "curl_printf.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef USE_PINGPONG
+
+/* Returns timeout in ms. 0 or negative number means the timeout has already
+ triggered */
+CURL_STATIC long Curl_pp_state_timeout(struct pingpong *pp)
+{
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data=conn->data;
+ long timeout_ms; /* in milliseconds */
+ long timeout2_ms; /* in milliseconds */
+ long response_time= (data->set.server_response_timeout)?
+ data->set.server_response_timeout: pp->response_time;
+
+ /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine
+ remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is
+ supposed to govern the response for any given server response, not for
+ the time from connect to the given server response. */
+
+ /* Without a requested timeout, we only wait 'response_time' seconds for the
+ full response to arrive before we bail out */
+ timeout_ms = response_time -
+ Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */
+
+ if(data->set.timeout) {
+ /* if timeout is requested, find out how much remaining time we have */
+ timeout2_ms = data->set.timeout - /* timeout time */
+ Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
+
+ /* pick the lowest number */
+ timeout_ms = CURLMIN(timeout_ms, timeout2_ms);
+ }
+
+ return timeout_ms;
+}
+
+/*
+ * Curl_pp_statemach()
+ */
+CURL_STATIC CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
+{
+ struct connectdata *conn = pp->conn;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ int rc;
+ long interval_ms;
+ long timeout_ms = Curl_pp_state_timeout(pp);
+ struct SessionHandle *data=conn->data;
+ CURLcode result = CURLE_OK;
+
+ if(timeout_ms <=0 ) {
+ failf(data, "server response timeout");
+ return CURLE_OPERATION_TIMEDOUT; /* already too little time */
+ }
+
+ if(block) {
+ interval_ms = 1000; /* use 1 second timeout intervals */
+ if(timeout_ms < interval_ms)
+ interval_ms = timeout_ms;
+ }
+ else
+ interval_ms = 0; /* immediate */
+
+ if(Curl_pp_moredata(pp))
+ /* We are receiving and there is data in the cache so just read it */
+ rc = 1;
+ else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
+ /* We are receiving and there is data ready in the SSL library */
+ rc = 1;
+ else
+ rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
+ pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
+ interval_ms);
+
+ if(block) {
+ /* if we didn't wait, we don't have to spend time on this now */
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(data, Curl_tvnow());
+
+ if(result)
+ return result;
+ }
+
+ if(rc == -1) {
+ failf(data, "select/poll error");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else if(rc)
+ result = pp->statemach_act(conn);
+
+ return result;
+}
+
+/* initialize stuff to prepare for reading a fresh new response */
+CURL_STATIC void Curl_pp_init(struct pingpong *pp)
+{
+ struct connectdata *conn = pp->conn;
+ pp->nread_resp = 0;
+ pp->linestart_resp = conn->data->state.buffer;
+ pp->pending_resp = TRUE;
+ pp->response = Curl_tvnow(); /* start response time-out now! */
+}
+
+
+
+/***********************************************************************
+ *
+ * Curl_pp_vsendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURL_STATIC CURLcode Curl_pp_vsendf(struct pingpong *pp,
+ const char *fmt,
+ va_list args)
+{
+ ssize_t bytes_written;
+ size_t write_len;
+ char *fmt_crlf;
+ char *s;
+ CURLcode result;
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data = conn->data;
+
+#ifdef HAVE_GSSAPI
+ enum protection_level data_sec = conn->data_prot;
+#endif
+
+ DEBUGASSERT(pp->sendleft == 0);
+ DEBUGASSERT(pp->sendsize == 0);
+ DEBUGASSERT(pp->sendthis == NULL);
+
+ fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
+ if(!fmt_crlf)
+ return CURLE_OUT_OF_MEMORY;
+
+ s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */
+ free(fmt_crlf);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY;
+
+ bytes_written = 0;
+ write_len = strlen(s);
+
+ Curl_pp_init(pp);
+
+ result = Curl_convert_to_network(data, s, write_len);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result) {
+ free(s);
+ return result;
+ }
+
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CMD;
+#endif
+ result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
+ &bytes_written);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
+ conn->data_prot = data_sec;
+#endif
+
+ if(result) {
+ free(s);
+ return result;
+ }
+
+ if(conn->data->set.verbose)
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT,
+ s, (size_t)bytes_written, conn);
+
+ if(bytes_written != (ssize_t)write_len) {
+ /* the whole chunk was not sent, keep it around and adjust sizes */
+ pp->sendthis = s;
+ pp->sendsize = write_len;
+ pp->sendleft = write_len - bytes_written;
+ }
+ else {
+ free(s);
+ pp->sendthis = NULL;
+ pp->sendleft = pp->sendsize = 0;
+ pp->response = Curl_tvnow();
+ }
+
+ return CURLE_OK;
+}
+
+
+/***********************************************************************
+ *
+ * Curl_pp_sendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURL_STATIC CURLcode Curl_pp_sendf(struct pingpong *pp,
+ const char *fmt, ...)
+{
+ CURLcode result;
+ va_list ap;
+ va_start(ap, fmt);
+
+ result = Curl_pp_vsendf(pp, fmt, ap);
+
+ va_end(ap);
+
+ return result;
+}
+
+/*
+ * Curl_pp_readresp()
+ *
+ * Reads a piece of a server response.
+ */
+CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *code, /* return the server code if done */
+ size_t *size) /* size of the response */
+{
+ ssize_t perline; /* count bytes per line */
+ bool keepon=TRUE;
+ ssize_t gotbytes;
+ char *ptr;
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data = conn->data;
+ char * const buf = data->state.buffer;
+ CURLcode result = CURLE_OK;
+
+ *code = 0; /* 0 for errors or not done */
+ *size = 0;
+
+ ptr=buf + pp->nread_resp;
+
+ /* number of bytes in the current line, so far */
+ perline = (ssize_t)(ptr-pp->linestart_resp);
+
+ while((pp->nread_resp<BUFSIZE) && (keepon && !result)) {
+
+ if(pp->cache) {
+ /* we had data in the "cache", copy that instead of doing an actual
+ * read
+ *
+ * pp->cache_size is cast to ssize_t here. This should be safe, because
+ * it would have been populated with something of size int to begin
+ * with, even though its datatype may be larger than an int.
+ */
+ DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1));
+ memcpy(ptr, pp->cache, pp->cache_size);
+ gotbytes = (ssize_t)pp->cache_size;
+ free(pp->cache); /* free the cache */
+ pp->cache = NULL; /* clear the pointer */
+ pp->cache_size = 0; /* zero the size just in case */
+ }
+ else {
+#ifdef HAVE_GSSAPI
+ enum protection_level prot = conn->data_prot;
+ conn->data_prot = PROT_CLEAR;
+#endif
+ DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
+ result = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
+ &gotbytes);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
+ conn->data_prot = prot;
+#endif
+ if(result == CURLE_AGAIN)
+ return CURLE_OK; /* return */
+
+ if(!result && (gotbytes > 0))
+ /* convert from the network encoding */
+ result = Curl_convert_from_network(data, ptr, gotbytes);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+
+ if(result)
+ /* Set outer result variable to this error. */
+ keepon = FALSE;
+ }
+
+ if(!keepon)
+ ;
+ else if(gotbytes <= 0) {
+ keepon = FALSE;
+ result = CURLE_RECV_ERROR;
+ failf(data, "response reading failed");
+ }
+ else {
+ /* we got a whole chunk of data, which can be anything from one
+ * byte to a set of lines and possible just a piece of the last
+ * line */
+ ssize_t i;
+ ssize_t clipamount = 0;
+ bool restart = FALSE;
+
+ data->req.headerbytecount += (long)gotbytes;
+
+ pp->nread_resp += gotbytes;
+ for(i = 0; i < gotbytes; ptr++, i++) {
+ perline++;
+ if(*ptr=='\n') {
+ /* a newline is CRLF in pp-talk, so the CR is ignored as
+ the line isn't really terminated until the LF comes */
+
+ /* output debug output if that is requested */
+#ifdef HAVE_GSSAPI
+ if(!conn->sec_complete)
+#endif
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ pp->linestart_resp, (size_t)perline, conn);
+
+ /*
+ * We pass all response-lines to the callback function registered
+ * for "headers". The response lines can be seen as a kind of
+ * headers.
+ */
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ pp->linestart_resp, perline);
+ if(result)
+ return result;
+
+ if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
+ /* This is the end of the last line, copy the last line to the
+ start of the buffer and zero terminate, for old times sake */
+ size_t n = ptr - pp->linestart_resp;
+ memmove(buf, pp->linestart_resp, n);
+ buf[n]=0; /* zero terminate */
+ keepon=FALSE;
+ pp->linestart_resp = ptr+1; /* advance pointer */
+ i++; /* skip this before getting out */
+
+ *size = pp->nread_resp; /* size of the response */
+ pp->nread_resp = 0; /* restart */
+ break;
+ }
+ perline=0; /* line starts over here */
+ pp->linestart_resp = ptr+1;
+ }
+ }
+
+ if(!keepon && (i != gotbytes)) {
+ /* We found the end of the response lines, but we didn't parse the
+ full chunk of data we have read from the server. We therefore need
+ to store the rest of the data to be checked on the next invoke as
+ it may actually contain another end of response already! */
+ clipamount = gotbytes - i;
+ restart = TRUE;
+ DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
+ "server response left\n",
+ (int)clipamount));
+ }
+ else if(keepon) {
+
+ if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
+ /* We got an excessive line without newlines and we need to deal
+ with it. We keep the first bytes of the line then we throw
+ away the rest. */
+ infof(data, "Excessive server response line length received, "
+ "%zd bytes. Stripping\n", gotbytes);
+ restart = TRUE;
+
+ /* we keep 40 bytes since all our pingpong protocols are only
+ interested in the first piece */
+ clipamount = 40;
+ }
+ else if(pp->nread_resp > BUFSIZE/2) {
+ /* We got a large chunk of data and there's potentially still
+ trailing data to take care of, so we put any such part in the
+ "cache", clear the buffer to make space and restart. */
+ clipamount = perline;
+ restart = TRUE;
+ }
+ }
+ else if(i == gotbytes)
+ restart = TRUE;
+
+ if(clipamount) {
+ pp->cache_size = clipamount;
+ pp->cache = malloc(pp->cache_size);
+ if(pp->cache)
+ memcpy(pp->cache, pp->linestart_resp, pp->cache_size);
+ else
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(restart) {
+ /* now reset a few variables to start over nicely from the start of
+ the big buffer */
+ pp->nread_resp = 0; /* start over from scratch in the buffer */
+ ptr = pp->linestart_resp = buf;
+ perline = 0;
+ }
+
+ } /* there was data */
+
+ } /* while there's buffer left and loop is requested */
+
+ pp->pending_resp = FALSE;
+
+ return result;
+}
+
+CURL_STATIC int Curl_pp_getsock(struct pingpong *pp,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ struct connectdata *conn = pp->conn;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ socks[0] = conn->sock[FIRSTSOCKET];
+
+ if(pp->sendleft) {
+ /* write mode */
+ return GETSOCK_WRITESOCK(0);
+ }
+
+ /* read mode */
+ return GETSOCK_READSOCK(0);
+}
+
+CURL_STATIC CURLcode Curl_pp_flushsend(struct pingpong *pp)
+{
+ /* we have a piece of a command still left to send */
+ struct connectdata *conn = pp->conn;
+ ssize_t written;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize -
+ pp->sendleft, pp->sendleft, &written);
+ if(result)
+ return result;
+
+ if(written != (ssize_t)pp->sendleft) {
+ /* only a fraction was sent */
+ pp->sendleft -= written;
+ }
+ else {
+ free(pp->sendthis);
+ pp->sendthis=NULL;
+ pp->sendleft = pp->sendsize = 0;
+ pp->response = Curl_tvnow();
+ }
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_pp_disconnect(struct pingpong *pp)
+{
+ free(pp->cache);
+ pp->cache = NULL;
+ return CURLE_OK;
+}
+
+CURL_STATIC bool Curl_pp_moredata(struct pingpong *pp)
+{
+ return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
+ TRUE : FALSE;
+}
+
+#endif
diff --git a/libcurl/src/lib/pingpong.h b/libcurl/src/lib/pingpong.h
new file mode 100644
index 0000000..6ee1fe7
--- /dev/null
+++ b/libcurl/src/lib/pingpong.h
@@ -0,0 +1,150 @@
+#ifndef HEADER_CURL_PINGPONG_H
+#define HEADER_CURL_PINGPONG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \
+ !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP)
+#define USE_PINGPONG
+#endif
+
+/* forward-declaration, this is defined in urldata.h */
+struct connectdata;
+
+typedef enum {
+ FTPTRANSFER_BODY, /* yes do transfer a body */
+ FTPTRANSFER_INFO, /* do still go through to get info/headers */
+ FTPTRANSFER_NONE, /* don't get anything and don't get info */
+ FTPTRANSFER_LAST /* end of list marker, never used */
+} curl_pp_transfer;
+
+/*
+ * 'pingpong' is the generic struct used for protocols doing server<->client
+ * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc.
+ *
+ * It holds response cache and non-blocking sending data.
+ */
+struct pingpong {
+ char *cache; /* data cache between getresponse()-calls */
+ size_t cache_size; /* size of cache in bytes */
+ size_t nread_resp; /* number of bytes currently read of a server response */
+ char *linestart_resp; /* line start pointer for the server response
+ reader function */
+ bool pending_resp; /* set TRUE when a server response is pending or in
+ progress, and is cleared once the last response is
+ read */
+ char *sendthis; /* allocated pointer to a buffer that is to be sent to the
+ server */
+ size_t sendleft; /* number of bytes left to send from the sendthis buffer */
+ size_t sendsize; /* total size of the sendthis buffer */
+ struct timeval response; /* set to Curl_tvnow() when a command has been sent
+ off, used to time-out response reading */
+ long response_time; /* When no timeout is given, this is the amount of
+ milliseconds we await for a server response. */
+
+ struct connectdata *conn; /* points to the connectdata struct that this
+ belongs to */
+
+ /* Function pointers the protocols MUST implement and provide for the
+ pingpong layer to function */
+
+ CURLcode (*statemach_act)(struct connectdata *conn);
+
+ bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len,
+ int *code);
+};
+
+/*
+ * Curl_pp_statemach()
+ *
+ * called repeatedly until done. Set 'wait' to make it wait a while on the
+ * socket if there's no traffic.
+ */
+CURL_STATIC CURLcode Curl_pp_statemach(struct pingpong *pp, bool block);
+
+/* initialize stuff to prepare for reading a fresh new response */
+CURL_STATIC void Curl_pp_init(struct pingpong *pp);
+
+/* Returns timeout in ms. 0 or negative number means the timeout has already
+ triggered */
+CURL_STATIC long Curl_pp_state_timeout(struct pingpong *pp);
+
+
+/***********************************************************************
+ *
+ * Curl_pp_sendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURL_STATIC CURLcode Curl_pp_sendf(struct pingpong *pp,
+ const char *fmt, ...);
+
+/***********************************************************************
+ *
+ * Curl_pp_vsendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURL_STATIC CURLcode Curl_pp_vsendf(struct pingpong *pp,
+ const char *fmt,
+ va_list args);
+
+/*
+ * Curl_pp_readresp()
+ *
+ * Reads a piece of a server response.
+ */
+CURL_STATIC CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *code, /* return the server code if done */
+ size_t *size); /* size of the response */
+
+
+CURL_STATIC CURLcode Curl_pp_flushsend(struct pingpong *pp);
+
+/* call this when a pingpong connection is disconnected */
+CURL_STATIC CURLcode Curl_pp_disconnect(struct pingpong *pp);
+
+CURL_STATIC int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks,
+ int numsocks);
+
+
+/***********************************************************************
+ *
+ * Curl_pp_moredata()
+ *
+ * Returns whether there are still more data in the cache and so a call
+ * to Curl_pp_readresp() will not block.
+ */
+CURL_STATIC bool Curl_pp_moredata(struct pingpong *pp);
+
+#endif /* HEADER_CURL_PINGPONG_H */
diff --git a/libcurl/src/lib/pipeline.c b/libcurl/src/lib/pipeline.c
new file mode 100644
index 0000000..7af5484
--- /dev/null
+++ b/libcurl/src/lib/pipeline.c
@@ -0,0 +1,338 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2013-2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "multiif.h"
+#include "pipeline.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "bundles.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+struct site_blacklist_entry {
+ char *hostname;
+ unsigned short port;
+};
+
+static void site_blacklist_llist_dtor(void *user, void *element)
+{
+ struct site_blacklist_entry *entry = element;
+ (void)user;
+
+ Curl_safefree(entry->hostname);
+ free(entry);
+}
+
+static void server_blacklist_llist_dtor(void *user, void *element)
+{
+ (void)user;
+ free(element);
+}
+
+CURL_STATIC bool Curl_pipeline_penalized(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ if(data) {
+ bool penalized = FALSE;
+ curl_off_t penalty_size =
+ Curl_multi_content_length_penalty_size(data->multi);
+ curl_off_t chunk_penalty_size =
+ Curl_multi_chunk_length_penalty_size(data->multi);
+ curl_off_t recv_size = -2; /* Make it easy to spot in the log */
+
+ /* Find the head of the recv pipe, if any */
+ if(conn->recv_pipe && conn->recv_pipe->head) {
+ struct SessionHandle *recv_handle = conn->recv_pipe->head->ptr;
+
+ recv_size = recv_handle->req.size;
+
+ if(penalty_size > 0 && recv_size > penalty_size)
+ penalized = TRUE;
+ }
+
+ if(chunk_penalty_size > 0 &&
+ (curl_off_t)conn->chunk.datasize > chunk_penalty_size)
+ penalized = TRUE;
+
+ infof(data, "Conn: %ld (%p) Receive pipe weight: (%"
+ CURL_FORMAT_CURL_OFF_T "/%zu), penalized: %s\n",
+ conn->connection_id, (void *)conn, recv_size,
+ conn->chunk.datasize, penalized?"TRUE":"FALSE");
+ return penalized;
+ }
+ return FALSE;
+}
+
+CURL_STATIC CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle,
+ struct connectdata *conn)
+{
+ struct curl_llist_element *sendhead = conn->send_pipe->head;
+ struct curl_llist *pipeline;
+ CURLcode result;
+
+ pipeline = conn->send_pipe;
+
+ result = Curl_addHandleToPipeline(handle, pipeline);
+
+ if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
+ /* this is a new one as head, expire it */
+ conn->writechannel_inuse = FALSE; /* not in use yet */
+ Curl_expire(conn->send_pipe->head->ptr, 1);
+ }
+
+#if 0 /* enable for pipeline debugging */
+ print_pipeline(conn);
+#endif
+
+ return result;
+}
+
+/* Move this transfer from the sending list to the receiving list.
+
+ Pay special attention to the new sending list "leader" as it needs to get
+ checked to update what sockets it acts on.
+
+*/
+CURL_STATIC void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle,
+ struct connectdata *conn)
+{
+ struct curl_llist_element *curr;
+
+ curr = conn->send_pipe->head;
+ while(curr) {
+ if(curr->ptr == handle) {
+ Curl_llist_move(conn->send_pipe, curr,
+ conn->recv_pipe, conn->recv_pipe->tail);
+
+ if(conn->send_pipe->head) {
+ /* Since there's a new easy handle at the start of the send pipeline,
+ set its timeout value to 1ms to make it trigger instantly */
+ conn->writechannel_inuse = FALSE; /* not used now */
+#ifdef DEBUGBUILD
+ infof(conn->data, "%p is at send pipe head B!\n",
+ (void *)conn->send_pipe->head->ptr);
+#endif
+ Curl_expire(conn->send_pipe->head->ptr, 1);
+ }
+
+ /* The receiver's list is not really interesting here since either this
+ handle is now first in the list and we'll deal with it soon, or
+ another handle is already first and thus is already taken care of */
+
+ break; /* we're done! */
+ }
+ curr = curr->next;
+ }
+}
+
+CURL_STATIC bool Curl_pipeline_site_blacklisted(struct SessionHandle *handle,
+ struct connectdata *conn)
+{
+ if(handle->multi) {
+ struct curl_llist *blacklist =
+ Curl_multi_pipelining_site_bl(handle->multi);
+
+ if(blacklist) {
+ struct curl_llist_element *curr;
+
+ curr = blacklist->head;
+ while(curr) {
+ struct site_blacklist_entry *site;
+
+ site = curr->ptr;
+ if(Curl_raw_equal(site->hostname, conn->host.name) &&
+ site->port == conn->remote_port) {
+ infof(handle, "Site %s:%d is pipeline blacklisted\n",
+ conn->host.name, conn->remote_port);
+ return TRUE;
+ }
+ curr = curr->next;
+ }
+ }
+ }
+ return FALSE;
+}
+
+CURL_STATIC CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
+ struct curl_llist **list_ptr)
+{
+ struct curl_llist *old_list = *list_ptr;
+ struct curl_llist *new_list = NULL;
+
+ if(sites) {
+ new_list = Curl_llist_alloc((curl_llist_dtor) site_blacklist_llist_dtor);
+ if(!new_list)
+ return CURLM_OUT_OF_MEMORY;
+
+ /* Parse the URLs and populate the list */
+ while(*sites) {
+ char *hostname;
+ char *port;
+ struct site_blacklist_entry *entry;
+
+ hostname = strdup(*sites);
+ if(!hostname) {
+ Curl_llist_destroy(new_list, NULL);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ entry = malloc(sizeof(struct site_blacklist_entry));
+ if(!entry) {
+ free(hostname);
+ Curl_llist_destroy(new_list, NULL);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ port = strchr(hostname, ':');
+ if(port) {
+ *port = '\0';
+ port++;
+ entry->port = (unsigned short)strtol(port, NULL, 10);
+ }
+ else {
+ /* Default port number for HTTP */
+ entry->port = 80;
+ }
+
+ entry->hostname = hostname;
+
+ if(!Curl_llist_insert_next(new_list, new_list->tail, entry)) {
+ site_blacklist_llist_dtor(NULL, entry);
+ Curl_llist_destroy(new_list, NULL);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ sites++;
+ }
+ }
+
+ /* Free the old list */
+ if(old_list) {
+ Curl_llist_destroy(old_list, NULL);
+ }
+
+ /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
+ *list_ptr = new_list;
+
+ return CURLM_OK;
+}
+
+CURL_STATIC bool Curl_pipeline_server_blacklisted(struct SessionHandle *handle,
+ char *server_name)
+{
+ if(handle->multi && server_name) {
+ struct curl_llist *blacklist =
+ Curl_multi_pipelining_server_bl(handle->multi);
+
+ if(blacklist) {
+ struct curl_llist_element *curr;
+
+ curr = blacklist->head;
+ while(curr) {
+ char *bl_server_name;
+
+ bl_server_name = curr->ptr;
+ if(Curl_raw_nequal(bl_server_name, server_name,
+ strlen(bl_server_name))) {
+ infof(handle, "Server %s is blacklisted\n", server_name);
+ return TRUE;
+ }
+ curr = curr->next;
+ }
+ }
+
+ DEBUGF(infof(handle, "Server %s is not blacklisted\n", server_name));
+ }
+ return FALSE;
+}
+
+CURL_STATIC CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
+ struct curl_llist **list_ptr)
+{
+ struct curl_llist *old_list = *list_ptr;
+ struct curl_llist *new_list = NULL;
+
+ if(servers) {
+ new_list = Curl_llist_alloc((curl_llist_dtor) server_blacklist_llist_dtor);
+ if(!new_list)
+ return CURLM_OUT_OF_MEMORY;
+
+ /* Parse the URLs and populate the list */
+ while(*servers) {
+ char *server_name;
+
+ server_name = strdup(*servers);
+ if(!server_name)
+ return CURLM_OUT_OF_MEMORY;
+
+ if(!Curl_llist_insert_next(new_list, new_list->tail, server_name))
+ return CURLM_OUT_OF_MEMORY;
+
+ servers++;
+ }
+ }
+
+ /* Free the old list */
+ if(old_list) {
+ Curl_llist_destroy(old_list, NULL);
+ }
+
+ /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
+ *list_ptr = new_list;
+
+ return CURLM_OK;
+}
+
+#if 0
+void print_pipeline(struct connectdata *conn)
+{
+ struct curl_llist_element *curr;
+ struct connectbundle *cb_ptr;
+ struct SessionHandle *data = conn->data;
+
+ cb_ptr = conn->bundle;
+
+ if(cb_ptr) {
+ curr = cb_ptr->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+ infof(data, "- Conn %ld (%p) send_pipe: %zu, recv_pipe: %zu\n",
+ conn->connection_id,
+ (void *)conn,
+ conn->send_pipe->size,
+ conn->recv_pipe->size);
+ curr = curr->next;
+ }
+ }
+}
+
+#endif
diff --git a/libcurl/src/lib/pipeline.h b/libcurl/src/lib/pipeline.h
new file mode 100644
index 0000000..a00db79
--- /dev/null
+++ b/libcurl/src/lib/pipeline.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_PIPELINE_H
+#define HEADER_CURL_PIPELINE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+CURL_STATIC CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle,
+ struct connectdata *conn);
+CURL_STATIC void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle,
+ struct connectdata *conn);
+CURL_STATIC bool Curl_pipeline_penalized(struct SessionHandle *data,
+ struct connectdata *conn);
+
+CURL_STATIC bool Curl_pipeline_site_blacklisted(struct SessionHandle *handle,
+ struct connectdata *conn);
+
+CURL_STATIC CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
+ struct curl_llist **list_ptr);
+
+CURL_STATIC bool Curl_pipeline_server_blacklisted(struct SessionHandle *handle,
+ char *server_name);
+
+CURL_STATIC CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
+ struct curl_llist **list_ptr);
+
+#endif /* HEADER_CURL_PIPELINE_H */
diff --git a/libcurl/src/lib/pop3.c b/libcurl/src/lib/pop3.c
new file mode 100644
index 0000000..d676b63
--- /dev/null
+++ b/libcurl/src/lib/pop3.c
@@ -0,0 +1,1601 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC1734 POP3 Authentication
+ * RFC1939 POP3 protocol
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2384 POP URL Scheme
+ * RFC2449 POP3 Extension Mechanism
+ * RFC2595 Using TLS with IMAP, POP3 and ACAP
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ * RFC5034 POP3 SASL Authentication Mechanism
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_POP3
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "pop3.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "select.h"
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "curl_sasl.h"
+#include "curl_md5.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local API functions */
+static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
+static CURLcode pop3_do(struct connectdata *conn, bool *done);
+static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+ bool premature);
+static CURLcode pop3_connect(struct connectdata *conn, bool *done);
+static CURLcode pop3_disconnect(struct connectdata *conn, bool dead);
+static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done);
+static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
+static CURLcode pop3_setup_connection(struct connectdata *conn);
+static CURLcode pop3_parse_url_options(struct connectdata *conn);
+static CURLcode pop3_parse_url_path(struct connectdata *conn);
+static CURLcode pop3_parse_custom_request(struct connectdata *conn);
+static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech,
+ const char *initresp);
+static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp);
+static void pop3_get_message(char *buffer, char** outptr);
+
+/*
+ * POP3 protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_pop3 = {
+ "POP3", /* scheme */
+ pop3_setup_connection, /* setup_connection */
+ pop3_do, /* do_it */
+ pop3_done, /* done */
+ ZERO_NULL, /* do_more */
+ pop3_connect, /* connect_it */
+ pop3_multi_statemach, /* connecting */
+ pop3_doing, /* doing */
+ pop3_getsock, /* proto_getsock */
+ pop3_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ pop3_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3, /* defport */
+ CURLPROTO_POP3, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * POP3S protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_pop3s = {
+ "POP3S", /* scheme */
+ pop3_setup_connection, /* setup_connection */
+ pop3_do, /* do_it */
+ pop3_done, /* done */
+ ZERO_NULL, /* do_more */
+ pop3_connect, /* connect_it */
+ pop3_multi_statemach, /* connecting */
+ pop3_doing, /* doing */
+ pop3_getsock, /* proto_getsock */
+ pop3_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ pop3_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3S, /* defport */
+ CURLPROTO_POP3S, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL
+ | PROTOPT_NOURLQUERY /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed POP3 protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_pop3_proxy = {
+ "POP3", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed POP3S protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_pop3s_proxy = {
+ "POP3S", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3S, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+/* SASL parameters for the pop3 protocol */
+static const struct SASLproto saslpop3 = {
+ "pop", /* The service name */
+ '+', /* Code received when continuation is expected */
+ '+', /* Code to receive upon authentication success */
+ 255 - 8, /* Maximum initial response length (no max) */
+ pop3_perform_auth, /* Send authentication command */
+ pop3_continue_auth, /* Send authentication continuation */
+ pop3_get_message /* Get SASL response message */
+};
+
+#ifdef USE_SSL
+static void pop3_to_pop3s(struct connectdata *conn)
+{
+ conn->handler = &Curl_handler_pop3s;
+}
+#else
+#define pop3_to_pop3s(x) Curl_nop_stmt
+#endif
+
+/***********************************************************************
+ *
+ * pop3_endofresp()
+ *
+ * Checks for an ending POP3 status code at the start of the given string, but
+ * also detects the APOP timestamp from the server greeting and various
+ * capabilities from the CAPA response including the supported authentication
+ * types and allowed SASL mechanisms.
+ */
+static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *resp)
+{
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ /* Do we have an error response? */
+ if(len >= 4 && !memcmp("-ERR", line, 4)) {
+ *resp = '-';
+
+ return TRUE;
+ }
+
+ /* Are we processing CAPA command responses? */
+ if(pop3c->state == POP3_CAPA) {
+ /* Do we have the terminating line? */
+ if(len >= 1 && !memcmp(line, ".", 1))
+ *resp = '+';
+ else
+ *resp = '*';
+
+ return TRUE;
+ }
+
+ /* Do we have a command or continuation response? */
+ if((len >= 3 && !memcmp("+OK", line, 3)) ||
+ (len >= 1 && !memcmp("+", line, 1))) {
+ *resp = '+';
+
+ return TRUE;
+ }
+
+ return FALSE; /* Nothing for us */
+}
+
+/***********************************************************************
+ *
+ * pop3_get_message()
+ *
+ * Gets the authentication message from the response buffer.
+ */
+static void pop3_get_message(char *buffer, char** outptr)
+{
+ size_t len = 0;
+ char* message = NULL;
+
+ /* Find the start of the message */
+ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
+ ;
+
+ /* Find the end of the message */
+ for(len = strlen(message); len--;)
+ if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+ message[len] != '\t')
+ break;
+
+ /* Terminate the message */
+ if(++len) {
+ message[len] = '\0';
+ }
+
+ *outptr = message;
+}
+
+/***********************************************************************
+ *
+ * state()
+ *
+ * This is the ONLY way to change POP3 state!
+ */
+static void state(struct connectdata *conn, pop3state newstate)
+{
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[] = {
+ "STOP",
+ "SERVERGREET",
+ "CAPA",
+ "STARTTLS",
+ "UPGRADETLS",
+ "AUTH",
+ "APOP",
+ "USER",
+ "PASS",
+ "COMMAND",
+ "QUIT",
+ /* LAST */
+ };
+
+ if(pop3c->state != newstate)
+ infof(conn->data, "POP3 %p state change from %s to %s\n",
+ (void *)pop3c, names[pop3c->state], names[newstate]);
+#endif
+
+ pop3c->state = newstate;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_capa()
+ *
+ * Sends the CAPA command in order to obtain a list of server side supported
+ * capabilities.
+ */
+static CURLcode pop3_perform_capa(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ pop3c->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */
+ pop3c->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */
+ pop3c->tls_supported = FALSE; /* Clear the TLS capability */
+
+ /* Send the CAPA command */
+ result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA");
+
+ if(!result)
+ state(conn, POP3_CAPA);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_starttls()
+ *
+ * Sends the STLS command to start the upgrade to TLS.
+ */
+static CURLcode pop3_perform_starttls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the STLS command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS");
+
+ if(!result)
+ state(conn, POP3_STARTTLS);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_upgrade_tls()
+ *
+ * Performs the upgrade to TLS.
+ */
+static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ /* Start the SSL connection */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
+
+ if(!result) {
+ if(pop3c->state != POP3_UPGRADETLS)
+ state(conn, POP3_UPGRADETLS);
+
+ if(pop3c->ssldone) {
+ pop3_to_pop3s(conn);
+ result = pop3_perform_capa(conn);
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_user()
+ *
+ * Sends a clear text USER command to authenticate with.
+ */
+static CURLcode pop3_perform_user(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, POP3_STOP);
+
+ return result;
+ }
+
+ /* Send the USER command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s",
+ conn->user ? conn->user : "");
+ if(!result)
+ state(conn, POP3_USER);
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/***********************************************************************
+ *
+ * pop3_perform_apop()
+ *
+ * Sends an APOP command to authenticate with.
+ */
+static CURLcode pop3_perform_apop(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ size_t i;
+ MD5_context *ctxt;
+ unsigned char digest[MD5_DIGEST_LEN];
+ char secret[2 * MD5_DIGEST_LEN + 1];
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, POP3_STOP);
+
+ return result;
+ }
+
+ /* Create the digest */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp,
+ curlx_uztoui(strlen(pop3c->apoptimestamp)));
+
+ Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd,
+ curlx_uztoui(strlen(conn->passwd)));
+
+ /* Finalise the digest */
+ Curl_MD5_final(ctxt, digest);
+
+ /* Convert the calculated 16 octet digest into a 32 byte hex string */
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&secret[2 * i], 3, "%02x", digest[i]);
+
+ result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
+
+ if(!result)
+ state(conn, POP3_APOP);
+
+ return result;
+}
+#endif
+
+/***********************************************************************
+ *
+ * pop3_perform_auth()
+ *
+ * Sends an AUTH command allowing the client to login with the given SASL
+ * authentication mechanism.
+ */
+static CURLcode pop3_perform_auth(struct connectdata *conn,
+ const char *mech,
+ const char *initresp)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ if(initresp) { /* AUTH <mech> ...<crlf> */
+ /* Send the AUTH command with the initial response */
+ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
+ }
+ else {
+ /* Send the AUTH command */
+ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_continue_auth()
+ *
+ * Sends SASL continuation data or cancellation.
+ */
+static CURLcode pop3_continue_auth(struct connectdata *conn,
+ const char *resp)
+{
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ return Curl_pp_sendf(&pop3c->pp, "%s", resp);
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_authentication()
+ *
+ * Initiates the authentication sequence, with the appropriate SASL
+ * authentication mechanism, falling back to APOP and clear text should a
+ * common mechanism not be available between the client and server.
+ */
+static CURLcode pop3_perform_authentication(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ saslprogress progress = SASL_IDLE;
+
+ /* Check we have enough data to authenticate with and end the
+ connect phase if we don't */
+ if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) {
+ state(conn, POP3_STOP);
+ return result;
+ }
+
+ if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) {
+ /* Calculate the SASL login details */
+ result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress);
+
+ if(!result)
+ if(progress == SASL_INPROGRESS)
+ state(conn, POP3_AUTH);
+ }
+
+ if(!result && progress == SASL_IDLE) {
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
+ /* Perform APOP authentication */
+ result = pop3_perform_apop(conn);
+ else
+#endif
+ if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
+ /* Perform clear text authentication */
+ result = pop3_perform_user(conn);
+ else {
+ /* Other mechanisms not supported */
+ infof(conn->data, "No known authentication mechanisms supported!\n");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_command()
+ *
+ * Sends a POP3 based command.
+ */
+static CURLcode pop3_perform_command(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ const char *command = NULL;
+
+ /* Calculate the default command */
+ if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
+ command = "LIST";
+
+ if(pop3->id[0] != '\0')
+ /* Message specific LIST so skip the BODY transfer */
+ pop3->transfer = FTPTRANSFER_INFO;
+ }
+ else
+ command = "RETR";
+
+ /* Send the command */
+ if(pop3->id[0] != '\0')
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
+ (pop3->custom && pop3->custom[0] != '\0' ?
+ pop3->custom : command), pop3->id);
+ else
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s",
+ (pop3->custom && pop3->custom[0] != '\0' ?
+ pop3->custom : command));
+
+ if(!result)
+ state(conn, POP3_COMMAND);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_quit()
+ *
+ * Performs the quit action prior to sclose() be called.
+ */
+static CURLcode pop3_perform_quit(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the QUIT command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT");
+
+ if(!result)
+ state(conn, POP3_QUIT);
+
+ return result;
+}
+
+/* For the initial server greeting */
+static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *line = data->state.buffer;
+ size_t len = strlen(line);
+ size_t i;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Got unexpected pop3-server response");
+ result = CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+ else {
+ /* Does the server support APOP authentication? */
+ if(len >= 4 && line[len - 2] == '>') {
+ /* Look for the APOP timestamp */
+ for(i = 3; i < len - 2; ++i) {
+ if(line[i] == '<') {
+ /* Calculate the length of the timestamp */
+ size_t timestamplen = len - 1 - i;
+ if(!timestamplen)
+ break;
+
+ /* Allocate some memory for the timestamp */
+ pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
+
+ if(!pop3c->apoptimestamp)
+ break;
+
+ /* Copy the timestamp */
+ memcpy(pop3c->apoptimestamp, line + i, timestamplen);
+ pop3c->apoptimestamp[timestamplen] = '\0';
+
+ /* Store the APOP capability */
+ pop3c->authtypes |= POP3_TYPE_APOP;
+ break;
+ }
+ }
+ }
+
+ result = pop3_perform_capa(conn);
+ }
+
+ return result;
+}
+
+/* For CAPA responses */
+static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *line = data->state.buffer;
+ size_t len = strlen(line);
+ size_t wordlen;
+
+ (void)instate; /* no use for this yet */
+
+ /* Do we have a untagged response? */
+ if(pop3code == '*') {
+ /* Does the server support the STLS capability? */
+ if(len >= 4 && !memcmp(line, "STLS", 4))
+ pop3c->tls_supported = TRUE;
+
+ /* Does the server support clear text authentication? */
+ else if(len >= 4 && !memcmp(line, "USER", 4))
+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+
+ /* Does the server support SASL based authentication? */
+ else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
+ pop3c->authtypes |= POP3_TYPE_SASL;
+
+ /* Advance past the SASL keyword */
+ line += 5;
+ len -= 5;
+
+ /* Loop through the data line */
+ for(;;) {
+ size_t llen;
+ unsigned int mechbit;
+
+ while(len &&
+ (*line == ' ' || *line == '\t' ||
+ *line == '\r' || *line == '\n')) {
+
+ line++;
+ len--;
+ }
+
+ if(!len)
+ break;
+
+ /* Extract the word */
+ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
+ line[wordlen] != '\t' && line[wordlen] != '\r' &&
+ line[wordlen] != '\n';)
+ wordlen++;
+
+ /* Test the word for a matching authentication mechanism */
+ if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) &&
+ llen == wordlen)
+ pop3c->sasl.authmechs |= mechbit;
+
+ line += wordlen;
+ len -= wordlen;
+ }
+ }
+ }
+ else if(pop3code == '+') {
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but SSL is requested */
+ if(pop3c->tls_supported)
+ /* Switch to TLS connection now */
+ result = pop3_perform_starttls(conn);
+ else if(data->set.use_ssl == CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = pop3_perform_authentication(conn);
+ else {
+ failf(data, "STLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
+ }
+ else
+ result = pop3_perform_authentication(conn);
+ }
+ else {
+ /* Clear text is supported when CAPA isn't recognised */
+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+
+ result = pop3_perform_authentication(conn);
+ }
+
+ return result;
+}
+
+/* For STARTTLS responses */
+static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ if(data->set.use_ssl != CURLUSESSL_TRY) {
+ failf(data, "STARTTLS denied. %c", pop3code);
+ result = CURLE_USE_SSL_FAILED;
+ }
+ else
+ result = pop3_perform_authentication(conn);
+ }
+ else
+ result = pop3_perform_upgrade_tls(conn);
+
+ return result;
+}
+
+/* For SASL authentication responses */
+static CURLcode pop3_state_auth_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ saslprogress progress;
+
+ (void)instate; /* no use for this yet */
+
+ result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress);
+ if(!result)
+ switch(progress) {
+ case SASL_DONE:
+ state(conn, POP3_STOP); /* Authenticated */
+ break;
+ case SASL_IDLE: /* No mechanism left after cancellation */
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
+ /* Perform APOP authentication */
+ result = pop3_perform_apop(conn);
+ else
+#endif
+ if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
+ /* Perform clear text authentication */
+ result = pop3_perform_user(conn);
+ else {
+ failf(data, "Authentication cancelled");
+ result = CURLE_LOGIN_DENIED;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/* For APOP responses */
+static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Authentication failed: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, POP3_STOP);
+
+ return result;
+}
+#endif
+
+/* For USER responses */
+static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied. %c", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* Send the PASS command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
+ conn->passwd ? conn->passwd : "");
+ if(!result)
+ state(conn, POP3_PASS);
+
+ return result;
+}
+
+/* For PASS responses */
+static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied. %c", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, POP3_STOP);
+
+ return result;
+}
+
+/* For command responses */
+static CURLcode pop3_state_command_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pingpong *pp = &pop3c->pp;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ state(conn, POP3_STOP);
+ return CURLE_RECV_ERROR;
+ }
+
+ /* This 'OK' line ends with a CR LF pair which is the two first bytes of the
+ EOB string so count this is two matching bytes. This is necessary to make
+ the code detect the EOB if the only data than comes now is %2e CR LF like
+ when there is no body to return. */
+ pop3c->eob = 2;
+
+ /* But since this initial CR LF pair is not part of the actual body, we set
+ the strip counter here so that these bytes won't be delivered. */
+ pop3c->strip = 2;
+
+ if(pop3->transfer == FTPTRANSFER_BODY) {
+ /* POP3 download */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+
+ if(pp->cache) {
+ /* The header "cache" contains a bunch of data that is actually body
+ content so send it as such. Note that there may even be additional
+ "headers" after the body */
+
+ if(!data->set.opt_no_body) {
+ result = Curl_pop3_write(conn, pp->cache, pp->cache_size);
+ if(result)
+ return result;
+ }
+
+ /* Free the cache */
+ Curl_safefree(pp->cache);
+
+ /* Reset the cache size */
+ pp->cache_size = 0;
+ }
+ }
+
+ /* End of DO phase */
+ state(conn, POP3_STOP);
+
+ return result;
+}
+
+static CURLcode pop3_statemach_act(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ int pop3code;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pingpong *pp = &pop3c->pp;
+ size_t nread = 0;
+
+ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
+ if(pop3c->state == POP3_UPGRADETLS)
+ return pop3_perform_upgrade_tls(conn);
+
+ /* Flush any data that needs to be sent */
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ do {
+ /* Read the response from the server */
+ result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
+ if(result)
+ return result;
+
+ if(!pop3code)
+ break;
+
+ /* We have now received a full POP3 server response */
+ switch(pop3c->state) {
+ case POP3_SERVERGREET:
+ result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_CAPA:
+ result = pop3_state_capa_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_STARTTLS:
+ result = pop3_state_starttls_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH:
+ result = pop3_state_auth_resp(conn, pop3code, pop3c->state);
+ break;
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ case POP3_APOP:
+ result = pop3_state_apop_resp(conn, pop3code, pop3c->state);
+ break;
+#endif
+
+ case POP3_USER:
+ result = pop3_state_user_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_PASS:
+ result = pop3_state_pass_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_COMMAND:
+ result = pop3_state_command_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, POP3_STOP);
+ break;
+ }
+ } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
+
+ return result;
+}
+
+/* Called repeatedly until done from multi.c */
+static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
+ if(result || !pop3c->ssldone)
+ return result;
+ }
+
+ result = Curl_pp_statemach(&pop3c->pp, FALSE);
+ *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode pop3_block_statemach(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ while(pop3c->state != POP3_STOP && !result)
+ result = Curl_pp_statemach(&pop3c->pp, TRUE);
+
+ return result;
+}
+
+/* Allocate and initialize the POP3 struct for the current SessionHandle if
+ required */
+static CURLcode pop3_init(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3;
+
+ pop3 = data->req.protop = calloc(sizeof(struct POP3), 1);
+ if(!pop3)
+ result = CURLE_OUT_OF_MEMORY;
+
+ return result;
+}
+
+/* For the POP3 "protocol connect" and "doing" phases only */
+static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks);
+}
+
+/***********************************************************************
+ *
+ * pop3_connect()
+ *
+ * This function should do everything that is to be considered a part of the
+ * connection phase.
+ *
+ * The variable 'done' points to will be TRUE if the protocol-layer connect
+ * phase is done when this function returns, or FALSE if not.
+ */
+static CURLcode pop3_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pingpong *pp = &pop3c->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections in POP3 */
+ connkeep(conn, "POP3 default");
+
+ /* Set the default response time-out */
+ pp->response_time = RESP_TIMEOUT;
+ pp->statemach_act = pop3_statemach_act;
+ pp->endofresp = pop3_endofresp;
+ pp->conn = conn;
+
+ /* Set the default preferred authentication type and mechanism */
+ pop3c->preftype = POP3_TYPE_ANY;
+ Curl_sasl_init(&pop3c->sasl, &saslpop3);
+
+ /* Initialise the pingpong layer */
+ Curl_pp_init(pp);
+
+ /* Parse the URL options */
+ result = pop3_parse_url_options(conn);
+ if(result)
+ return result;
+
+ /* Start off waiting for the server greeting response */
+ state(conn, POP3_SERVERGREET);
+
+ result = pop3_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+
+ (void)premature;
+
+ if(!pop3)
+ /* When the easy handle is removed from the multi interface while libcurl
+ is still trying to resolve the host name, the POP3 struct is not yet
+ initialized. However, the removal action calls Curl_done() which in
+ turn calls this function, so we simply return success. */
+ return CURLE_OK;
+
+ if(status) {
+ connclose(conn, "POP3 done with bad status");
+ result = status; /* use the already set error code */
+ }
+
+ /* Cleanup our per-request based variables */
+ Curl_safefree(pop3->id);
+ Curl_safefree(pop3->custom);
+
+ /* Clear the transfer mode for the next request */
+ pop3->transfer = FTPTRANSFER_BODY;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform()
+ *
+ * This is the actual DO function for POP3. Get a message/listing according to
+ * the options previously setup.
+ */
+static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
+ bool *dophase_done)
+{
+ /* This is POP3 and no proxy */
+ CURLcode result = CURLE_OK;
+ struct POP3 *pop3 = conn->data->req.protop;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(conn->data->set.opt_no_body) {
+ /* Requested no body means no transfer */
+ pop3->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* Start the first command in the DO phase */
+ result = pop3_perform_command(conn);
+ if(result)
+ return result;
+
+ /* Run the state-machine */
+ result = pop3_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (pop3_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode pop3_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+
+ *done = FALSE; /* default to false */
+
+ /* Parse the URL path */
+ result = pop3_parse_url_path(conn);
+ if(result)
+ return result;
+
+ /* Parse the custom request */
+ result = pop3_parse_custom_request(conn);
+ if(result)
+ return result;
+
+ result = pop3_regular_transfer(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_disconnect()
+ *
+ * Disconnect from an POP3 server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to. */
+
+ /* The POP3 session may or may not have been allocated/setup at this
+ point! */
+ if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart)
+ if(!pop3_perform_quit(conn))
+ (void)pop3_block_statemach(conn); /* ignore errors on QUIT */
+
+ /* Disconnect from the server */
+ Curl_pp_disconnect(&pop3c->pp);
+
+ /* Cleanup the SASL module */
+ Curl_sasl_cleanup(conn, pop3c->sasl.authused);
+
+ /* Cleanup our connection based variables */
+ Curl_safefree(pop3c->apoptimestamp);
+
+ return CURLE_OK;
+}
+
+/* Call this when the DO phase has completed */
+static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected)
+{
+ (void)conn;
+ (void)connected;
+
+ return CURLE_OK;
+}
+
+/* Called from multi.c while DOing */
+static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = pop3_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = pop3_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ */
+static CURLcode pop3_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ struct SessionHandle *data = conn->data;
+
+ /* Make sure size is unknown at this point */
+ data->req.size = -1;
+
+ /* Set the progress data */
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ /* Carry out the perform */
+ result = pop3_perform(conn, &connected, dophase_done);
+
+ /* Perform post DO phase operations if necessary */
+ if(!result && *dophase_done)
+ result = pop3_dophase_done(conn, connected);
+
+ return result;
+}
+
+static CURLcode pop3_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+
+ /* Initialise the POP3 layer */
+ CURLcode result = pop3_init(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel POP3 operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_pop3)
+ conn->handler = &Curl_handler_pop3_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_pop3s_proxy;
+#else
+ failf(data, "POP3S not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ /* set it up as an HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+#else
+ failf(data, "POP3 over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ data->state.path++; /* don't include the initial slash */
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * pop3_parse_url_options()
+ *
+ * Parse the URL login options.
+ */
+static CURLcode pop3_parse_url_options(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *ptr = conn->options;
+
+ pop3c->sasl.resetprefs = TRUE;
+
+ while(!result && ptr && *ptr) {
+ const char *key = ptr;
+ const char *value;
+
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ value = ptr + 1;
+
+ while(*ptr && *ptr != ';')
+ ptr++;
+
+ if(strnequal(key, "AUTH=", 5)) {
+ result = Curl_sasl_parse_url_auth_option(&pop3c->sasl,
+ value, ptr - value);
+
+ if(result && strnequal(value, "+APOP", ptr - value)) {
+ pop3c->preftype = POP3_TYPE_APOP;
+ pop3c->sasl.prefmech = SASL_AUTH_NONE;
+ result = CURLE_OK;
+ }
+ }
+ else
+ result = CURLE_URL_MALFORMAT;
+
+ if(*ptr == ';')
+ ptr++;
+ }
+
+ if(pop3c->preftype != POP3_TYPE_APOP)
+ switch(pop3c->sasl.prefmech) {
+ case SASL_AUTH_NONE:
+ pop3c->preftype = POP3_TYPE_NONE;
+ break;
+ case SASL_AUTH_DEFAULT:
+ pop3c->preftype = POP3_TYPE_ANY;
+ break;
+ default:
+ pop3c->preftype = POP3_TYPE_SASL;
+ break;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ */
+static CURLcode pop3_parse_url_path(struct connectdata *conn)
+{
+ /* The POP3 struct is already initialised in pop3_connect() */
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ const char *path = data->state.path;
+
+ /* URL decode the path for the message ID */
+ return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
+}
+
+/***********************************************************************
+ *
+ * pop3_parse_custom_request()
+ *
+ * Parse the custom request.
+ */
+static CURLcode pop3_parse_custom_request(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ const char *custom = data->set.str[STRING_CUSTOMREQUEST];
+
+ /* URL decode the custom request */
+ if(custom)
+ result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * Curl_pop3_write()
+ *
+ * This function scans the body after the end-of-body and writes everything
+ * until the end is found.
+ */
+CURL_STATIC CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
+{
+ /* This code could be made into a special function in the handler struct */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ bool strip_dot = FALSE;
+ size_t last = 0;
+ size_t i;
+
+ /* Search through the buffer looking for the end-of-body marker which is
+ 5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches
+ the eob so the server will have prefixed it with an extra dot which we
+ need to strip out. Additionally the marker could of course be spread out
+ over 5 different data chunks. */
+ for(i = 0; i < nread; i++) {
+ size_t prev = pop3c->eob;
+
+ switch(str[i]) {
+ case 0x0d:
+ if(pop3c->eob == 0) {
+ pop3c->eob++;
+
+ if(i) {
+ /* Write out the body part that didn't match */
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ i - last);
+
+ if(result)
+ return result;
+
+ last = i;
+ }
+ }
+ else if(pop3c->eob == 3)
+ pop3c->eob++;
+ else
+ /* If the character match wasn't at position 0 or 3 then restart the
+ pattern matching */
+ pop3c->eob = 1;
+ break;
+
+ case 0x0a:
+ if(pop3c->eob == 1 || pop3c->eob == 4)
+ pop3c->eob++;
+ else
+ /* If the character match wasn't at position 1 or 4 then start the
+ search again */
+ pop3c->eob = 0;
+ break;
+
+ case 0x2e:
+ if(pop3c->eob == 2)
+ pop3c->eob++;
+ else if(pop3c->eob == 3) {
+ /* We have an extra dot after the CRLF which we need to strip off */
+ strip_dot = TRUE;
+ pop3c->eob = 0;
+ }
+ else
+ /* If the character match wasn't at position 2 then start the search
+ again */
+ pop3c->eob = 0;
+ break;
+
+ default:
+ pop3c->eob = 0;
+ break;
+ }
+
+ /* Did we have a partial match which has subsequently failed? */
+ if(prev && prev >= pop3c->eob) {
+ /* Strip can only be non-zero for the very first mismatch after CRLF
+ and then both prev and strip are equal and nothing will be output
+ below */
+ while(prev && pop3c->strip) {
+ prev--;
+ pop3c->strip--;
+ }
+
+ if(prev) {
+ /* If the partial match was the CRLF and dot then only write the CRLF
+ as the server would have inserted the dot */
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
+ strip_dot ? prev - 1 : prev);
+
+ if(result)
+ return result;
+
+ last = i;
+ strip_dot = FALSE;
+ }
+ }
+ }
+
+ if(pop3c->eob == POP3_EOB_LEN) {
+ /* We have a full match so the transfer is done, however we must transfer
+ the CRLF at the start of the EOB as this is considered to be part of the
+ message as per RFC-1939, sect. 3 */
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2);
+
+ k->keepon &= ~KEEP_RECV;
+ pop3c->eob = 0;
+
+ return result;
+ }
+
+ if(pop3c->eob)
+ /* While EOB is matching nothing should be output */
+ return CURLE_OK;
+
+ if(nread - last) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ nread - last);
+ }
+
+ return result;
+}
+
+#endif /* CURL_DISABLE_POP3 */
diff --git a/libcurl/src/lib/pop3.h b/libcurl/src/lib/pop3.h
new file mode 100644
index 0000000..3e65d74
--- /dev/null
+++ b/libcurl/src/lib/pop3.h
@@ -0,0 +1,95 @@
+#ifndef HEADER_CURL_POP3_H
+#define HEADER_CURL_POP3_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+#include "curl_sasl.h"
+
+/****************************************************************************
+ * POP3 unique setup
+ ***************************************************************************/
+typedef enum {
+ POP3_STOP, /* do nothing state, stops the state machine */
+ POP3_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ POP3_CAPA,
+ POP3_STARTTLS,
+ POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ POP3_AUTH,
+ POP3_APOP,
+ POP3_USER,
+ POP3_PASS,
+ POP3_COMMAND,
+ POP3_QUIT,
+ POP3_LAST /* never used */
+} pop3state;
+
+/* This POP3 struct is used in the SessionHandle. All POP3 data that is
+ connection-oriented must be in pop3_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct POP3 {
+ curl_pp_transfer transfer;
+ char *id; /* Message ID */
+ char *custom; /* Custom Request */
+};
+
+/* pop3_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct pop3_conn {
+ struct pingpong pp;
+ pop3state state; /* Always use pop3.c:state() to change state! */
+ bool ssldone; /* Is connect() over SSL done? */
+ size_t eob; /* Number of bytes of the EOB (End Of Body) that
+ have been received so far */
+ size_t strip; /* Number of bytes from the start to ignore as
+ non-body */
+ struct SASL sasl; /* SASL-related storage */
+ unsigned int authtypes; /* Accepted authentication types */
+ unsigned int preftype; /* Preferred authentication type */
+ char *apoptimestamp; /* APOP timestamp from the server greeting */
+ bool tls_supported; /* StartTLS capability supported by server */
+};
+
+extern const struct Curl_handler Curl_handler_pop3;
+extern const struct Curl_handler Curl_handler_pop3s;
+
+/* Authentication type flags */
+#define POP3_TYPE_CLEARTEXT (1 << 0)
+#define POP3_TYPE_APOP (1 << 1)
+#define POP3_TYPE_SASL (1 << 2)
+
+/* Authentication type values */
+#define POP3_TYPE_NONE 0
+#define POP3_TYPE_ANY ~0U
+
+/* This is the 5-bytes End-Of-Body marker for POP3 */
+#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
+#define POP3_EOB_LEN 5
+
+/* This function scans the body after the end-of-body and writes everything
+ * until the end is found */
+CURL_STATIC CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread);
+
+#endif /* HEADER_CURL_POP3_H */
diff --git a/libcurl/src/lib/progress.c b/libcurl/src/lib/progress.c
new file mode 100644
index 0000000..d126237
--- /dev/null
+++ b/libcurl/src/lib/progress.c
@@ -0,0 +1,492 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "urldata.h"
+#include "sendf.h"
+#include "progress.h"
+#include "curl_printf.h"
+
+/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
+ byte) */
+static void time2str(char *r, curl_off_t seconds)
+{
+ curl_off_t d, h, m, s;
+ if(seconds <= 0) {
+ strcpy(r, "--:--:--");
+ return;
+ }
+ h = seconds / CURL_OFF_T_C(3600);
+ if(h <= CURL_OFF_T_C(99)) {
+ m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
+ s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
+ snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
+ ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
+ }
+ else {
+ /* this equals to more than 99 hours, switch to a more suitable output
+ format to fit within the limits. */
+ d = seconds / CURL_OFF_T_C(86400);
+ h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
+ if(d <= CURL_OFF_T_C(999))
+ snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
+ "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
+ else
+ snprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
+ }
+}
+
+/* The point of this function would be to return a string of the input data,
+ but never longer than 5 columns (+ one zero byte).
+ Add suffix k, M, G when suitable... */
+static char *max5data(curl_off_t bytes, char *max5)
+{
+#define ONE_KILOBYTE CURL_OFF_T_C(1024)
+#define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE)
+#define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE)
+#define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE)
+#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE)
+
+ if(bytes < CURL_OFF_T_C(100000))
+ snprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE)
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
+
+ else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE)
+ /* 'XX.XM' is good as long as we're less than 100 megs */
+ snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
+ (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
+ /* 'XXXXM' is good until we're at 10000MB or above */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+
+ else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE)
+ /* 10000 MB - 100 GB, we show it as XX.XG */
+ snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
+ (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE)
+ /* up to 10000GB, display without decimal: XXXXG */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE)
+ /* up to 10000TB, display without decimal: XXXXT */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
+
+ else
+ /* up to 10000PB, display without decimal: XXXXP */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
+
+ /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
+ can hold, but our data type is signed so 8192PB will be the maximum. */
+
+#else
+
+ else
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+
+#endif
+
+ return max5;
+}
+
+/*
+
+ New proposed interface, 9th of February 2000:
+
+ pgrsStartNow() - sets start time
+ pgrsSetDownloadSize(x) - known expected download size
+ pgrsSetUploadSize(x) - known expected upload size
+ pgrsSetDownloadCounter() - amount of data currently downloaded
+ pgrsSetUploadCounter() - amount of data currently uploaded
+ pgrsUpdate() - show progress
+ pgrsDone() - transfer complete
+
+*/
+
+CURL_STATIC int Curl_pgrsDone(struct connectdata *conn)
+{
+ int rc;
+ struct SessionHandle *data = conn->data;
+ data->progress.lastshow=0;
+ rc = Curl_pgrsUpdate(conn); /* the final (forced) update */
+ if(rc)
+ return rc;
+
+ if(!(data->progress.flags & PGRS_HIDE) &&
+ !data->progress.callback)
+ /* only output if we don't use a progress callback and we're not
+ * hidden */
+ fprintf(data->set.err, "\n");
+
+ data->progress.speeder_c = 0; /* reset the progress meter display */
+ return 0;
+}
+
+/* reset all times except redirect, and reset the known transfer sizes */
+CURL_STATIC void Curl_pgrsResetTimesSizes(struct SessionHandle *data)
+{
+ data->progress.t_nslookup = 0.0;
+ data->progress.t_connect = 0.0;
+ data->progress.t_pretransfer = 0.0;
+ data->progress.t_starttransfer = 0.0;
+
+ Curl_pgrsSetDownloadSize(data, -1);
+ Curl_pgrsSetUploadSize(data, -1);
+}
+
+CURL_STATIC void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
+{
+ struct timeval now = Curl_tvnow();
+
+ switch(timer) {
+ default:
+ case TIMER_NONE:
+ /* mistake filter */
+ break;
+ case TIMER_STARTOP:
+ /* This is set at the start of a transfer */
+ data->progress.t_startop = now;
+ break;
+ case TIMER_STARTSINGLE:
+ /* This is set at the start of each single fetch */
+ data->progress.t_startsingle = now;
+ break;
+
+ case TIMER_STARTACCEPT:
+ data->progress.t_acceptdata = Curl_tvnow();
+ break;
+
+ case TIMER_NAMELOOKUP:
+ data->progress.t_nslookup =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_CONNECT:
+ data->progress.t_connect =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_APPCONNECT:
+ data->progress.t_appconnect =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_PRETRANSFER:
+ data->progress.t_pretransfer =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_STARTTRANSFER:
+ data->progress.t_starttransfer =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_POSTRANSFER:
+ /* this is the normal end-of-transfer thing */
+ break;
+ case TIMER_REDIRECT:
+ data->progress.t_redirect = Curl_tvdiff_secs(now, data->progress.start);
+ break;
+ }
+}
+
+CURL_STATIC void Curl_pgrsStartNow(struct SessionHandle *data)
+{
+ data->progress.speeder_c = 0; /* reset the progress meter display */
+ data->progress.start = Curl_tvnow();
+ /* clear all bits except HIDE and HEADERS_OUT */
+ data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
+}
+
+CURL_STATIC void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size)
+{
+ data->progress.downloaded = size;
+}
+
+CURL_STATIC void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size)
+{
+ data->progress.uploaded = size;
+}
+
+CURL_STATIC void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size)
+{
+ if(size >= 0) {
+ data->progress.size_dl = size;
+ data->progress.flags |= PGRS_DL_SIZE_KNOWN;
+ }
+ else {
+ data->progress.size_dl = 0;
+ data->progress.flags &= ~PGRS_DL_SIZE_KNOWN;
+ }
+}
+
+CURL_STATIC void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size)
+{
+ if(size >= 0) {
+ data->progress.size_ul = size;
+ data->progress.flags |= PGRS_UL_SIZE_KNOWN;
+ }
+ else {
+ data->progress.size_ul = 0;
+ data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
+ }
+}
+
+/*
+ * Curl_pgrsUpdate() returns 0 for success or the value returned by the
+ * progress callback!
+ */
+CURL_STATIC int Curl_pgrsUpdate(struct connectdata *conn)
+{
+ struct timeval now;
+ int result;
+ char max5[6][10];
+ curl_off_t dlpercen=0;
+ curl_off_t ulpercen=0;
+ curl_off_t total_percen=0;
+ curl_off_t total_transfer;
+ curl_off_t total_expected_transfer;
+ curl_off_t timespent;
+ struct SessionHandle *data = conn->data;
+ int nowindex = data->progress.speeder_c% CURR_TIME;
+ int checkindex;
+ int countindex; /* amount of seconds stored in the speeder array */
+ char time_left[10];
+ char time_total[10];
+ char time_spent[10];
+ curl_off_t ulestimate=0;
+ curl_off_t dlestimate=0;
+ curl_off_t total_estimate;
+ bool shownow=FALSE;
+
+ now = Curl_tvnow(); /* what time is it */
+
+ /* The time spent so far (from the start) */
+ data->progress.timespent =
+ (double)(now.tv_sec - data->progress.start.tv_sec) +
+ (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0;
+ timespent = (curl_off_t)data->progress.timespent;
+
+ /* The average download speed this far */
+ data->progress.dlspeed = (curl_off_t)
+ ((double)data->progress.downloaded/
+ (data->progress.timespent>0?data->progress.timespent:1));
+
+ /* The average upload speed this far */
+ data->progress.ulspeed = (curl_off_t)
+ ((double)data->progress.uploaded/
+ (data->progress.timespent>0?data->progress.timespent:1));
+
+ /* Calculations done at most once a second, unless end is reached */
+ if(data->progress.lastshow != (long)now.tv_sec) {
+ shownow = TRUE;
+
+ data->progress.lastshow = now.tv_sec;
+
+ /* Let's do the "current speed" thing, which should use the fastest
+ of the dl/ul speeds. Store the faster speed at entry 'nowindex'. */
+ data->progress.speeder[ nowindex ] =
+ data->progress.downloaded>data->progress.uploaded?
+ data->progress.downloaded:data->progress.uploaded;
+
+ /* remember the exact time for this moment */
+ data->progress.speeder_time [ nowindex ] = now;
+
+ /* advance our speeder_c counter, which is increased every time we get
+ here and we expect it to never wrap as 2^32 is a lot of seconds! */
+ data->progress.speeder_c++;
+
+ /* figure out how many index entries of data we have stored in our speeder
+ array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of
+ transfer. Imagine, after one second we have filled in two entries,
+ after two seconds we've filled in three entries etc. */
+ countindex = ((data->progress.speeder_c>=CURR_TIME)?
+ CURR_TIME:data->progress.speeder_c) - 1;
+
+ /* first of all, we don't do this if there's no counted seconds yet */
+ if(countindex) {
+ long span_ms;
+
+ /* Get the index position to compare with the 'nowindex' position.
+ Get the oldest entry possible. While we have less than CURR_TIME
+ entries, the first entry will remain the oldest. */
+ checkindex = (data->progress.speeder_c>=CURR_TIME)?
+ data->progress.speeder_c%CURR_TIME:0;
+
+ /* Figure out the exact time for the time span */
+ span_ms = Curl_tvdiff(now,
+ data->progress.speeder_time[checkindex]);
+ if(0 == span_ms)
+ span_ms=1; /* at least one millisecond MUST have passed */
+
+ /* Calculate the average speed the last 'span_ms' milliseconds */
+ {
+ curl_off_t amount = data->progress.speeder[nowindex]-
+ data->progress.speeder[checkindex];
+
+ if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */)
+ /* the 'amount' value is bigger than would fit in 32 bits if
+ multiplied with 1000, so we use the double math for this */
+ data->progress.current_speed = (curl_off_t)
+ ((double)amount/((double)span_ms/1000.0));
+ else
+ /* the 'amount' value is small enough to fit within 32 bits even
+ when multiplied with 1000 */
+ data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms;
+ }
+ }
+ else
+ /* the first second we use the main average */
+ data->progress.current_speed =
+ (data->progress.ulspeed>data->progress.dlspeed)?
+ data->progress.ulspeed:data->progress.dlspeed;
+
+ } /* Calculations end */
+
+ if(!(data->progress.flags & PGRS_HIDE)) {
+ /* progress meter has not been shut off */
+
+ if(data->set.fxferinfo) {
+ /* There's a callback set, call that */
+ result= data->set.fxferinfo(data->set.progress_client,
+ data->progress.size_dl,
+ data->progress.downloaded,
+ data->progress.size_ul,
+ data->progress.uploaded);
+ if(result)
+ failf(data, "Callback aborted");
+ return result;
+ }
+ else if(data->set.fprogress) {
+ /* The older deprecated callback is set, call that */
+ result= data->set.fprogress(data->set.progress_client,
+ (double)data->progress.size_dl,
+ (double)data->progress.downloaded,
+ (double)data->progress.size_ul,
+ (double)data->progress.uploaded);
+ if(result)
+ failf(data, "Callback aborted");
+ return result;
+ }
+
+ if(!shownow)
+ /* only show the internal progress meter once per second */
+ return 0;
+
+ /* If there's no external callback set, use internal code to show
+ progress */
+
+ if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
+ if(data->state.resume_from) {
+ fprintf(data->set.err,
+ "** Resuming transfer from byte position %"
+ CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
+ }
+ fprintf(data->set.err,
+ " %% Total %% Received %% Xferd Average Speed "
+ "Time Time Time Current\n"
+ " Dload Upload "
+ "Total Spent Left Speed\n");
+ data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */
+ }
+
+ /* Figure out the estimated time of arrival for the upload */
+ if((data->progress.flags & PGRS_UL_SIZE_KNOWN) &&
+ (data->progress.ulspeed > CURL_OFF_T_C(0))) {
+ ulestimate = data->progress.size_ul / data->progress.ulspeed;
+
+ if(data->progress.size_ul > CURL_OFF_T_C(10000))
+ ulpercen = data->progress.uploaded /
+ (data->progress.size_ul/CURL_OFF_T_C(100));
+ else if(data->progress.size_ul > CURL_OFF_T_C(0))
+ ulpercen = (data->progress.uploaded*100) /
+ data->progress.size_ul;
+ }
+
+ /* ... and the download */
+ if((data->progress.flags & PGRS_DL_SIZE_KNOWN) &&
+ (data->progress.dlspeed > CURL_OFF_T_C(0))) {
+ dlestimate = data->progress.size_dl / data->progress.dlspeed;
+
+ if(data->progress.size_dl > CURL_OFF_T_C(10000))
+ dlpercen = data->progress.downloaded /
+ (data->progress.size_dl/CURL_OFF_T_C(100));
+ else if(data->progress.size_dl > CURL_OFF_T_C(0))
+ dlpercen = (data->progress.downloaded*100) /
+ data->progress.size_dl;
+ }
+
+ /* Now figure out which of them is slower and use that one for the
+ total estimate! */
+ total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
+
+ /* create the three time strings */
+ time2str(time_left, total_estimate > 0?(total_estimate - timespent):0);
+ time2str(time_total, total_estimate);
+ time2str(time_spent, timespent);
+
+ /* Get the total amount of data expected to get transferred */
+ total_expected_transfer =
+ (data->progress.flags & PGRS_UL_SIZE_KNOWN?
+ data->progress.size_ul:data->progress.uploaded)+
+ (data->progress.flags & PGRS_DL_SIZE_KNOWN?
+ data->progress.size_dl:data->progress.downloaded);
+
+ /* We have transferred this much so far */
+ total_transfer = data->progress.downloaded + data->progress.uploaded;
+
+ /* Get the percentage of data transferred so far */
+ if(total_expected_transfer > CURL_OFF_T_C(10000))
+ total_percen = total_transfer /
+ (total_expected_transfer/CURL_OFF_T_C(100));
+ else if(total_expected_transfer > CURL_OFF_T_C(0))
+ total_percen = (total_transfer*100) / total_expected_transfer;
+
+ fprintf(data->set.err,
+ "\r"
+ "%3" CURL_FORMAT_CURL_OFF_T " %s "
+ "%3" CURL_FORMAT_CURL_OFF_T " %s "
+ "%3" CURL_FORMAT_CURL_OFF_T " %s %s %s %s %s %s %s",
+ total_percen, /* 3 letters */ /* total % */
+ max5data(total_expected_transfer, max5[2]), /* total size */
+ dlpercen, /* 3 letters */ /* rcvd % */
+ max5data(data->progress.downloaded, max5[0]), /* rcvd size */
+ ulpercen, /* 3 letters */ /* xfer % */
+ max5data(data->progress.uploaded, max5[1]), /* xfer size */
+ max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */
+ max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */
+ time_total, /* 8 letters */ /* total time */
+ time_spent, /* 8 letters */ /* time spent */
+ time_left, /* 8 letters */ /* time left */
+ max5data(data->progress.current_speed, max5[5]) /* current speed */
+ );
+
+ /* we flush the output stream to make it appear as soon as possible */
+ fflush(data->set.err);
+
+ } /* !(data->progress.flags & PGRS_HIDE) */
+
+ return 0;
+}
diff --git a/libcurl/src/lib/progress.h b/libcurl/src/lib/progress.h
new file mode 100644
index 0000000..5a9c99f
--- /dev/null
+++ b/libcurl/src/lib/progress.h
@@ -0,0 +1,73 @@
+#ifndef HEADER_CURL_PROGRESS_H
+#define HEADER_CURL_PROGRESS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "timeval.h"
+
+
+typedef enum {
+ TIMER_NONE,
+ TIMER_STARTOP,
+ TIMER_STARTSINGLE,
+ TIMER_NAMELOOKUP,
+ TIMER_CONNECT,
+ TIMER_APPCONNECT,
+ TIMER_PRETRANSFER,
+ TIMER_STARTTRANSFER,
+ TIMER_POSTRANSFER,
+ TIMER_STARTACCEPT,
+ TIMER_REDIRECT,
+ TIMER_LAST /* must be last */
+} timerid;
+
+CURL_STATIC int Curl_pgrsDone(struct connectdata *);
+CURL_STATIC void Curl_pgrsStartNow(struct SessionHandle *data);
+CURL_STATIC void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size);
+CURL_STATIC void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size);
+CURL_STATIC void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size);
+CURL_STATIC void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size);
+CURL_STATIC int Curl_pgrsUpdate(struct connectdata *);
+CURL_STATIC void Curl_pgrsResetTimesSizes(struct SessionHandle *data);
+CURL_STATIC void Curl_pgrsTime(struct SessionHandle *data, timerid timer);
+
+
+/* Don't show progress for sizes smaller than: */
+#define LEAST_SIZE_PROGRESS BUFSIZE
+
+#define PROGRESS_DOWNLOAD (1<<0)
+#define PROGRESS_UPLOAD (1<<1)
+#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD)
+
+#define PGRS_SHOW_DL (1<<0)
+#define PGRS_SHOW_UL (1<<1)
+#define PGRS_DONE_DL (1<<2)
+#define PGRS_DONE_UL (1<<3)
+#define PGRS_HIDE (1<<4)
+#define PGRS_UL_SIZE_KNOWN (1<<5)
+#define PGRS_DL_SIZE_KNOWN (1<<6)
+
+#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
+
+
+#endif /* HEADER_CURL_PROGRESS_H */
+
diff --git a/libcurl/src/lib/rawstr.c b/libcurl/src/lib/rawstr.c
new file mode 100644
index 0000000..541e3f6
--- /dev/null
+++ b/libcurl/src/lib/rawstr.c
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "rawstr.h"
+
+/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
+ its behavior is altered by the current locale. */
+CURL_STATIC char Curl_raw_toupper(char in)
+{
+ switch (in) {
+ case 'a':
+ return 'A';
+ case 'b':
+ return 'B';
+ case 'c':
+ return 'C';
+ case 'd':
+ return 'D';
+ case 'e':
+ return 'E';
+ case 'f':
+ return 'F';
+ case 'g':
+ return 'G';
+ case 'h':
+ return 'H';
+ case 'i':
+ return 'I';
+ case 'j':
+ return 'J';
+ case 'k':
+ return 'K';
+ case 'l':
+ return 'L';
+ case 'm':
+ return 'M';
+ case 'n':
+ return 'N';
+ case 'o':
+ return 'O';
+ case 'p':
+ return 'P';
+ case 'q':
+ return 'Q';
+ case 'r':
+ return 'R';
+ case 's':
+ return 'S';
+ case 't':
+ return 'T';
+ case 'u':
+ return 'U';
+ case 'v':
+ return 'V';
+ case 'w':
+ return 'W';
+ case 'x':
+ return 'X';
+ case 'y':
+ return 'Y';
+ case 'z':
+ return 'Z';
+ }
+ return in;
+}
+
+/*
+ * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
+ * to be locale independent and only compare strings we know are safe for
+ * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
+ * some further explanation to why this function is necessary.
+ *
+ * The function is capable of comparing a-z case insensitively even for
+ * non-ascii.
+ */
+
+CURL_STATIC int Curl_raw_equal(const char *first, const char *second)
+{
+ while(*first && *second) {
+ if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
+ /* get out of the loop as soon as they don't match */
+ break;
+ first++;
+ second++;
+ }
+ /* we do the comparison here (possibly again), just to make sure that if the
+ loop above is skipped because one of the strings reached zero, we must not
+ return this as a successful match */
+ return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
+}
+
+CURL_STATIC int Curl_raw_nequal(const char *first, const char *second, size_t max)
+{
+ while(*first && *second && max) {
+ if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
+ break;
+ }
+ max--;
+ first++;
+ second++;
+ }
+ if(0 == max)
+ return 1; /* they are equal this far */
+
+ return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
+}
+
+/* Copy an upper case version of the string from src to dest. The
+ * strings may overlap. No more than n characters of the string are copied
+ * (including any NUL) and the destination string will NOT be
+ * NUL-terminated if that limit is reached.
+ */
+CURL_STATIC void Curl_strntoupper(char *dest, const char *src, size_t n)
+{
+ if(n < 1)
+ return;
+
+ do {
+ *dest++ = Curl_raw_toupper(*src);
+ } while(*src++ && --n);
+}
diff --git a/libcurl/src/lib/rawstr.h b/libcurl/src/lib/rawstr.h
new file mode 100644
index 0000000..554e050
--- /dev/null
+++ b/libcurl/src/lib/rawstr.h
@@ -0,0 +1,47 @@
+#ifndef HEADER_CURL_RAWSTR_H
+#define HEADER_CURL_RAWSTR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+/*
+ * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
+ * to be locale independent and only compare strings we know are safe for
+ * this.
+ *
+ * The function is capable of comparing a-z case insensitively even for
+ * non-ascii.
+ */
+CURL_STATIC int Curl_raw_equal(const char *first, const char *second);
+CURL_STATIC int Curl_raw_nequal(const char *first, const char *second, size_t max);
+
+CURL_STATIC char Curl_raw_toupper(char in);
+
+/* checkprefix() is a shorter version of the above, used when the first
+ argument is zero-byte terminated */
+#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a))
+
+CURL_STATIC void Curl_strntoupper(char *dest, const char *src, size_t n);
+
+#endif /* HEADER_CURL_RAWSTR_H */
+
diff --git a/libcurl/src/lib/rtsp.c b/libcurl/src/lib/rtsp.c
new file mode 100644
index 0000000..531d206
--- /dev/null
+++ b/libcurl/src/lib/rtsp.c
@@ -0,0 +1,807 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_RTSP
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "http.h"
+#include "url.h"
+#include "progress.h"
+#include "rtsp.h"
+#include "rawstr.h"
+#include "select.h"
+#include "connect.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * TODO (general)
+ * -incoming server requests
+ * -server CSeq counter
+ * -digest authentication
+ * -connect thru proxy
+ * -pipelining?
+ */
+
+
+#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1])))
+
+#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \
+ ((int)((unsigned char)((p)[3]))))
+
+/* protocol-specific functions set up to be called by the main engine */
+static CURLcode rtsp_do(struct connectdata *conn, bool *done);
+static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature);
+static CURLcode rtsp_connect(struct connectdata *conn, bool *done);
+static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead);
+
+static int rtsp_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+/*
+ * Parse and write out any available RTP data.
+ *
+ * nread: amount of data left after k->str. will be modified if RTP
+ * data is parsed and k->str is moved up
+ * readmore: whether or not the RTP parser needs more data right away
+ */
+static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *readmore);
+
+static CURLcode rtsp_setup_connection(struct connectdata *conn);
+
+
+/* this returns the socket to wait for in the DO and DOING state for the multi
+ interface and then we're always _sending_ a request and thus we wait for
+ the single socket to become writable only */
+static int rtsp_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ /* write mode */
+ (void)numsocks; /* unused, we trust it to be at least 1 */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_WRITESOCK(0);
+}
+
+static
+CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
+
+
+/*
+ * RTSP handler interface.
+ */
+const struct Curl_handler Curl_handler_rtsp = {
+ "RTSP", /* scheme */
+ rtsp_setup_connection, /* setup_connection */
+ rtsp_do, /* do_it */
+ rtsp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtsp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ rtsp_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtsp_disconnect, /* disconnect */
+ rtsp_rtp_readwrite, /* readwrite */
+ PORT_RTSP, /* defport */
+ CURLPROTO_RTSP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+
+static CURLcode rtsp_setup_connection(struct connectdata *conn)
+{
+ struct RTSP *rtsp;
+
+ conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP));
+ if(!rtsp)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+
+/*
+ * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not
+ * want to block the application forever while receiving a stream. Therefore,
+ * we cannot assume that an RTSP socket is dead just because it is readable.
+ *
+ * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket
+ * and distinguish between closed and data.
+ */
+CURL_STATIC bool Curl_rtsp_connisdead(struct connectdata *check)
+{
+ int sval;
+ bool ret_val = TRUE;
+
+ sval = Curl_socket_ready(check->sock[FIRSTSOCKET], CURL_SOCKET_BAD, 0);
+ if(sval == 0) {
+ /* timeout */
+ ret_val = FALSE;
+ }
+ else if(sval & CURL_CSELECT_ERR) {
+ /* socket is in an error state */
+ ret_val = TRUE;
+ }
+ else if((sval & CURL_CSELECT_IN) && check->data) {
+ /* readable with no error. could be closed or could be alive but we can
+ only check if we have a proper SessionHandle for the connection */
+ curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check);
+ if(connectinfo != CURL_SOCKET_BAD)
+ ret_val = FALSE;
+ }
+
+ return ret_val;
+}
+
+static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode httpStatus;
+ struct SessionHandle *data = conn->data;
+
+ httpStatus = Curl_http_connect(conn, done);
+
+ /* Initialize the CSeq if not already done */
+ if(data->state.rtsp_next_client_CSeq == 0)
+ data->state.rtsp_next_client_CSeq = 1;
+ if(data->state.rtsp_next_server_CSeq == 0)
+ data->state.rtsp_next_server_CSeq = 1;
+
+ conn->proto.rtspc.rtp_channel = -1;
+
+ return httpStatus;
+}
+
+static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead)
+{
+ (void) dead;
+ Curl_safefree(conn->proto.rtspc.rtp_buf);
+ return CURLE_OK;
+}
+
+
+static CURLcode rtsp_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct SessionHandle *data = conn->data;
+ struct RTSP *rtsp = data->req.protop;
+ CURLcode httpStatus;
+ long CSeq_sent;
+ long CSeq_recv;
+
+ /* Bypass HTTP empty-reply checks on receive */
+ if(data->set.rtspreq == RTSPREQ_RECEIVE)
+ premature = TRUE;
+
+ httpStatus = Curl_http_done(conn, status, premature);
+
+ if(rtsp) {
+ /* Check the sequence numbers */
+ CSeq_sent = rtsp->CSeq_sent;
+ CSeq_recv = rtsp->CSeq_recv;
+ if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) {
+ failf(data,
+ "The CSeq of this request %ld did not match the response %ld",
+ CSeq_sent, CSeq_recv);
+ return CURLE_RTSP_CSEQ_ERROR;
+ }
+ else if(data->set.rtspreq == RTSPREQ_RECEIVE &&
+ (conn->proto.rtspc.rtp_channel == -1)) {
+ infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
+ /* TODO CPC: Server -> Client logic here */
+ }
+ }
+
+ return httpStatus;
+}
+
+static CURLcode rtsp_do(struct connectdata *conn, bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode result=CURLE_OK;
+ Curl_RtspReq rtspreq = data->set.rtspreq;
+ struct RTSP *rtsp = data->req.protop;
+ struct HTTP *http;
+ Curl_send_buffer *req_buffer;
+ curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
+ curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
+
+ const char *p_request = NULL;
+ const char *p_session_id = NULL;
+ const char *p_accept = NULL;
+ const char *p_accept_encoding = NULL;
+ const char *p_range = NULL;
+ const char *p_referrer = NULL;
+ const char *p_stream_uri = NULL;
+ const char *p_transport = NULL;
+ const char *p_uagent = NULL;
+
+ *done = TRUE;
+
+ http = &(rtsp->http_wrapper);
+ /* Assert that no one has changed the RTSP struct in an evil way */
+ DEBUGASSERT((void *)http == (void *)rtsp);
+
+ rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
+ rtsp->CSeq_recv = 0;
+
+ /* Setup the 'p_request' pointer to the proper p_request string
+ * Since all RTSP requests are included here, there is no need to
+ * support custom requests like HTTP.
+ **/
+ DEBUGASSERT((rtspreq > RTSPREQ_NONE && rtspreq < RTSPREQ_LAST));
+ data->set.opt_no_body = TRUE; /* most requests don't contain a body */
+ switch(rtspreq) {
+ case RTSPREQ_NONE:
+ failf(data, "Got invalid RTSP request: RTSPREQ_NONE");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ case RTSPREQ_OPTIONS:
+ p_request = "OPTIONS";
+ break;
+ case RTSPREQ_DESCRIBE:
+ p_request = "DESCRIBE";
+ data->set.opt_no_body = FALSE;
+ break;
+ case RTSPREQ_ANNOUNCE:
+ p_request = "ANNOUNCE";
+ break;
+ case RTSPREQ_SETUP:
+ p_request = "SETUP";
+ break;
+ case RTSPREQ_PLAY:
+ p_request = "PLAY";
+ break;
+ case RTSPREQ_PAUSE:
+ p_request = "PAUSE";
+ break;
+ case RTSPREQ_TEARDOWN:
+ p_request = "TEARDOWN";
+ break;
+ case RTSPREQ_GET_PARAMETER:
+ /* GET_PARAMETER's no_body status is determined later */
+ p_request = "GET_PARAMETER";
+ data->set.opt_no_body = FALSE;
+ break;
+ case RTSPREQ_SET_PARAMETER:
+ p_request = "SET_PARAMETER";
+ break;
+ case RTSPREQ_RECORD:
+ p_request = "RECORD";
+ break;
+ case RTSPREQ_RECEIVE:
+ p_request = "";
+ /* Treat interleaved RTP as body*/
+ data->set.opt_no_body = FALSE;
+ break;
+ case RTSPREQ_LAST:
+ failf(data, "Got invalid RTSP request: RTSPREQ_LAST");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ if(rtspreq == RTSPREQ_RECEIVE) {
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, -1, NULL);
+
+ return result;
+ }
+
+ p_session_id = data->set.str[STRING_RTSP_SESSION_ID];
+ if(!p_session_id &&
+ (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) {
+ failf(data, "Refusing to issue an RTSP request [%s] without a session ID.",
+ p_request ? p_request : "");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ /* TODO: auth? */
+ /* TODO: proxy? */
+
+ /* Stream URI. Default to server '*' if not specified */
+ if(data->set.str[STRING_RTSP_STREAM_URI]) {
+ p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI];
+ }
+ else {
+ p_stream_uri = "*";
+ }
+
+ /* Transport Header for SETUP requests */
+ p_transport = Curl_checkheaders(conn, "Transport:");
+ if(rtspreq == RTSPREQ_SETUP && !p_transport) {
+ /* New Transport: setting? */
+ if(data->set.str[STRING_RTSP_TRANSPORT]) {
+ Curl_safefree(conn->allocptr.rtsp_transport);
+
+ conn->allocptr.rtsp_transport =
+ aprintf("Transport: %s\r\n",
+ data->set.str[STRING_RTSP_TRANSPORT]);
+ if(!conn->allocptr.rtsp_transport)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ failf(data,
+ "Refusing to issue an RTSP SETUP without a Transport: header.");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ p_transport = conn->allocptr.rtsp_transport;
+ }
+
+ /* Accept Headers for DESCRIBE requests */
+ if(rtspreq == RTSPREQ_DESCRIBE) {
+ /* Accept Header */
+ p_accept = Curl_checkheaders(conn, "Accept:")?
+ NULL:"Accept: application/sdp\r\n";
+
+ /* Accept-Encoding header */
+ if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ data->set.str[STRING_ENCODING]) {
+ Curl_safefree(conn->allocptr.accept_encoding);
+ conn->allocptr.accept_encoding =
+ aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
+
+ if(!conn->allocptr.accept_encoding)
+ return CURLE_OUT_OF_MEMORY;
+
+ p_accept_encoding = conn->allocptr.accept_encoding;
+ }
+ }
+
+ /* The User-Agent string might have been allocated in url.c already, because
+ it might have been used in the proxy connect, but if we have got a header
+ with the user-agent string specified, we erase the previously made string
+ here. */
+ if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
+ Curl_safefree(conn->allocptr.uagent);
+ conn->allocptr.uagent = NULL;
+ }
+ else if(!Curl_checkheaders(conn, "User-Agent:") &&
+ data->set.str[STRING_USERAGENT]) {
+ p_uagent = conn->allocptr.uagent;
+ }
+
+ /* Referrer */
+ Curl_safefree(conn->allocptr.ref);
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
+ conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ else
+ conn->allocptr.ref = NULL;
+
+ p_referrer = conn->allocptr.ref;
+
+ /*
+ * Range Header
+ * Only applies to PLAY, PAUSE, RECORD
+ *
+ * Go ahead and use the Range stuff supplied for HTTP
+ */
+ if(data->state.use_range &&
+ (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
+
+ /* Check to see if there is a range set in the custom headers */
+ if(!Curl_checkheaders(conn, "Range:") && data->state.range) {
+ Curl_safefree(conn->allocptr.rangeline);
+ conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
+ p_range = conn->allocptr.rangeline;
+ }
+ }
+
+ /*
+ * Sanity check the custom headers
+ */
+ if(Curl_checkheaders(conn, "CSeq:")) {
+ failf(data, "CSeq cannot be set as a custom header.");
+ return CURLE_RTSP_CSEQ_ERROR;
+ }
+ if(Curl_checkheaders(conn, "Session:")) {
+ failf(data, "Session ID cannot be set as a custom header.");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ /* Initialize a dynamic send buffer */
+ req_buffer = Curl_add_buffer_init();
+
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ result =
+ Curl_add_bufferf(req_buffer,
+ "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
+ "CSeq: %ld\r\n", /* CSeq */
+ (p_request ? p_request : ""), p_stream_uri,
+ rtsp->CSeq_sent);
+ if(result)
+ return result;
+
+ /*
+ * Rather than do a normal alloc line, keep the session_id unformatted
+ * to make comparison easier
+ */
+ if(p_session_id) {
+ result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id);
+ if(result)
+ return result;
+ }
+
+ /*
+ * Shared HTTP-like options
+ */
+ result = Curl_add_bufferf(req_buffer,
+ "%s" /* transport */
+ "%s" /* accept */
+ "%s" /* accept-encoding */
+ "%s" /* range */
+ "%s" /* referrer */
+ "%s" /* user-agent */
+ ,
+ p_transport ? p_transport : "",
+ p_accept ? p_accept : "",
+ p_accept_encoding ? p_accept_encoding : "",
+ p_range ? p_range : "",
+ p_referrer ? p_referrer : "",
+ p_uagent ? p_uagent : "");
+ if(result)
+ return result;
+
+ if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
+ result = Curl_add_timecondition(data, req_buffer);
+ if(result)
+ return result;
+ }
+
+ result = Curl_add_custom_headers(conn, FALSE, req_buffer);
+ if(result)
+ return result;
+
+ if(rtspreq == RTSPREQ_ANNOUNCE ||
+ rtspreq == RTSPREQ_SET_PARAMETER ||
+ rtspreq == RTSPREQ_GET_PARAMETER) {
+
+ if(data->set.upload) {
+ putsize = data->state.infilesize;
+ data->set.httpreq = HTTPREQ_PUT;
+
+ }
+ else {
+ postsize = (data->set.postfieldsize != -1)?
+ data->set.postfieldsize:
+ (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
+ data->set.httpreq = HTTPREQ_POST;
+ }
+
+ if(putsize > 0 || postsize > 0) {
+ /* As stated in the http comments, it is probably not wise to
+ * actually set a custom Content-Length in the headers */
+ if(!Curl_checkheaders(conn, "Content-Length:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
+ (data->set.upload ? putsize : postsize));
+ if(result)
+ return result;
+ }
+
+ if(rtspreq == RTSPREQ_SET_PARAMETER ||
+ rtspreq == RTSPREQ_GET_PARAMETER) {
+ if(!Curl_checkheaders(conn, "Content-Type:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Type: text/parameters\r\n");
+ if(result)
+ return result;
+ }
+ }
+
+ if(rtspreq == RTSPREQ_ANNOUNCE) {
+ if(!Curl_checkheaders(conn, "Content-Type:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Type: application/sdp\r\n");
+ if(result)
+ return result;
+ }
+ }
+
+ data->state.expect100header = FALSE; /* RTSP posts are simple/small */
+ }
+ else if(rtspreq == RTSPREQ_GET_PARAMETER) {
+ /* Check for an empty GET_PARAMETER (heartbeat) request */
+ data->set.httpreq = HTTPREQ_HEAD;
+ data->set.opt_no_body = TRUE;
+ }
+ }
+
+ /* RTSP never allows chunked transfer */
+ data->req.forbidchunk = TRUE;
+ /* Finish the request buffer */
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ if(result)
+ return result;
+
+ if(postsize > 0) {
+ result = Curl_add_buffer(req_buffer, data->set.postfields,
+ (size_t)postsize);
+ if(result)
+ return result;
+ }
+
+ /* issue the request */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result) {
+ failf(data, "Failed sending RTSP request");
+ return result;
+ }
+
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
+ putsize?FIRSTSOCKET:-1,
+ putsize?&http->writebytecount:NULL);
+
+ /* Increment the CSeq on success */
+ data->state.rtsp_next_client_CSeq++;
+
+ if(http->writebytecount) {
+ /* if a request-body has been sent off, we make sure this progress is
+ noted properly */
+ Curl_pgrsSetUploadCounter(data, http->writebytecount);
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ }
+
+ return result;
+}
+
+
+static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *readmore) {
+ struct SingleRequest *k = &data->req;
+ struct rtsp_conn *rtspc = &(conn->proto.rtspc);
+
+ char *rtp; /* moving pointer to rtp data */
+ ssize_t rtp_dataleft; /* how much data left to parse in this round */
+ char *scratch;
+ CURLcode result;
+
+ if(rtspc->rtp_buf) {
+ /* There was some leftover data the last time. Merge buffers */
+ char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread);
+ if(!newptr) {
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ rtspc->rtp_buf = newptr;
+ memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread);
+ rtspc->rtp_bufsize += *nread;
+ rtp = rtspc->rtp_buf;
+ rtp_dataleft = rtspc->rtp_bufsize;
+ }
+ else {
+ /* Just parse the request buffer directly */
+ rtp = k->str;
+ rtp_dataleft = *nread;
+ }
+
+ while((rtp_dataleft > 0) &&
+ (rtp[0] == '$')) {
+ if(rtp_dataleft > 4) {
+ int rtp_length;
+
+ /* Parse the header */
+ /* The channel identifier immediately follows and is 1 byte */
+ rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp);
+
+ /* The length is two bytes */
+ rtp_length = RTP_PKT_LENGTH(rtp);
+
+ if(rtp_dataleft < rtp_length + 4) {
+ /* Need more - incomplete payload*/
+ *readmore = TRUE;
+ break;
+ }
+ else {
+ /* We have the full RTP interleaved packet
+ * Write out the header including the leading '$' */
+ DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
+ rtspc->rtp_channel, rtp_length));
+ result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
+ if(result) {
+ failf(data, "Got an error writing an RTP packet");
+ *readmore = FALSE;
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+ return result;
+ }
+
+ /* Move forward in the buffer */
+ rtp_dataleft -= rtp_length + 4;
+ rtp += rtp_length + 4;
+
+ if(data->set.rtspreq == RTSPREQ_RECEIVE) {
+ /* If we are in a passive receive, give control back
+ * to the app as often as we can.
+ */
+ k->keepon &= ~KEEP_RECV;
+ }
+ }
+ }
+ else {
+ /* Need more - incomplete header */
+ *readmore = TRUE;
+ break;
+ }
+ }
+
+ if(rtp_dataleft != 0 && rtp[0] == '$') {
+ DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft,
+ *readmore ? "(READMORE)" : ""));
+
+ /* Store the incomplete RTP packet for a "rewind" */
+ scratch = malloc(rtp_dataleft);
+ if(!scratch) {
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(scratch, rtp, rtp_dataleft);
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = scratch;
+ rtspc->rtp_bufsize = rtp_dataleft;
+
+ /* As far as the transfer is concerned, this data is consumed */
+ *nread = 0;
+ return CURLE_OK;
+ }
+ else {
+ /* Fix up k->str to point just after the last RTP packet */
+ k->str += *nread - rtp_dataleft;
+
+ /* either all of the data has been read or...
+ * rtp now points at the next byte to parse
+ */
+ if(rtp_dataleft > 0)
+ DEBUGASSERT(k->str[0] == rtp[0]);
+
+ DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
+
+ *nread = rtp_dataleft;
+ }
+
+ /* If we get here, we have finished with the leftover/merge buffer */
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+
+ return CURLE_OK;
+}
+
+static
+CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
+{
+ struct SessionHandle *data = conn->data;
+ size_t wrote;
+ curl_write_callback writeit;
+
+ if(len == 0) {
+ failf (data, "Cannot write a 0 size RTP packet.");
+ return CURLE_WRITE_ERROR;
+ }
+
+ writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func;
+ wrote = writeit(ptr, 1, len, data->set.rtp_out);
+
+ if(CURL_WRITEFUNC_PAUSE == wrote) {
+ failf (data, "Cannot pause RTP");
+ return CURLE_WRITE_ERROR;
+ }
+
+ if(wrote != len) {
+ failf (data, "Failed writing RTP data");
+ return CURLE_WRITE_ERROR;
+ }
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
+ char *header)
+{
+ struct SessionHandle *data = conn->data;
+ long CSeq = 0;
+
+ if(checkprefix("CSeq:", header)) {
+ /* Store the received CSeq. Match is verified in rtsp_done */
+ int nc = sscanf(&header[4], ": %ld", &CSeq);
+ if(nc == 1) {
+ struct RTSP *rtsp = data->req.protop;
+ rtsp->CSeq_recv = CSeq; /* mark the request */
+ data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
+ }
+ else {
+ failf(data, "Unable to read the CSeq header: [%s]", header);
+ return CURLE_RTSP_CSEQ_ERROR;
+ }
+ }
+ else if(checkprefix("Session:", header)) {
+ char *start;
+
+ /* Find the first non-space letter */
+ start = header + 8;
+ while(*start && ISSPACE(*start))
+ start++;
+
+ if(!*start) {
+ failf(data, "Got a blank Session ID");
+ }
+ else if(data->set.str[STRING_RTSP_SESSION_ID]) {
+ /* If the Session ID is set, then compare */
+ if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID],
+ strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) {
+ failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
+ start, data->set.str[STRING_RTSP_SESSION_ID]);
+ return CURLE_RTSP_SESSION_ERROR;
+ }
+ }
+ else {
+ /* If the Session ID is not set, and we find it in a response, then
+ set it */
+
+ /* The session ID can be an alphanumeric or a 'safe' character
+ *
+ * RFC 2326 15.1 Base Syntax:
+ * safe = "\$" | "-" | "_" | "." | "+"
+ * */
+ char *end = start;
+ while(*end &&
+ (ISALNUM(*end) || *end == '-' || *end == '_' || *end == '.' ||
+ *end == '+' ||
+ (*end == '\\' && *(end + 1) && *(end + 1) == '$' && (++end, 1))))
+ end++;
+
+ /* Copy the id substring into a new buffer */
+ data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1);
+ if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start);
+ (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0';
+ }
+ }
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_RTSP */
diff --git a/libcurl/src/lib/rtsp.h b/libcurl/src/lib/rtsp.h
new file mode 100644
index 0000000..00933c0
--- /dev/null
+++ b/libcurl/src/lib/rtsp.h
@@ -0,0 +1,69 @@
+#ifndef HEADER_CURL_RTSP_H
+#define HEADER_CURL_RTSP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_RTSP
+
+extern const struct Curl_handler Curl_handler_rtsp;
+
+CURL_STATIC bool Curl_rtsp_connisdead(struct connectdata *check);
+CURL_STATIC CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);
+
+#else
+/* disabled */
+#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN
+#define Curl_rtsp_connisdead(x) TRUE
+
+#endif /* CURL_DISABLE_RTSP */
+
+/*
+ * RTSP Connection data
+ *
+ * Currently, only used for tracking incomplete RTP data reads
+ */
+struct rtsp_conn {
+ char *rtp_buf;
+ ssize_t rtp_bufsize;
+ int rtp_channel;
+};
+
+/****************************************************************************
+ * RTSP unique setup
+ ***************************************************************************/
+struct RTSP {
+ /*
+ * http_wrapper MUST be the first element of this structure for the wrap
+ * logic to work. In this way, we get a cheap polymorphism because
+ * &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec
+ *
+ * HTTP functions can safely treat this as an HTTP struct, but RTSP aware
+ * functions can also index into the later elements.
+ */
+ struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */
+
+ long CSeq_sent; /* CSeq of this request */
+ long CSeq_recv; /* CSeq received */
+};
+
+
+#endif /* HEADER_CURL_RTSP_H */
+
diff --git a/libcurl/src/lib/security.c b/libcurl/src/lib/security.c
new file mode 100644
index 0000000..10cb73c
--- /dev/null
+++ b/libcurl/src/lib/security.c
@@ -0,0 +1,597 @@
+/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
+ * use in Curl. His latest changes were done 2000-09-18.
+ *
+ * It has since been patched and modified a lot by Daniel Stenberg
+ * <daniel@haxx.se> to make it better applied to curl conditions, and to make
+ * it not use globals, pollute name space and more. This source code awaits a
+ * rewrite to work around the paragraph 2 in the BSD licenses as explained
+ * below.
+ *
+ * Copyright (c) 1998, 1999 Kungliga Tekniska Hgskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ *
+ * Copyright (C) 2001 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+#ifdef HAVE_GSSAPI
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "urldata.h"
+#include "curl_base64.h"
+#include "curl_memory.h"
+#include "curl_sec.h"
+#include "ftp.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "warnless.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static const struct {
+ enum protection_level level;
+ const char *name;
+} level_names[] = {
+ { PROT_CLEAR, "clear" },
+ { PROT_SAFE, "safe" },
+ { PROT_CONFIDENTIAL, "confidential" },
+ { PROT_PRIVATE, "private" }
+};
+
+static enum protection_level
+name_to_level(const char *name)
+{
+ int i;
+ for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
+ if(checkprefix(name, level_names[i].name))
+ return level_names[i].level;
+ return PROT_NONE;
+}
+
+/* Convert a protocol |level| to its char representation.
+ We take an int to catch programming mistakes. */
+static char level_to_char(int level) {
+ switch(level) {
+ case PROT_CLEAR:
+ return 'C';
+ case PROT_SAFE:
+ return 'S';
+ case PROT_CONFIDENTIAL:
+ return 'E';
+ case PROT_PRIVATE:
+ return 'P';
+ case PROT_CMD:
+ /* Fall through */
+ default:
+ /* Those 2 cases should not be reached! */
+ break;
+ }
+ DEBUGASSERT(0);
+ /* Default to the most secure alternative. */
+ return 'P';
+}
+
+static const struct Curl_sec_client_mech * const mechs[] = {
+#ifdef HAVE_GSSAPI
+ &Curl_krb5_client_mech,
+#endif
+ NULL
+};
+
+/* Send an FTP command defined by |message| and the optional arguments. The
+ function returns the ftp_code. If an error occurs, -1 is returned. */
+static int ftp_send_command(struct connectdata *conn, const char *message, ...)
+{
+ int ftp_code;
+ ssize_t nread=0;
+ va_list args;
+ char print_buffer[50];
+
+ va_start(args, message);
+ vsnprintf(print_buffer, sizeof(print_buffer), message, args);
+ va_end(args);
+
+ if(Curl_ftpsendf(conn, print_buffer)) {
+ ftp_code = -1;
+ }
+ else {
+ if(Curl_GetFTPResponse(&nread, conn, &ftp_code))
+ ftp_code = -1;
+ }
+
+ (void)nread; /* Unused */
+ return ftp_code;
+}
+
+/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
+ saying whether an error occurred or CURLE_OK if |len| was read. */
+static CURLcode
+socket_read(curl_socket_t fd, void *to, size_t len)
+{
+ char *to_p = to;
+ CURLcode result;
+ ssize_t nread;
+
+ while(len > 0) {
+ result = Curl_read_plain(fd, to_p, len, &nread);
+ if(!result) {
+ len -= nread;
+ to_p += nread;
+ }
+ else {
+ /* FIXME: We are doing a busy wait */
+ if(result == CURLE_AGAIN)
+ continue;
+ return result;
+ }
+ }
+ return CURLE_OK;
+}
+
+
+/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a
+ CURLcode saying whether an error occurred or CURLE_OK if |len| was
+ written. */
+static CURLcode
+socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
+ size_t len)
+{
+ const char *to_p = to;
+ CURLcode result;
+ ssize_t written;
+
+ while(len > 0) {
+ result = Curl_write_plain(conn, fd, to_p, len, &written);
+ if(!result) {
+ len -= written;
+ to_p += written;
+ }
+ else {
+ /* FIXME: We are doing a busy wait */
+ if(result == CURLE_AGAIN)
+ continue;
+ return result;
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode read_data(struct connectdata *conn,
+ curl_socket_t fd,
+ struct krb5buffer *buf)
+{
+ int len;
+ void* tmp;
+ CURLcode result;
+
+ result = socket_read(fd, &len, sizeof(len));
+ if(result)
+ return result;
+
+ len = ntohl(len);
+ tmp = realloc(buf->data, len);
+ if(tmp == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ buf->data = tmp;
+ result = socket_read(fd, buf->data, len);
+ if(result)
+ return result;
+ buf->size = conn->mech->decode(conn->app_data, buf->data, len,
+ conn->data_prot, conn);
+ buf->index = 0;
+ return CURLE_OK;
+}
+
+static size_t
+buffer_read(struct krb5buffer *buf, void *data, size_t len)
+{
+ if(buf->size - buf->index < len)
+ len = buf->size - buf->index;
+ memcpy(data, (char*)buf->data + buf->index, len);
+ buf->index += len;
+ return len;
+}
+
+/* Matches Curl_recv signature */
+static ssize_t sec_recv(struct connectdata *conn, int sockindex,
+ char *buffer, size_t len, CURLcode *err)
+{
+ size_t bytes_read;
+ size_t total_read = 0;
+ curl_socket_t fd = conn->sock[sockindex];
+
+ *err = CURLE_OK;
+
+ /* Handle clear text response. */
+ if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
+ return read(fd, buffer, len);
+
+ if(conn->in_buffer.eof_flag) {
+ conn->in_buffer.eof_flag = 0;
+ return 0;
+ }
+
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+
+ while(len > 0) {
+ if(read_data(conn, fd, &conn->in_buffer))
+ return -1;
+ if(conn->in_buffer.size == 0) {
+ if(bytes_read > 0)
+ conn->in_buffer.eof_flag = 1;
+ return bytes_read;
+ }
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+ }
+ /* FIXME: Check for overflow */
+ return total_read;
+}
+
+/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
+ and negociating with the server. |from| can be NULL. */
+/* FIXME: We don't check for errors nor report any! */
+static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
+ const char *from, int length)
+{
+ int bytes, htonl_bytes; /* 32-bit integers for htonl */
+ char *buffer = NULL;
+ char *cmd_buffer;
+ size_t cmd_size = 0;
+ CURLcode error;
+ enum protection_level prot_level = conn->data_prot;
+ bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
+
+ DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
+
+ if(iscmd) {
+ if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5))
+ prot_level = PROT_PRIVATE;
+ else
+ prot_level = conn->command_prot;
+ }
+ bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
+ (void**)&buffer);
+ if(!buffer || bytes <= 0)
+ return; /* error */
+
+ if(iscmd) {
+ error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes),
+ &cmd_buffer, &cmd_size);
+ if(error) {
+ free(buffer);
+ return; /* error */
+ }
+ if(cmd_size > 0) {
+ static const char *enc = "ENC ";
+ static const char *mic = "MIC ";
+ if(prot_level == PROT_PRIVATE)
+ socket_write(conn, fd, enc, 4);
+ else
+ socket_write(conn, fd, mic, 4);
+
+ socket_write(conn, fd, cmd_buffer, cmd_size);
+ socket_write(conn, fd, "\r\n", 2);
+ infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
+ cmd_buffer);
+ free(cmd_buffer);
+ }
+ }
+ else {
+ htonl_bytes = htonl(bytes);
+ socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes));
+ socket_write(conn, fd, buffer, curlx_sitouz(bytes));
+ }
+ free(buffer);
+}
+
+static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd,
+ const char *buffer, size_t length)
+{
+ ssize_t tx = 0, len = conn->buffer_size;
+
+ len -= conn->mech->overhead(conn->app_data, conn->data_prot,
+ curlx_sztosi(len));
+ if(len <= 0)
+ len = length;
+ while(length) {
+ if(length < (size_t)len)
+ len = length;
+
+ do_sec_send(conn, fd, buffer, curlx_sztosi(len));
+ length -= len;
+ buffer += len;
+ tx += len;
+ }
+ return tx;
+}
+
+/* Matches Curl_send signature */
+static ssize_t sec_send(struct connectdata *conn, int sockindex,
+ const void *buffer, size_t len, CURLcode *err)
+{
+ curl_socket_t fd = conn->sock[sockindex];
+ *err = CURLE_OK;
+ return sec_write(conn, fd, buffer, len);
+}
+
+CURL_STATIC int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
+ enum protection_level level)
+{
+ /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an
+ int */
+ int decoded_len;
+ char *buf;
+ int ret_code;
+ size_t decoded_sz = 0;
+ CURLcode error;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
+ if(error || decoded_sz == 0)
+ return -1;
+
+ if(decoded_sz > (size_t)INT_MAX) {
+ free(buf);
+ return -1;
+ }
+ decoded_len = curlx_uztosi(decoded_sz);
+
+ decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
+ level, conn);
+ if(decoded_len <= 0) {
+ free(buf);
+ return -1;
+ }
+
+ if(conn->data->set.verbose) {
+ buf[decoded_len] = '\n';
+ Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn);
+ }
+
+ buf[decoded_len] = '\0';
+ DEBUGASSERT(decoded_len > 3);
+ if(buf[3] == '-')
+ ret_code = 0;
+ else {
+ /* Check for error? */
+ (void)sscanf(buf, "%d", &ret_code);
+ }
+
+ if(buf[decoded_len - 1] == '\n')
+ buf[decoded_len - 1] = '\0';
+ /* FIXME: Is |buffer| length always greater than |decoded_len|? */
+ strcpy(buffer, buf);
+ free(buf);
+ return ret_code;
+}
+
+/* FIXME: The error code returned here is never checked. */
+static int sec_set_protection_level(struct connectdata *conn)
+{
+ int code;
+ char* pbsz;
+ static unsigned int buffer_size = 1 << 20; /* 1048576 */
+ enum protection_level level = conn->request_data_prot;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ if(!conn->sec_complete) {
+ infof(conn->data, "Trying to change the protection level after the"
+ "completion of the data exchange.\n");
+ return -1;
+ }
+
+ /* Bail out if we try to set up the same level */
+ if(conn->data_prot == level)
+ return 0;
+
+ if(level) {
+ code = ftp_send_command(conn, "PBSZ %u", buffer_size);
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(conn->data, "Failed to set the protection's buffer size.");
+ return -1;
+ }
+ conn->buffer_size = buffer_size;
+
+ pbsz = strstr(conn->data->state.buffer, "PBSZ=");
+ if(pbsz) {
+ /* FIXME: Checks for errors in sscanf? */
+ sscanf(pbsz, "PBSZ=%u", &buffer_size);
+ if(buffer_size < conn->buffer_size)
+ conn->buffer_size = buffer_size;
+ }
+ }
+
+ /* Now try to negiociate the protection level. */
+ code = ftp_send_command(conn, "PROT %c", level_to_char(level));
+
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(conn->data, "Failed to set the protection level.");
+ return -1;
+ }
+
+ conn->data_prot = level;
+ if(level == PROT_PRIVATE)
+ conn->command_prot = level;
+
+ return 0;
+}
+
+CURL_STATIC int
+Curl_sec_request_prot(struct connectdata *conn, const char *level)
+{
+ enum protection_level l = name_to_level(level);
+ if(l == PROT_NONE)
+ return -1;
+ DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
+ conn->request_data_prot = l;
+ return 0;
+}
+
+static CURLcode choose_mech(struct connectdata *conn)
+{
+ int ret;
+ struct SessionHandle *data = conn->data;
+ const struct Curl_sec_client_mech * const *mech;
+ void *tmp_allocation;
+ const char *mech_name;
+
+ for(mech = mechs; (*mech); ++mech) {
+ mech_name = (*mech)->name;
+ /* We have no mechanism with a NULL name but keep this check */
+ DEBUGASSERT(mech_name != NULL);
+ if(mech_name == NULL) {
+ infof(data, "Skipping mechanism with empty name (%p)\n", (void *)mech);
+ continue;
+ }
+ tmp_allocation = realloc(conn->app_data, (*mech)->size);
+ if(tmp_allocation == NULL) {
+ failf(data, "Failed realloc of size %u", (*mech)->size);
+ mech = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ conn->app_data = tmp_allocation;
+
+ if((*mech)->init) {
+ ret = (*mech)->init(conn->app_data);
+ if(ret != 0) {
+ infof(data, "Failed initialization for %s. Skipping it.\n", mech_name);
+ continue;
+ }
+ }
+
+ infof(data, "Trying mechanism %s...\n", mech_name);
+ ret = ftp_send_command(conn, "AUTH %s", mech_name);
+ if(ret < 0)
+ /* FIXME: This error is too generic but it is OK for now. */
+ return CURLE_COULDNT_CONNECT;
+
+ if(ret/100 != 3) {
+ switch(ret) {
+ case 504:
+ infof(data, "Mechanism %s is not supported by the server (server "
+ "returned ftp code: 504).\n", mech_name);
+ break;
+ case 534:
+ infof(data, "Mechanism %s was rejected by the server (server returned "
+ "ftp code: 534).\n", mech_name);
+ break;
+ default:
+ if(ret/100 == 5) {
+ infof(data, "server does not support the security extensions\n");
+ return CURLE_USE_SSL_FAILED;
+ }
+ break;
+ }
+ continue;
+ }
+
+ /* Authenticate */
+ ret = (*mech)->auth(conn->app_data, conn);
+
+ if(ret == AUTH_CONTINUE)
+ continue;
+ else if(ret != AUTH_OK) {
+ /* Mechanism has dumped the error to stderr, don't error here. */
+ return -1;
+ }
+ DEBUGASSERT(ret == AUTH_OK);
+
+ conn->mech = *mech;
+ conn->sec_complete = 1;
+ conn->recv[FIRSTSOCKET] = sec_recv;
+ conn->send[FIRSTSOCKET] = sec_send;
+ conn->recv[SECONDARYSOCKET] = sec_recv;
+ conn->send[SECONDARYSOCKET] = sec_send;
+ conn->command_prot = PROT_SAFE;
+ /* Set the requested protection level */
+ /* BLOCKING */
+ (void)sec_set_protection_level(conn);
+ break;
+ }
+
+ return *mech != NULL ? CURLE_OK : CURLE_FAILED_INIT;
+}
+
+CURL_STATIC CURLcode
+Curl_sec_login(struct connectdata *conn)
+{
+ return choose_mech(conn);
+}
+
+
+CURL_STATIC void
+Curl_sec_end(struct connectdata *conn)
+{
+ if(conn->mech != NULL && conn->mech->end)
+ conn->mech->end(conn->app_data);
+ free(conn->app_data);
+ conn->app_data = NULL;
+ if(conn->in_buffer.data) {
+ free(conn->in_buffer.data);
+ conn->in_buffer.data = NULL;
+ conn->in_buffer.size = 0;
+ conn->in_buffer.index = 0;
+ /* FIXME: Is this really needed? */
+ conn->in_buffer.eof_flag = 0;
+ }
+ conn->sec_complete = 0;
+ conn->data_prot = PROT_CLEAR;
+ conn->mech = NULL;
+}
+
+#endif /* HAVE_GSSAPI */
+
+#endif /* CURL_DISABLE_FTP */
diff --git a/libcurl/src/lib/select.c b/libcurl/src/lib/select.c
new file mode 100644
index 0000000..ce9db28
--- /dev/null
+++ b/libcurl/src/lib/select.c
@@ -0,0 +1,578 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
+#error "We can't compile without select() or poll() support."
+#endif
+
+#if defined(__BEOS__) && !defined(__HAIKU__)
+/* BeOS has FD_SET defined in socket.h */
+#include <socket.h>
+#endif
+
+#ifdef MSDOS
+#include <dos.h> /* delay() */
+#endif
+
+#ifdef __VXWORKS__
+#include <strings.h> /* bzero() in FD_SET */
+#endif
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "connect.h"
+#include "select.h"
+#include "warnless.h"
+
+/* Convenience local macros */
+
+#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
+
+CURL_STATIC_DEF(int, Curl_ack_eintr, 0);
+#define error_not_EINTR (Curl_ack_eintr || error != EINTR)
+
+/*
+ * Internal function used for waiting a specific amount of ms
+ * in Curl_socket_ready() and Curl_poll() when no file descriptor
+ * is provided to wait on, just being used to delay execution.
+ * WinSock select() and poll() timeout mechanisms need a valid
+ * socket descriptor in a not null file descriptor set to work.
+ * Waiting indefinitely with this function is not allowed, a
+ * zero or negative timeout value will return immediately.
+ * Timeout resolution, accuracy, as well as maximum supported
+ * value is system dependent, neither factor is a citical issue
+ * for the intended use of this function in the library.
+ *
+ * Return values:
+ * -1 = system call error, invalid timeout value, or interrupted
+ * 0 = specified timeout has elapsed
+ */
+CURL_STATIC int Curl_wait_ms(int timeout_ms)
+{
+#if !defined(MSDOS) && !defined(USE_WINSOCK) || defined(CURL_WINRT)
+#ifndef HAVE_POLL_FINE
+ struct timeval pending_tv;
+#endif
+ struct timeval initial_tv;
+ int pending_ms;
+ int error;
+#endif
+ int r = 0;
+
+ if(!timeout_ms)
+ return 0;
+ if(timeout_ms < 0) {
+ SET_SOCKERRNO(EINVAL);
+ return -1;
+ }
+#if defined(MSDOS)
+ delay(timeout_ms);
+#elif defined(USE_WINSOCK) && !defined(CURL_WINRT)
+ Sleep(timeout_ms);
+#else
+ pending_ms = timeout_ms;
+ initial_tv = curlx_tvnow();
+ do {
+#if defined(HAVE_POLL_FINE)
+ r = poll(NULL, 0, pending_ms);
+#else
+ pending_tv.tv_sec = pending_ms / 1000;
+ pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ r = select(0, NULL, NULL, NULL, &pending_tv);
+#endif /* HAVE_POLL_FINE */
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ } while(r == -1);
+#endif /* USE_WINSOCK */
+ if(r)
+ r = -1;
+ return r;
+}
+
+/*
+ * Wait for read or write events on a set of file descriptors. It uses poll()
+ * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
+ * otherwise select() is used. An error is returned if select() is being used
+ * and a file descriptor is too large for FD_SETSIZE.
+ *
+ * A negative timeout value makes this function wait indefinitely,
+ * unles no valid file descriptor is given, when this happens the
+ * negative timeout is ignored and the function times out immediately.
+ *
+ * Return values:
+ * -1 = system call error or fd >= FD_SETSIZE
+ * 0 = timeout
+ * [bitmask] = action as described below
+ *
+ * CURL_CSELECT_IN - first socket is readable
+ * CURL_CSELECT_IN2 - second socket is readable
+ * CURL_CSELECT_OUT - write socket is writable
+ * CURL_CSELECT_ERR - an error condition occurred
+ */
+int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
+ curl_socket_t readfd1,
+ curl_socket_t writefd, /* socket to write to */
+ long timeout_ms) /* milliseconds to wait */
+{
+#ifdef HAVE_POLL_FINE
+ struct pollfd pfd[3];
+ int num;
+#else
+ struct timeval pending_tv;
+ struct timeval *ptimeout;
+ fd_set fds_read;
+ fd_set fds_write;
+ fd_set fds_err;
+ curl_socket_t maxfd;
+#endif
+ struct timeval initial_tv = {0, 0};
+ int pending_ms = 0;
+ int error;
+ int r;
+ int ret;
+
+ if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
+ (writefd == CURL_SOCKET_BAD)) {
+ /* no sockets, just wait */
+ r = Curl_wait_ms((int)timeout_ms);
+ return r;
+ }
+
+ /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
+ time in this function does not need to be measured. This happens
+ when function is called with a zero timeout or a negative timeout
+ value indicating a blocking call should be performed. */
+
+ if(timeout_ms > 0) {
+ pending_ms = (int)timeout_ms;
+ initial_tv = curlx_tvnow();
+ }
+
+#ifdef HAVE_POLL_FINE
+
+ num = 0;
+ if(readfd0 != CURL_SOCKET_BAD) {
+ pfd[num].fd = readfd0;
+ pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
+ pfd[num].revents = 0;
+ num++;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ pfd[num].fd = readfd1;
+ pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
+ pfd[num].revents = 0;
+ num++;
+ }
+ if(writefd != CURL_SOCKET_BAD) {
+ pfd[num].fd = writefd;
+ pfd[num].events = POLLWRNORM|POLLOUT;
+ pfd[num].revents = 0;
+ num++;
+ }
+
+ do {
+ if(timeout_ms < 0)
+ pending_ms = -1;
+ else if(!timeout_ms)
+ pending_ms = 0;
+ r = poll(pfd, num, pending_ms);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = (int)(timeout_ms - elapsed_ms);
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ ret = 0;
+ num = 0;
+ if(readfd0 != CURL_SOCKET_BAD) {
+ if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
+ ret |= CURL_CSELECT_IN;
+ if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
+ ret |= CURL_CSELECT_ERR;
+ num++;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
+ ret |= CURL_CSELECT_IN2;
+ if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
+ ret |= CURL_CSELECT_ERR;
+ num++;
+ }
+ if(writefd != CURL_SOCKET_BAD) {
+ if(pfd[num].revents & (POLLWRNORM|POLLOUT))
+ ret |= CURL_CSELECT_OUT;
+ if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
+ ret |= CURL_CSELECT_ERR;
+ }
+
+ return ret;
+
+#else /* HAVE_POLL_FINE */
+
+ FD_ZERO(&fds_err);
+ maxfd = (curl_socket_t)-1;
+
+ FD_ZERO(&fds_read);
+ if(readfd0 != CURL_SOCKET_BAD) {
+ VERIFY_SOCK(readfd0);
+ FD_SET(readfd0, &fds_read);
+ FD_SET(readfd0, &fds_err);
+ maxfd = readfd0;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ VERIFY_SOCK(readfd1);
+ FD_SET(readfd1, &fds_read);
+ FD_SET(readfd1, &fds_err);
+ if(readfd1 > maxfd)
+ maxfd = readfd1;
+ }
+
+ FD_ZERO(&fds_write);
+ if(writefd != CURL_SOCKET_BAD) {
+ VERIFY_SOCK(writefd);
+ FD_SET(writefd, &fds_write);
+ FD_SET(writefd, &fds_err);
+ if(writefd > maxfd)
+ maxfd = writefd;
+ }
+
+ ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
+
+ do {
+ if(timeout_ms > 0) {
+ pending_tv.tv_sec = pending_ms / 1000;
+ pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ }
+ else if(!timeout_ms) {
+ pending_tv.tv_sec = 0;
+ pending_tv.tv_usec = 0;
+ }
+
+ /* WinSock select() must not be called with an fd_set that contains zero
+ fd flags, or it will return WSAEINVAL. But, it also can't be called
+ with no fd_sets at all! From the documentation:
+
+ Any two of the parameters, readfds, writefds, or exceptfds, can be
+ given as null. At least one must be non-null, and any non-null
+ descriptor set must contain at least one handle to a socket.
+
+ We know that we have at least one bit set in at least two fd_sets in
+ this case, but we may have no bits set in either fds_read or fd_write,
+ so check for that and handle it. Luckily, with WinSock, we can _also_
+ ask how many bits are set on an fd_set.
+
+ It is unclear why WinSock doesn't just handle this for us instead of
+ calling this an error.
+
+ Note also that WinSock ignores the first argument, so we don't worry
+ about the fact that maxfd is computed incorrectly with WinSock (since
+ curl_socket_t is unsigned in such cases and thus -1 is the largest
+ value).
+ */
+ r = select((int)maxfd + 1,
+#ifndef USE_WINSOCK
+ &fds_read,
+ &fds_write,
+#else
+ fds_read.fd_count ? &fds_read : NULL,
+ fds_write.fd_count ? &fds_write : NULL,
+#endif
+ &fds_err, ptimeout);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ ret = 0;
+ if(readfd0 != CURL_SOCKET_BAD) {
+ if(FD_ISSET(readfd0, &fds_read))
+ ret |= CURL_CSELECT_IN;
+ if(FD_ISSET(readfd0, &fds_err))
+ ret |= CURL_CSELECT_ERR;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ if(FD_ISSET(readfd1, &fds_read))
+ ret |= CURL_CSELECT_IN2;
+ if(FD_ISSET(readfd1, &fds_err))
+ ret |= CURL_CSELECT_ERR;
+ }
+ if(writefd != CURL_SOCKET_BAD) {
+ if(FD_ISSET(writefd, &fds_write))
+ ret |= CURL_CSELECT_OUT;
+ if(FD_ISSET(writefd, &fds_err))
+ ret |= CURL_CSELECT_ERR;
+ }
+
+ return ret;
+
+#endif /* HAVE_POLL_FINE */
+
+}
+
+/*
+ * This is a wrapper around poll(). If poll() does not exist, then
+ * select() is used instead. An error is returned if select() is
+ * being used and a file descriptor is too large for FD_SETSIZE.
+ * A negative timeout value makes this function wait indefinitely,
+ * unles no valid file descriptor is given, when this happens the
+ * negative timeout is ignored and the function times out immediately.
+ *
+ * Return values:
+ * -1 = system call error or fd >= FD_SETSIZE
+ * 0 = timeout
+ * N = number of structures with non zero revent fields
+ */
+CURL_STATIC int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
+{
+#ifndef HAVE_POLL_FINE
+ struct timeval pending_tv;
+ struct timeval *ptimeout;
+ fd_set fds_read;
+ fd_set fds_write;
+ fd_set fds_err;
+ curl_socket_t maxfd;
+#endif
+ struct timeval initial_tv = {0, 0};
+ bool fds_none = TRUE;
+ unsigned int i;
+ int pending_ms = 0;
+ int error;
+ int r;
+
+ if(ufds) {
+ for(i = 0; i < nfds; i++) {
+ if(ufds[i].fd != CURL_SOCKET_BAD) {
+ fds_none = FALSE;
+ break;
+ }
+ }
+ }
+ if(fds_none) {
+ r = Curl_wait_ms(timeout_ms);
+ return r;
+ }
+
+ /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
+ time in this function does not need to be measured. This happens
+ when function is called with a zero timeout or a negative timeout
+ value indicating a blocking call should be performed. */
+
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms;
+ initial_tv = curlx_tvnow();
+ }
+
+#ifdef HAVE_POLL_FINE
+
+ do {
+ if(timeout_ms < 0)
+ pending_ms = -1;
+ else if(!timeout_ms)
+ pending_ms = 0;
+ r = poll(ufds, nfds, pending_ms);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ for(i = 0; i < nfds; i++) {
+ if(ufds[i].fd == CURL_SOCKET_BAD)
+ continue;
+ if(ufds[i].revents & POLLHUP)
+ ufds[i].revents |= POLLIN;
+ if(ufds[i].revents & POLLERR)
+ ufds[i].revents |= (POLLIN|POLLOUT);
+ }
+
+#else /* HAVE_POLL_FINE */
+
+ FD_ZERO(&fds_read);
+ FD_ZERO(&fds_write);
+ FD_ZERO(&fds_err);
+ maxfd = (curl_socket_t)-1;
+
+ for(i = 0; i < nfds; i++) {
+ ufds[i].revents = 0;
+ if(ufds[i].fd == CURL_SOCKET_BAD)
+ continue;
+ VERIFY_SOCK(ufds[i].fd);
+ if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
+ POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
+ if(ufds[i].fd > maxfd)
+ maxfd = ufds[i].fd;
+ if(ufds[i].events & (POLLRDNORM|POLLIN))
+ FD_SET(ufds[i].fd, &fds_read);
+ if(ufds[i].events & (POLLWRNORM|POLLOUT))
+ FD_SET(ufds[i].fd, &fds_write);
+ if(ufds[i].events & (POLLRDBAND|POLLPRI))
+ FD_SET(ufds[i].fd, &fds_err);
+ }
+ }
+
+#ifdef USE_WINSOCK
+ /* WinSock select() can't handle zero events. See the comment about this in
+ Curl_check_socket(). */
+ if(fds_read.fd_count == 0 && fds_write.fd_count == 0
+ && fds_err.fd_count == 0) {
+ r = Curl_wait_ms(timeout_ms);
+ return r;
+ }
+#endif
+
+ ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
+
+ do {
+ if(timeout_ms > 0) {
+ pending_tv.tv_sec = pending_ms / 1000;
+ pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ }
+ else if(!timeout_ms) {
+ pending_tv.tv_sec = 0;
+ pending_tv.tv_usec = 0;
+ }
+ r = select((int)maxfd + 1,
+#ifndef USE_WINSOCK
+ &fds_read, &fds_write, &fds_err,
+#else
+ /* WinSock select() can't handle fd_sets with zero bits set, so
+ don't give it such arguments. See the comment about this in
+ Curl_check_socket().
+ */
+ fds_read.fd_count ? &fds_read : NULL,
+ fds_write.fd_count ? &fds_write : NULL,
+ fds_err.fd_count ? &fds_err : NULL,
+#endif
+ ptimeout);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ r = 0;
+ for(i = 0; i < nfds; i++) {
+ ufds[i].revents = 0;
+ if(ufds[i].fd == CURL_SOCKET_BAD)
+ continue;
+ if(FD_ISSET(ufds[i].fd, &fds_read))
+ ufds[i].revents |= POLLIN;
+ if(FD_ISSET(ufds[i].fd, &fds_write))
+ ufds[i].revents |= POLLOUT;
+ if(FD_ISSET(ufds[i].fd, &fds_err))
+ ufds[i].revents |= POLLPRI;
+ if(ufds[i].revents != 0)
+ r++;
+ }
+
+#endif /* HAVE_POLL_FINE */
+
+ return r;
+}
+
+#ifdef TPF
+/*
+ * This is a replacement for select() on the TPF platform.
+ * It is used whenever libcurl calls select().
+ * The call below to tpf_process_signals() is required because
+ * TPF's select calls are not signal interruptible.
+ *
+ * Return values are the same as select's.
+ */
+int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
+ fd_set* excepts, struct timeval* tv)
+{
+ int rc;
+
+ rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
+ tpf_process_signals();
+ return rc;
+}
+#endif /* TPF */
diff --git a/libcurl/src/lib/select.h b/libcurl/src/lib/select.h
new file mode 100644
index 0000000..903c14a
--- /dev/null
+++ b/libcurl/src/lib/select.h
@@ -0,0 +1,114 @@
+#ifndef HEADER_CURL_SELECT_H
+#define HEADER_CURL_SELECT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#elif defined(HAVE_POLL_H)
+#include <poll.h>
+#endif
+
+/*
+ * Definition of pollfd struct and constants for platforms lacking them.
+ */
+
+#if !defined(HAVE_STRUCT_POLLFD) && \
+ !defined(HAVE_SYS_POLL_H) && \
+ !defined(HAVE_POLL_H)
+
+#define POLLIN 0x01
+#define POLLPRI 0x02
+#define POLLOUT 0x04
+#define POLLERR 0x08
+#define POLLHUP 0x10
+#define POLLNVAL 0x20
+
+struct pollfd
+{
+ curl_socket_t fd;
+ short events;
+ short revents;
+};
+
+#endif
+
+#ifndef POLLRDNORM
+#define POLLRDNORM POLLIN
+#endif
+
+#ifndef POLLWRNORM
+#define POLLWRNORM POLLOUT
+#endif
+
+#ifndef POLLRDBAND
+#define POLLRDBAND POLLPRI
+#endif
+
+/* there are three CSELECT defines that are defined in the public header that
+ are exposed to users, but this *IN2 bit is only ever used internally and
+ therefore defined here */
+#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1)
+
+CURL_STATIC int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
+ curl_socket_t writefd,
+ long timeout_ms);
+
+/* provide the former API internally */
+#define Curl_socket_ready(x,y,z) \
+ Curl_socket_check(x, CURL_SOCKET_BAD, y, z)
+
+CURL_STATIC int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
+
+/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set,
+ * EINTR condition is honored and function might exit early without
+ * awaiting full timeout. Otherwise EINTR will be ignored and full
+ * timeout will elapse. */
+CURL_STATIC_DECL(int, Curl_ack_eintr, 0);
+
+CURL_STATIC int Curl_wait_ms(int timeout_ms);
+
+#ifdef TPF
+int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
+ fd_set* excepts, struct timeval* tv);
+#endif
+
+/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which
+ unfortunately makes it impossible for us to easily check if they're valid
+*/
+#if defined(USE_WINSOCK) || defined(TPF)
+#define VALID_SOCK(x) 1
+#define VERIFY_SOCK(x) Curl_nop_stmt
+#else
+#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
+#define VERIFY_SOCK(x) do { \
+ if(!VALID_SOCK(x)) { \
+ SET_SOCKERRNO(EINVAL); \
+ return -1; \
+ } \
+} WHILE_FALSE
+#endif
+
+#endif /* HEADER_CURL_SELECT_H */
+
diff --git a/libcurl/src/lib/sendf.c b/libcurl/src/lib/sendf.c
new file mode 100644
index 0000000..854606b
--- /dev/null
+++ b/libcurl/src/lib/sendf.c
@@ -0,0 +1,710 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "connect.h"
+#include "vtls/vtls.h"
+#include "ssh.h"
+#include "multiif.h"
+#include "non-ascii.h"
+#include "curl_printf.h"
+#include "strerror.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef CURL_DO_LINEEND_CONV
+/*
+ * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
+ * (\n), with special processing for CRLF sequences that are split between two
+ * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
+ * size of the data is returned.
+ */
+static size_t convert_lineends(struct SessionHandle *data,
+ char *startPtr, size_t size)
+{
+ char *inPtr, *outPtr;
+
+ /* sanity check */
+ if((startPtr == NULL) || (size < 1)) {
+ return size;
+ }
+
+ if(data->state.prev_block_had_trailing_cr) {
+ /* The previous block of incoming data
+ had a trailing CR, which was turned into a LF. */
+ if(*startPtr == '\n') {
+ /* This block of incoming data starts with the
+ previous block's LF so get rid of it */
+ memmove(startPtr, startPtr+1, size-1);
+ size--;
+ /* and it wasn't a bare CR but a CRLF conversion instead */
+ data->state.crlf_conversions++;
+ }
+ data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
+ }
+
+ /* find 1st CR, if any */
+ inPtr = outPtr = memchr(startPtr, '\r', size);
+ if(inPtr) {
+ /* at least one CR, now look for CRLF */
+ while(inPtr < (startPtr+size-1)) {
+ /* note that it's size-1, so we'll never look past the last byte */
+ if(memcmp(inPtr, "\r\n", 2) == 0) {
+ /* CRLF found, bump past the CR and copy the NL */
+ inPtr++;
+ *outPtr = *inPtr;
+ /* keep track of how many CRLFs we converted */
+ data->state.crlf_conversions++;
+ }
+ else {
+ if(*inPtr == '\r') {
+ /* lone CR, move LF instead */
+ *outPtr = '\n';
+ }
+ else {
+ /* not a CRLF nor a CR, just copy whatever it is */
+ *outPtr = *inPtr;
+ }
+ }
+ outPtr++;
+ inPtr++;
+ } /* end of while loop */
+
+ if(inPtr < startPtr+size) {
+ /* handle last byte */
+ if(*inPtr == '\r') {
+ /* deal with a CR at the end of the buffer */
+ *outPtr = '\n'; /* copy a NL instead */
+ /* note that a CRLF might be split across two blocks */
+ data->state.prev_block_had_trailing_cr = TRUE;
+ }
+ else {
+ /* copy last byte */
+ *outPtr = *inPtr;
+ }
+ outPtr++;
+ }
+ if(outPtr < startPtr+size)
+ /* tidy up by null terminating the now shorter data */
+ *outPtr = '\0';
+
+ return (outPtr - startPtr);
+ }
+ return size;
+}
+#endif /* CURL_DO_LINEEND_CONV */
+
+/* Curl_infof() is for info message along the way */
+
+CURL_STATIC void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
+{
+ if(data && data->set.verbose) {
+ va_list ap;
+ size_t len;
+ char print_buffer[2048 + 1];
+ va_start(ap, fmt);
+ vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+ va_end(ap);
+ len = strlen(print_buffer);
+ Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
+ }
+}
+
+/* Curl_failf() is for messages stating why we failed.
+ * The message SHALL NOT include any LF or CR.
+ */
+
+CURL_STATIC void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
+{
+ va_list ap;
+ size_t len;
+ va_start(ap, fmt);
+
+ vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
+
+ if(data->set.errorbuffer && !data->state.errorbuf) {
+ snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
+ data->state.errorbuf = TRUE; /* wrote error string */
+ }
+ if(data->set.verbose) {
+ len = strlen(data->state.buffer);
+ if(len < BUFSIZE - 1) {
+ data->state.buffer[len] = '\n';
+ data->state.buffer[++len] = '\0';
+ }
+ Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
+ }
+
+ va_end(ap);
+}
+
+/* Curl_sendf() sends formated data to the server */
+CURL_STATIC CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
+ const char *fmt, ...)
+{
+ struct SessionHandle *data = conn->data;
+ ssize_t bytes_written;
+ size_t write_len;
+ CURLcode result = CURLE_OK;
+ char *s;
+ char *sptr;
+ va_list ap;
+ va_start(ap, fmt);
+ s = vaprintf(fmt, ap); /* returns an allocated string */
+ va_end(ap);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY; /* failure */
+
+ bytes_written=0;
+ write_len = strlen(s);
+ sptr = s;
+
+ for(;;) {
+ /* Write the buffer to the socket */
+ result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
+
+ if(result)
+ break;
+
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
+
+ if((size_t)bytes_written != write_len) {
+ /* if not all was written at once, we must advance the pointer, decrease
+ the size left and try again! */
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ free(s); /* free the output string */
+
+ return result;
+}
+
+/*
+ * Curl_write() is an internal write function that sends data to the
+ * server. Works with plain sockets, SCP, SSL or kerberos.
+ *
+ * If the write would block (CURLE_AGAIN), we return CURLE_OK and
+ * (*written == 0). Otherwise we return regular CURLcode value.
+ */
+CURL_STATIC CURLcode Curl_write(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem,
+ size_t len,
+ ssize_t *written)
+{
+ ssize_t bytes_written;
+ CURLcode result = CURLE_OK;
+ int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+
+ bytes_written = conn->send[num](conn, num, mem, len, &result);
+
+ *written = bytes_written;
+ if(bytes_written >= 0)
+ /* we completely ignore the curlcode value when subzero is not returned */
+ return CURLE_OK;
+
+ /* handle CURLE_AGAIN or a send failure */
+ switch(result) {
+ case CURLE_AGAIN:
+ *written = 0;
+ return CURLE_OK;
+
+ case CURLE_OK:
+ /* general send failure */
+ return CURLE_SEND_ERROR;
+
+ default:
+ /* we got a specific curlcode, forward it */
+ return result;
+ }
+}
+
+CURL_STATIC ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ const void *mem, size_t len, CURLcode *code)
+{
+ curl_socket_t sockfd = conn->sock[num];
+ ssize_t bytes_written = swrite(sockfd, mem, len);
+
+ *code = CURLE_OK;
+ if(-1 == bytes_written) {
+ int err = SOCKERRNO;
+
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == err)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
+ due to its inability to send off data without blocking. We therefor
+ treat both error codes the same here */
+ (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
+#endif
+ ) {
+ /* this is just a case of EWOULDBLOCK */
+ bytes_written=0;
+ *code = CURLE_AGAIN;
+ }
+ else {
+ failf(conn->data, "Send failure: %s",
+ Curl_strerror(conn, err));
+ conn->data->state.os_errno = err;
+ *code = CURLE_SEND_ERROR;
+ }
+ }
+ return bytes_written;
+}
+
+/*
+ * Curl_write_plain() is an internal write function that sends data to the
+ * server using plain sockets only. Otherwise meant to have the exact same
+ * proto as Curl_write()
+ */
+CURL_STATIC CURLcode Curl_write_plain(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem,
+ size_t len,
+ ssize_t *written)
+{
+ ssize_t bytes_written;
+ CURLcode result;
+ int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+
+ bytes_written = Curl_send_plain(conn, num, mem, len, &result);
+
+ *written = bytes_written;
+
+ return result;
+}
+
+CURL_STATIC ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ size_t len, CURLcode *code)
+{
+ curl_socket_t sockfd = conn->sock[num];
+ ssize_t nread = sread(sockfd, buf, len);
+
+ *code = CURLE_OK;
+ if(-1 == nread) {
+ int err = SOCKERRNO;
+
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == err)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
+ due to its inability to send off data without blocking. We therefor
+ treat both error codes the same here */
+ (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
+#endif
+ ) {
+ /* this is just a case of EWOULDBLOCK */
+ *code = CURLE_AGAIN;
+ }
+ else {
+ failf(conn->data, "Recv failure: %s",
+ Curl_strerror(conn, err));
+ conn->data->state.os_errno = err;
+ *code = CURLE_RECV_ERROR;
+ }
+ }
+ return nread;
+}
+
+static CURLcode pausewrite(struct SessionHandle *data,
+ int type, /* what type of data */
+ const char *ptr,
+ size_t len)
+{
+ /* signalled to pause sending on this connection, but since we have data
+ we want to send we need to dup it to save a copy for when the sending
+ is again enabled */
+ struct SingleRequest *k = &data->req;
+ char *dupl = malloc(len);
+ if(!dupl)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(dupl, ptr, len);
+
+ /* store this information in the state struct for later use */
+ data->state.tempwrite = dupl;
+ data->state.tempwritesize = len;
+ data->state.tempwritetype = type;
+
+ /* mark the connection as RECV paused */
+ k->keepon |= KEEP_RECV_PAUSE;
+
+ DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
+ len, type));
+
+ return CURLE_OK;
+}
+
+
+/* Curl_client_chop_write() writes chunks of data not larger than
+ * CURL_MAX_WRITE_SIZE via client write callback(s) and
+ * takes care of pause requests from the callbacks.
+ */
+CURL_STATIC CURLcode Curl_client_chop_write(struct connectdata *conn,
+ int type,
+ char * ptr,
+ size_t len)
+{
+ struct SessionHandle *data = conn->data;
+ curl_write_callback writeheader = NULL;
+ curl_write_callback writebody = NULL;
+
+ if (!len)
+ return CURLE_OK;
+
+ /* If reading is actually paused, we're forced to append this chunk of data
+ to the already held data, but only if it is the same type as otherwise it
+ can't work and it'll return error instead. */
+ if(data->req.keepon & KEEP_RECV_PAUSE) {
+ size_t newlen;
+ char *newptr;
+ if(type != data->state.tempwritetype)
+ /* major internal confusion */
+ return CURLE_RECV_ERROR;
+
+ DEBUGASSERT(data->state.tempwrite);
+
+ /* figure out the new size of the data to save */
+ newlen = len + data->state.tempwritesize;
+ /* allocate the new memory area */
+ newptr = realloc(data->state.tempwrite, newlen);
+ if(!newptr)
+ return CURLE_OUT_OF_MEMORY;
+ /* copy the new data to the end of the new area */
+ memcpy(newptr + data->state.tempwritesize, ptr, len);
+ /* update the pointer and the size */
+ data->state.tempwrite = newptr;
+ data->state.tempwritesize = newlen;
+ return CURLE_OK;
+ }
+
+ /* Determine the callback(s) to use. */
+ if(type & CLIENTWRITE_BODY)
+ writebody = data->set.fwrite_func;
+ if((type & CLIENTWRITE_HEADER) &&
+ (data->set.fwrite_header || data->set.writeheader)) {
+ /*
+ * Write headers to the same callback or to the especially setup
+ * header callback function (added after version 7.7.1).
+ */
+ writeheader =
+ data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
+ }
+
+ /* Chop data, write chunks. */
+ while(len) {
+ size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
+
+ if(writebody) {
+ size_t wrote = writebody(ptr, 1, chunklen, data->set.out);
+
+ if(CURL_WRITEFUNC_PAUSE == wrote) {
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ /* Protocols that work without network cannot be paused. This is
+ actually only FILE:// just now, and it can't pause since the
+ transfer isn't done using the "normal" procedure. */
+ failf(data, "Write callback asked for PAUSE when not supported!");
+ return CURLE_WRITE_ERROR;
+ }
+ else
+ return pausewrite(data, type, ptr, len);
+ }
+ else if(wrote != chunklen) {
+ failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
+ return CURLE_WRITE_ERROR;
+ }
+ }
+
+ if(writeheader) {
+ size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
+
+ if(CURL_WRITEFUNC_PAUSE == wrote)
+ /* here we pass in the HEADER bit only since if this was body as well
+ then it was passed already and clearly that didn't trigger the
+ pause, so this is saved for later with the HEADER bit only */
+ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
+
+ if(wrote != chunklen) {
+ failf (data, "Failed writing header");
+ return CURLE_WRITE_ERROR;
+ }
+ }
+
+ ptr += chunklen;
+ len -= chunklen;
+ }
+
+ return CURLE_OK;
+}
+
+
+/* Curl_client_write() sends data to the write callback(s)
+
+ The bit pattern defines to what "streams" to write to. Body and/or header.
+ The defines are in sendf.h of course.
+
+ If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
+ local character encoding. This is a problem and should be changed in
+ the future to leave the original data alone.
+ */
+CURL_STATIC CURLcode Curl_client_write(struct connectdata *conn,
+ int type,
+ char *ptr,
+ size_t len)
+{
+ struct SessionHandle *data = conn->data;
+
+ if(0 == len)
+ len = strlen(ptr);
+
+ /* FTP data may need conversion. */
+ if((type & CLIENTWRITE_BODY) &&
+ (conn->handler->protocol & PROTO_FAMILY_FTP) &&
+ conn->proto.ftpc.transfertype == 'A') {
+ /* convert from the network encoding */
+ CURLcode result = Curl_convert_from_network(data, ptr, len);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+#ifdef CURL_DO_LINEEND_CONV
+ /* convert end-of-line markers */
+ len = convert_lineends(data, ptr, len);
+#endif /* CURL_DO_LINEEND_CONV */
+ }
+
+ return Curl_client_chop_write(conn, type, ptr, len);
+}
+
+CURL_STATIC CURLcode Curl_read_plain(curl_socket_t sockfd,
+ char *buf,
+ size_t bytesfromsocket,
+ ssize_t *n)
+{
+ ssize_t nread = sread(sockfd, buf, bytesfromsocket);
+
+ if(-1 == nread) {
+ int err = SOCKERRNO;
+#ifdef USE_WINSOCK
+ if(WSAEWOULDBLOCK == err)
+#else
+ if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
+#endif
+ return CURLE_AGAIN;
+ else
+ return CURLE_RECV_ERROR;
+ }
+
+ /* we only return number of bytes read when we return OK */
+ *n = nread;
+ return CURLE_OK;
+}
+
+/*
+ * Internal read-from-socket function. This is meant to deal with plain
+ * sockets, SSL sockets and kerberos sockets.
+ *
+ * Returns a regular CURLcode value.
+ */
+CURLcode Curl_read(struct connectdata *conn, /* connection data */
+ curl_socket_t sockfd, /* read from this socket */
+ char *buf, /* store read data here */
+ size_t sizerequested, /* max amount to read */
+ ssize_t *n) /* amount bytes read */
+{
+ CURLcode result = CURLE_RECV_ERROR;
+ ssize_t nread = 0;
+ size_t bytesfromsocket = 0;
+ char *buffertofill = NULL;
+ bool pipelining = Curl_multi_pipeline_enabled(conn->data->multi);
+
+ /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
+ If it is the second socket, we set num to 1. Otherwise to 0. This lets
+ us use the correct ssl handle. */
+ int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+
+ *n=0; /* reset amount to zero */
+
+ /* If session can pipeline, check connection buffer */
+ if(pipelining) {
+ size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
+ sizerequested);
+
+ /* Copy from our master buffer first if we have some unread data there*/
+ if(bytestocopy > 0) {
+ memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
+ conn->read_pos += bytestocopy;
+ conn->bits.stream_was_rewound = FALSE;
+
+ *n = (ssize_t)bytestocopy;
+ return CURLE_OK;
+ }
+ /* If we come here, it means that there is no data to read from the buffer,
+ * so we read from the socket */
+ bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
+ buffertofill = conn->master_buffer;
+ }
+ else {
+ bytesfromsocket = CURLMIN((long)sizerequested,
+ conn->data->set.buffer_size ?
+ conn->data->set.buffer_size : BUFSIZE);
+ buffertofill = buf;
+ }
+
+ nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
+ if(nread < 0)
+ return result;
+
+ if(pipelining) {
+ memcpy(buf, conn->master_buffer, nread);
+ conn->buf_len = nread;
+ conn->read_pos = nread;
+ }
+
+ *n += nread;
+
+ return CURLE_OK;
+}
+
+/* return 0 on success */
+static int showit(struct SessionHandle *data, curl_infotype type,
+ char *ptr, size_t size)
+{
+ static const char s_infotype[CURLINFO_END][3] = {
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
+
+#ifdef CURL_DOES_CONVERSIONS
+ char buf[BUFSIZE+1];
+ size_t conv_size = 0;
+
+ switch(type) {
+ case CURLINFO_HEADER_OUT:
+ /* assume output headers are ASCII */
+ /* copy the data into my buffer so the original is unchanged */
+ if(size > BUFSIZE) {
+ size = BUFSIZE; /* truncate if necessary */
+ buf[BUFSIZE] = '\0';
+ }
+ conv_size = size;
+ memcpy(buf, ptr, size);
+ /* Special processing is needed for this block if it
+ * contains both headers and data (separated by CRLFCRLF).
+ * We want to convert just the headers, leaving the data as-is.
+ */
+ if(size > 4) {
+ size_t i;
+ for(i = 0; i < size-4; i++) {
+ if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
+ /* convert everything through this CRLFCRLF but no further */
+ conv_size = i + 4;
+ break;
+ }
+ }
+ }
+
+ Curl_convert_from_network(data, buf, conv_size);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* we might as well continue even if it fails... */
+ ptr = buf; /* switch pointer to use my buffer instead */
+ break;
+ default:
+ /* leave everything else as-is */
+ break;
+ }
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if(data->set.fdebug)
+ return (*data->set.fdebug)(data, type, ptr, size,
+ data->set.debugdata);
+
+ switch(type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
+ fwrite(s_infotype[type], 2, 1, data->set.err);
+ fwrite(ptr, size, 1, data->set.err);
+#ifdef CURL_DOES_CONVERSIONS
+ if(size != conv_size) {
+ /* we had untranslated data so we need an explicit newline */
+ fwrite("\n", 1, 1, data->set.err);
+ }
+#endif
+ break;
+ default: /* nada */
+ break;
+ }
+ return 0;
+}
+
+CURL_STATIC int Curl_debug(struct SessionHandle *data, curl_infotype type,
+ char *ptr, size_t size,
+ struct connectdata *conn)
+{
+ int rc;
+ if(data->set.printhost && conn && conn->host.dispname) {
+ char buffer[160];
+ const char *t=NULL;
+ const char *w="Data";
+ switch (type) {
+ case CURLINFO_HEADER_IN:
+ w = "Header";
+ /* FALLTHROUGH */
+ case CURLINFO_DATA_IN:
+ t = "from";
+ break;
+ case CURLINFO_HEADER_OUT:
+ w = "Header";
+ /* FALLTHROUGH */
+ case CURLINFO_DATA_OUT:
+ t = "to";
+ break;
+ default:
+ break;
+ }
+
+ if(t) {
+ snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
+ conn->host.dispname);
+ rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
+ if(rc)
+ return rc;
+ }
+ }
+ rc = showit(data, type, ptr, size);
+ return rc;
+}
diff --git a/libcurl/src/lib/sendf.h b/libcurl/src/lib/sendf.h
new file mode 100644
index 0000000..f5f03c2
--- /dev/null
+++ b/libcurl/src/lib/sendf.h
@@ -0,0 +1,93 @@
+#ifndef HEADER_CURL_SENDF_H
+#define HEADER_CURL_SENDF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+CURL_STATIC CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *,
+ const char *fmt, ...);
+CURL_STATIC void Curl_infof(struct SessionHandle *, const char *fmt, ...);
+CURL_STATIC void Curl_failf(struct SessionHandle *, const char *fmt, ...);
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+
+#if defined(HAVE_VARIADIC_MACROS_C99)
+#define infof(...) Curl_nop_stmt
+#elif defined(HAVE_VARIADIC_MACROS_GCC)
+#define infof(x...) Curl_nop_stmt
+#else
+#define infof (void)
+#endif
+
+#else /* CURL_DISABLE_VERBOSE_STRINGS */
+
+#define infof Curl_infof
+
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+
+#define failf Curl_failf
+
+#define CLIENTWRITE_BODY (1<<0)
+#define CLIENTWRITE_HEADER (1<<1)
+#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
+
+CURL_STATIC CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr,
+ size_t len) WARN_UNUSED_RESULT;
+
+CURL_STATIC CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
+ size_t len) WARN_UNUSED_RESULT;
+
+/* internal read-function, does plain socket only */
+CURL_STATIC CURLcode Curl_read_plain(curl_socket_t sockfd,
+ char *buf,
+ size_t bytesfromsocket,
+ ssize_t *n);
+
+CURL_STATIC ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ size_t len, CURLcode *code);
+CURL_STATIC ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ const void *mem, size_t len, CURLcode *code);
+
+/* internal read-function, does plain socket, SSL and krb4 */
+CURL_STATIC CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd,
+ char *buf, size_t buffersize,
+ ssize_t *n);
+/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
+CURL_STATIC CURLcode Curl_write(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem, size_t len,
+ ssize_t *written);
+
+/* internal write-function, does plain sockets ONLY */
+CURL_STATIC CURLcode Curl_write_plain(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem, size_t len,
+ ssize_t *written);
+
+/* the function used to output verbose information */
+CURL_STATIC int Curl_debug(struct SessionHandle *handle, curl_infotype type,
+ char *data, size_t size,
+ struct connectdata *conn);
+
+
+#endif /* HEADER_CURL_SENDF_H */
diff --git a/libcurl/src/lib/setup-os400.h b/libcurl/src/lib/setup-os400.h
new file mode 100644
index 0000000..6d4c507
--- /dev/null
+++ b/libcurl/src/lib/setup-os400.h
@@ -0,0 +1,223 @@
+#ifndef HEADER_CURL_SETUP_OS400_H
+#define HEADER_CURL_SETUP_OS400_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/* OS/400 netdb.h does not define NI_MAXHOST. */
+#define NI_MAXHOST 1025
+
+/* OS/400 netdb.h does not define NI_MAXSERV. */
+#define NI_MAXSERV 32
+
+/* No OS/400 header file defines u_int32_t. */
+typedef unsigned long u_int32_t;
+
+
+/* System API wrapper prototypes & definitions to support ASCII parameters. */
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <gskssl.h>
+#include <qsoasync.h>
+#include <gssapi.h>
+
+extern CURL_STATIC int Curl_getaddrinfo_a(const char * nodename,
+ const char * servname,
+ const struct addrinfo * hints,
+ struct addrinfo * * res);
+#define getaddrinfo Curl_getaddrinfo_a
+
+
+extern CURL_STATIC int Curl_getnameinfo_a(const struct sockaddr * sa,
+ curl_socklen_t salen,
+ char * nodename, curl_socklen_t nodenamelen,
+ char * servname, curl_socklen_t servnamelen,
+ int flags);
+#define getnameinfo Curl_getnameinfo_a
+
+
+/* GSKit wrappers. */
+
+extern CURL_STATIC int Curl_gsk_environment_open(gsk_handle * my_env_handle);
+#define gsk_environment_open Curl_gsk_environment_open
+
+extern CURL_STATIC int Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
+ gsk_handle * my_session_handle);
+#define gsk_secure_soc_open Curl_gsk_secure_soc_open
+
+extern CURL_STATIC int Curl_gsk_environment_close(gsk_handle * my_env_handle);
+#define gsk_environment_close Curl_gsk_environment_close
+
+extern CURL_STATIC int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle);
+#define gsk_secure_soc_close Curl_gsk_secure_soc_close
+
+extern CURL_STATIC int Curl_gsk_environment_init(gsk_handle my_env_handle);
+#define gsk_environment_init Curl_gsk_environment_init
+
+extern CURL_STATIC int Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
+#define gsk_secure_soc_init Curl_gsk_secure_soc_init
+
+extern CURL_STATIC int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
+ GSK_BUF_ID bufID,
+ const char * buffer,
+ int bufSize);
+#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a
+
+extern CURL_STATIC int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle,
+ GSK_ENUM_ID enumID,
+ GSK_ENUM_VALUE enumValue);
+#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum
+
+extern CURL_STATIC int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
+ GSK_NUM_ID numID,
+ int numValue);
+#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value
+
+extern CURL_STATIC int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
+ GSK_CALLBACK_ID callBackID,
+ void * callBackAreaPtr);
+#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback
+
+extern CURL_STATIC int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
+ GSK_BUF_ID bufID,
+ const char * * buffer,
+ int * bufSize);
+#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a
+
+extern CURL_STATIC int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
+ GSK_ENUM_ID enumID,
+ GSK_ENUM_VALUE * enumValue);
+#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum
+
+extern CURL_STATIC int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
+ GSK_NUM_ID numID,
+ int * numValue);
+#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
+
+extern CURL_STATIC int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
+ GSK_CERT_ID certID,
+ const gsk_cert_data_elem * * certDataElem,
+ int * certDataElementCount);
+#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info
+
+extern CURL_STATIC int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
+ GSK_MISC_ID miscID);
+#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc
+
+extern CURL_STATIC int Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
+ char * readBuffer,
+ int readBufSize, int * amtRead);
+#define gsk_secure_soc_read Curl_gsk_secure_soc_read
+
+extern CURL_STATIC int Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
+ char * writeBuffer,
+ int writeBufSize, int * amtWritten);
+#define gsk_secure_soc_write Curl_gsk_secure_soc_write
+
+extern CURL_STATIC const char * Curl_gsk_strerror_a(int gsk_return_value);
+#define gsk_strerror Curl_gsk_strerror_a
+
+extern CURL_STATIC int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
+ int IOCompletionPort,
+ Qso_OverlappedIO_t * communicationsArea);
+#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit
+
+
+/* GSSAPI wrappers. */
+
+extern CURL_STATIC OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status,
+ gss_buffer_t in_name,
+ gss_OID in_name_type,
+ gss_name_t * out_name);
+#define gss_import_name Curl_gss_import_name_a
+
+
+extern CURL_STATIC OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status,
+ OM_uint32 status_value,
+ int status_type, gss_OID mech_type,
+ gss_msg_ctx_t * message_context,
+ gss_buffer_t status_string);
+#define gss_display_status Curl_gss_display_status_a
+
+
+extern CURL_STATIC OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
+ gss_cred_id_t cred_handle,
+ gss_ctx_id_t * context_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ gss_flags_t req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t
+ input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID * actual_mech_type,
+ gss_buffer_t output_token,
+ gss_flags_t * ret_flags,
+ OM_uint32 * time_rec);
+#define gss_init_sec_context Curl_gss_init_sec_context_a
+
+
+extern CURL_STATIC OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
+ gss_ctx_id_t * context_handle,
+ gss_buffer_t output_token);
+#define gss_delete_sec_context Curl_gss_delete_sec_context_a
+
+
+/* LDAP wrappers. */
+
+#define BerValue struct berval
+
+#define ldap_url_parse ldap_url_parse_utf8
+#define ldap_init Curl_ldap_init_a
+#define ldap_simple_bind_s Curl_ldap_simple_bind_s_a
+#define ldap_search_s Curl_ldap_search_s_a
+#define ldap_get_values_len Curl_ldap_get_values_len_a
+#define ldap_err2string Curl_ldap_err2string_a
+#define ldap_get_dn Curl_ldap_get_dn_a
+#define ldap_first_attribute Curl_ldap_first_attribute_a
+#define ldap_next_attribute Curl_ldap_next_attribute_a
+
+/* Some socket functions must be wrapped to process textual addresses
+ like AF_UNIX. */
+
+extern CURL_STATIC int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen);
+extern CURL_STATIC int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen);
+extern CURL_STATIC int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
+ struct sockaddr * dstaddr, int addrlen);
+extern CURL_STATIC int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
+ struct sockaddr * fromaddr, int * addrlen);
+
+#define connect Curl_os400_connect
+#define bind Curl_os400_bind
+#define sendto Curl_os400_sendto
+#define recvfrom Curl_os400_recvfrom
+
+#ifdef HAVE_LIBZ
+#define zlibVersion Curl_os400_zlibVersion
+#define inflateInit_ Curl_os400_inflateInit_
+#define inflateInit2_ Curl_os400_inflateInit2_
+#define inflate Curl_os400_inflate
+#define inflateEnd Curl_os400_inflateEnd
+#endif
+
+#endif /* HEADER_CURL_SETUP_OS400_H */
diff --git a/libcurl/src/lib/setup-vms.h b/libcurl/src/lib/setup-vms.h
new file mode 100644
index 0000000..f6179a4
--- /dev/null
+++ b/libcurl/src/lib/setup-vms.h
@@ -0,0 +1,430 @@
+#ifndef HEADER_CURL_SETUP_VMS_H
+#define HEADER_CURL_SETUP_VMS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* */
+/* JEM, 12/30/12, VMS now generates config.h, so only define wrappers for */
+/* getenv(), getpwuid() and provide is_vms_shell() */
+/* Also need upper case symbols for system services, and */
+/* OpenSSL, and some Kerberos image */
+
+#ifdef __DECC
+#pragma message save
+#pragma message disable dollarid
+#endif
+
+/* Hide the stuff we are overriding */
+#define getenv decc_getenv
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE != 64
+# define getpwuid decc_getpwuid
+# endif
+#endif
+#include <stdlib.h>
+ char * decc$getenv(const char * __name);
+#include <pwd.h>
+
+#include <string.h>
+#include <unixlib.h>
+
+#undef getenv
+#undef getpwuid
+#define getenv vms_getenv
+#define getpwuid vms_getpwuid
+
+/* VAX needs these in upper case when compiling exact case */
+#define sys$assign SYS$ASSIGN
+#define sys$dassgn SYS$DASSGN
+#define sys$qiow SYS$QIOW
+
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE
+# pragma __pointer_size __save
+# endif
+#endif
+
+#if __USE_LONG_GID_T
+# define decc_getpwuid DECC$__LONG_GID_GETPWUID
+#else
+# if __INITIAL_POINTER_SIZE
+# define decc_getpwuid decc$__32_getpwuid
+# else
+# define decc_getpwuid decc$getpwuid
+# endif
+#endif
+
+ struct passwd * decc_getpwuid(uid_t uid);
+
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE == 32
+/* Translate the path, but only if the path is a VMS file specification */
+/* The translation is usually only needed for older versions of VMS */
+static char * vms_translate_path(const char * path) {
+char * unix_path;
+char * test_str;
+
+ /* See if the result is in VMS format, if not, we are done */
+ /* Assume that this is a PATH, not just some data */
+ test_str = strpbrk(path, ":[<^");
+ if(test_str == NULL) {
+ return (char *)path;
+ }
+
+ unix_path = decc$translate_vms(path);
+
+ if((int)unix_path <= 0) {
+ /* We can not translate it, so return the original string */
+ return (char *)path;
+ }
+}
+# else
+ /* VMS translate path is actually not needed on the current 64 bit */
+ /* VMS platforms, so instead of figuring out the pointer settings */
+ /* Change it to a noop */
+# define vms_translate_path(__path) __path
+# endif
+#endif
+
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE
+# pragma __pointer_size __restore
+# endif
+#endif
+
+static char * vms_getenv(const char * envvar) {
+
+char * result;
+char * vms_path;
+
+ /* first use the DECC getenv() function */
+ result = decc$getenv(envvar);
+ if(result == NULL) {
+ return result;
+ }
+
+ vms_path = result;
+ result = vms_translate_path(vms_path);
+
+ /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
+ /* may do a malloc(2048) for each call to getenv(), so you will need */
+ /* to add a free(vms_path) */
+ /* Do not do a free() for DEC C RTL builds, which should be used for */
+ /* VMS 5.5-2 and later, even if using GCC */
+
+ return result;
+}
+
+
+static struct passwd vms_passwd_cache;
+
+static struct passwd * vms_getpwuid(uid_t uid) {
+
+struct passwd * my_passwd;
+
+/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE
+__char_ptr32 unix_path;
+# else
+char * unix_path;
+# endif
+#else
+char * unix_path;
+#endif
+
+ my_passwd = decc_getpwuid(uid);
+ if(my_passwd == NULL) {
+ return my_passwd;
+ }
+
+ unix_path = vms_translate_path(my_passwd->pw_dir);
+
+ if((long)unix_path <= 0) {
+ /* We can not translate it, so return the original string */
+ return my_passwd;
+ }
+
+ /* If no changes needed just return it */
+ if(unix_path == my_passwd->pw_dir) {
+ return my_passwd;
+ }
+
+ /* Need to copy the structure returned */
+ /* Since curl is only using pw_dir, no need to fix up *
+ /* the pw_shell when running under Bash */
+ vms_passwd_cache.pw_name = my_passwd->pw_name;
+ vms_passwd_cache.pw_uid = my_passwd->pw_uid;
+ vms_passwd_cache.pw_gid = my_passwd->pw_uid;
+ vms_passwd_cache.pw_dir = unix_path;
+ vms_passwd_cache.pw_shell = my_passwd->pw_shell;
+
+ return &vms_passwd_cache;
+}
+
+#ifdef __DECC
+#pragma message restore
+#endif
+
+/* Bug - VMS OpenSSL and Kerberos universal symbols are in uppercase only */
+/* VMS libraries should have universal symbols in exact and uppercase */
+
+#define ASN1_INTEGER_get ASN1_INTEGER_GET
+#define ASN1_STRING_data ASN1_STRING_DATA
+#define ASN1_STRING_length ASN1_STRING_LENGTH
+#define ASN1_STRING_print ASN1_STRING_PRINT
+#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8
+#define ASN1_STRING_type ASN1_STRING_TYPE
+#define BIO_ctrl BIO_CTRL
+#define BIO_free BIO_FREE
+#define BIO_new BIO_NEW
+#define BIO_s_mem BIO_S_MEM
+#define BN_bn2bin BN_BN2BIN
+#define BN_num_bits BN_NUM_BITS
+#define CRYPTO_cleanup_all_ex_data CRYPTO_CLEANUP_ALL_EX_DATA
+#define CRYPTO_free CRYPTO_FREE
+#define CRYPTO_malloc CRYPTO_MALLOC
+#define CONF_modules_load_file CONF_MODULES_LOAD_FILE
+#ifdef __VAX
+# ifdef VMS_OLD_SSL
+ /* Ancient OpenSSL on VAX/VMS missing this constant */
+# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10
+# undef CONF_modules_load_file
+ static int CONF_modules_load_file(const char *filename,
+ const char *appname,
+ unsigned long flags) {
+ return 1;
+ }
+# endif
+#endif
+#define DES_ecb_encrypt DES_ECB_ENCRYPT
+#define DES_set_key DES_SET_KEY
+#define DES_set_odd_parity DES_SET_ODD_PARITY
+#define ENGINE_ctrl ENGINE_CTRL
+#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD
+#define ENGINE_finish ENGINE_FINISH
+#define ENGINE_free ENGINE_FREE
+#define ENGINE_get_first ENGINE_GET_FIRST
+#define ENGINE_get_id ENGINE_GET_ID
+#define ENGINE_get_next ENGINE_GET_NEXT
+#define ENGINE_init ENGINE_INIT
+#define ENGINE_load_builtin_engines ENGINE_LOAD_BUILTIN_ENGINES
+#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY
+#define ENGINE_set_default ENGINE_SET_DEFAULT
+#define ERR_clear_error ERR_CLEAR_ERROR
+#define ERR_error_string ERR_ERROR_STRING
+#define ERR_error_string_n ERR_ERROR_STRING_N
+#define ERR_free_strings ERR_FREE_STRINGS
+#define ERR_get_error ERR_GET_ERROR
+#define ERR_peek_error ERR_PEEK_ERROR
+#define ERR_remove_state ERR_REMOVE_STATE
+#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS
+#define EVP_PKEY_free EVP_PKEY_FREE
+#define EVP_cleanup EVP_CLEANUP
+#define GENERAL_NAMES_free GENERAL_NAMES_FREE
+#define i2d_X509_PUBKEY I2D_X509_PUBKEY
+#define MD4_Final MD4_FINAL
+#define MD4_Init MD4_INIT
+#define MD4_Update MD4_UPDATE
+#define MD5_Final MD5_FINAL
+#define MD5_Init MD5_INIT
+#define MD5_Update MD5_UPDATE
+#define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF
+#define PEM_read_X509 PEM_READ_X509
+#define PEM_write_bio_X509 PEM_WRITE_BIO_X509
+#define PKCS12_PBE_add PKCS12_PBE_ADD
+#define PKCS12_free PKCS12_FREE
+#define PKCS12_parse PKCS12_PARSE
+#define RAND_add RAND_ADD
+#define RAND_bytes RAND_BYTES
+#define RAND_egd RAND_EGD
+#define RAND_file_name RAND_FILE_NAME
+#define RAND_load_file RAND_LOAD_FILE
+#define RAND_status RAND_STATUS
+#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME
+#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA
+#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL
+#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY
+#define SSL_CTX_ctrl SSL_CTX_CTRL
+#define SSL_CTX_free SSL_CTX_FREE
+#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE
+#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS
+#define SSL_CTX_new SSL_CTX_NEW
+#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST
+#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD
+#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB
+#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY
+#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY
+#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE
+#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE
+#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE
+#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE
+#define SSL_SESSION_free SSL_SESSION_FREE
+#define SSL_connect SSL_CONNECT
+#define SSL_free SSL_FREE
+#define SSL_get1_session SSL_GET1_SESSION
+#define SSL_get_certificate SSL_GET_CERTIFICATE
+#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER
+#define SSL_get_error SSL_GET_ERROR
+#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN
+#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE
+#define SSL_get_privatekey SSL_GET_PRIVATEKEY
+#define SSL_get_session SSL_GET_SESSION
+#define SSL_get_shutdown SSL_GET_SHUTDOWN
+#define SSL_get_verify_result SSL_GET_VERIFY_RESULT
+#define SSL_library_init SSL_LIBRARY_INIT
+#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS
+#define SSL_new SSL_NEW
+#define SSL_peek SSL_PEEK
+#define SSL_pending SSL_PENDING
+#define SSL_read SSL_READ
+#define SSL_set_connect_state SSL_SET_CONNECT_STATE
+#define SSL_set_fd SSL_SET_FD
+#define SSL_set_session SSL_SET_SESSION
+#define SSL_shutdown SSL_SHUTDOWN
+#define SSL_write SSL_WRITE
+#define SSLeay SSLEAY
+#define SSLv23_client_method SSLV23_CLIENT_METHOD
+#define SSLv3_client_method SSLV3_CLIENT_METHOD
+#define TLSv1_client_method TLSV1_CLIENT_METHOD
+#define UI_create_method UI_CREATE_METHOD
+#define UI_destroy_method UI_DESTROY_METHOD
+#define UI_get0_user_data UI_GET0_USER_DATA
+#define UI_get_input_flags UI_GET_INPUT_FLAGS
+#define UI_get_string_type UI_GET_STRING_TYPE
+#define UI_create_method UI_CREATE_METHOD
+#define UI_destroy_method UI_DESTROY_METHOD
+#define UI_method_get_closer UI_METHOD_GET_CLOSER
+#define UI_method_get_opener UI_METHOD_GET_OPENER
+#define UI_method_get_reader UI_METHOD_GET_READER
+#define UI_method_get_writer UI_METHOD_GET_WRITER
+#define UI_method_set_closer UI_METHOD_SET_CLOSER
+#define UI_method_set_opener UI_METHOD_SET_OPENER
+#define UI_method_set_reader UI_METHOD_SET_READER
+#define UI_method_set_writer UI_METHOD_SET_WRITER
+#define UI_OpenSSL UI_OPENSSL
+#define UI_set_result UI_SET_RESULT
+#define X509V3_EXT_print X509V3_EXT_PRINT
+#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL
+#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT
+#define X509_LOOKUP_file X509_LOOKUP_FILE
+#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA
+#define X509_NAME_get_entry X509_NAME_GET_ENTRY
+#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID
+#define X509_NAME_print_ex X509_NAME_PRINT_EX
+#define X509_STORE_CTX_get_current_cert X509_STORE_CTX_GET_CURRENT_CERT
+#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP
+#define X509_STORE_set_flags X509_STORE_SET_FLAGS
+#define X509_check_issued X509_CHECK_ISSUED
+#define X509_free X509_FREE
+#define X509_get_ext_d2i X509_GET_EXT_D2I
+#define X509_get_issuer_name X509_GET_ISSUER_NAME
+#define X509_get_pubkey X509_GET_PUBKEY
+#define X509_get_serialNumber X509_GET_SERIALNUMBER
+#define X509_get_subject_name X509_GET_SUBJECT_NAME
+#define X509_load_crl_file X509_LOAD_CRL_FILE
+#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING
+#define d2i_PKCS12_fp D2I_PKCS12_FP
+#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT
+#define sk_num SK_NUM
+#define sk_pop SK_POP
+#define sk_pop_free SK_POP_FREE
+#define sk_value SK_VALUE
+
+#define USE_UPPERCASE_GSSAPI 1
+#define gss_seal GSS_SEAL
+#define gss_unseal GSS_UNSEAL
+
+#define USE_UPPERCASE_KRBAPI 1
+
+/* AI_NUMERICHOST needed for IP V6 support in Curl */
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#ifndef AI_NUMERICHOST
+#ifdef ENABLE_IPV6
+#undef ENABLE_IPV6
+#endif
+#endif
+#endif
+
+/* VAX symbols are always in uppercase */
+#ifdef __VAX
+#define inflate INFLATE
+#define inflateEnd INFLATEEND
+#define inflateInit2_ INFLATEINIT2_
+#define inflateInit_ INFLATEINIT_
+#define zlibVersion ZLIBVERSION
+#endif
+
+/* Older VAX OpenSSL port defines these as Macros */
+/* Need to include the headers first and then redefine */
+/* that way a newer port will also work if some one has one */
+#ifdef __VAX
+
+# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+# define des_set_odd_parity DES_SET_ODD_PARITY
+# define des_set_key DES_SET_KEY
+# define des_ecb_encrypt DES_ECB_ENCRYPT
+
+# endif
+# include <openssl/evp.h>
+# ifndef OpenSSL_add_all_algorithms
+# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS
+ void OPENSSL_ADD_ALL_ALGORITHMS(void);
+# endif
+
+ /* Curl defines these to lower case and VAX needs them in upper case */
+ /* So we need static routines */
+# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+
+# undef des_set_odd_parity
+# undef DES_set_odd_parity
+# undef des_set_key
+# undef DES_set_key
+# undef des_ecb_encrypt
+# undef DES_ecb_encrypt
+
+ static void des_set_odd_parity(des_cblock *key) {
+ DES_SET_ODD_PARITY(key);
+ }
+
+ static int des_set_key(const_des_cblock *key,
+ des_key_schedule schedule) {
+ return DES_SET_KEY(key, schedule);
+ }
+
+ static void des_ecb_encrypt(const_des_cblock *input,
+ des_cblock *output,
+ des_key_schedule ks, int enc) {
+ DES_ECB_ENCRYPT(input, output, ks, enc);
+ }
+#endif
+/* Need this to stop a macro redefinition error */
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+# ifdef X509_STORE_set_flags
+# undef X509_STORE_set_flags
+# define X509_STORE_set_flags(x,y) Curl_nop_stmt
+# endif
+#endif
+#endif
+
+#endif /* HEADER_CURL_SETUP_VMS_H */
diff --git a/libcurl/src/lib/share.c b/libcurl/src/lib/share.c
new file mode 100644
index 0000000..ee04521
--- /dev/null
+++ b/libcurl/src/lib/share.c
@@ -0,0 +1,253 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "share.h"
+#include "vtls/vtls.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURLSH *
+curl_share_init(void)
+{
+ struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
+ if(share)
+ share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
+
+ return share;
+}
+
+//#undef curl_share_setopt
+CURLSHcode
+curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
+{
+ struct Curl_share *share = (struct Curl_share *)sh;
+ va_list param;
+ int type;
+ curl_lock_function lockfunc;
+ curl_unlock_function unlockfunc;
+ void *ptr;
+ CURLSHcode res = CURLSHE_OK;
+
+ if(share->dirty)
+ /* don't allow setting options while one or more handles are already
+ using this share */
+ return CURLSHE_IN_USE;
+
+ va_start(param, option);
+
+ switch(option) {
+ case CURLSHOPT_SHARE:
+ /* this is a type this share will share */
+ type = va_arg(param, int);
+ share->specifier |= (1<<type);
+ switch( type ) {
+ case CURL_LOCK_DATA_DNS:
+ if(!share->hostcache) {
+ share->hostcache = Curl_mk_dnscache();
+ if(!share->hostcache)
+ res = CURLSHE_NOMEM;
+ }
+ break;
+
+ case CURL_LOCK_DATA_COOKIE:
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(!share->cookies) {
+ share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE );
+ if(!share->cookies)
+ res = CURLSHE_NOMEM;
+ }
+#else /* CURL_DISABLE_HTTP */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_SSL_SESSION:
+#ifdef USE_SSL
+ if(!share->sslsession) {
+ share->max_ssl_sessions = 8;
+ share->sslsession = calloc(share->max_ssl_sessions,
+ sizeof(struct curl_ssl_session));
+ share->sessionage = 0;
+ if(!share->sslsession)
+ res = CURLSHE_NOMEM;
+ }
+#else
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
+ break;
+
+ default:
+ res = CURLSHE_BAD_OPTION;
+ }
+ break;
+
+ case CURLSHOPT_UNSHARE:
+ /* this is a type this share will no longer share */
+ type = va_arg(param, int);
+ share->specifier &= ~(1<<type);
+ switch( type ) {
+ case CURL_LOCK_DATA_DNS:
+ if(share->hostcache) {
+ Curl_hash_destroy(share->hostcache);
+ share->hostcache = NULL;
+ }
+ break;
+
+ case CURL_LOCK_DATA_COOKIE:
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(share->cookies) {
+ Curl_cookie_cleanup(share->cookies);
+ share->cookies = NULL;
+ }
+#else /* CURL_DISABLE_HTTP */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_SSL_SESSION:
+#ifdef USE_SSL
+ Curl_safefree(share->sslsession);
+#else
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_CONNECT:
+ break;
+
+ default:
+ res = CURLSHE_BAD_OPTION;
+ break;
+ }
+ break;
+
+ case CURLSHOPT_LOCKFUNC:
+ lockfunc = va_arg(param, curl_lock_function);
+ share->lockfunc = lockfunc;
+ break;
+
+ case CURLSHOPT_UNLOCKFUNC:
+ unlockfunc = va_arg(param, curl_unlock_function);
+ share->unlockfunc = unlockfunc;
+ break;
+
+ case CURLSHOPT_USERDATA:
+ ptr = va_arg(param, void *);
+ share->clientdata = ptr;
+ break;
+
+ default:
+ res = CURLSHE_BAD_OPTION;
+ break;
+ }
+
+ va_end(param);
+
+ return res;
+}
+
+CURLSHcode
+curl_share_cleanup(CURLSH *sh)
+{
+ struct Curl_share *share = (struct Curl_share *)sh;
+
+ if(share == NULL)
+ return CURLSHE_INVALID;
+
+ if(share->lockfunc)
+ share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
+ share->clientdata);
+
+ if(share->dirty) {
+ if(share->unlockfunc)
+ share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
+ return CURLSHE_IN_USE;
+ }
+
+ if(share->hostcache) {
+ Curl_hash_destroy(share->hostcache);
+ share->hostcache = NULL;
+ }
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ Curl_cookie_cleanup(share->cookies);
+#endif
+
+#ifdef USE_SSL
+ if(share->sslsession) {
+ size_t i;
+ for(i = 0; i < share->max_ssl_sessions; i++)
+ Curl_ssl_kill_session(&(share->sslsession[i]));
+ free(share->sslsession);
+ }
+#endif
+
+ if(share->unlockfunc)
+ share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
+ free(share);
+
+ return CURLSHE_OK;
+}
+
+
+CURL_STATIC CURLSHcode
+Curl_share_lock(struct SessionHandle *data, curl_lock_data type,
+ curl_lock_access accesstype)
+{
+ struct Curl_share *share = data->share;
+
+ if(share == NULL)
+ return CURLSHE_INVALID;
+
+ if(share->specifier & (1<<type)) {
+ if(share->lockfunc) /* only call this if set! */
+ share->lockfunc(data, type, accesstype, share->clientdata);
+ }
+ /* else if we don't share this, pretend successful lock */
+
+ return CURLSHE_OK;
+}
+
+CURL_STATIC CURLSHcode
+Curl_share_unlock(struct SessionHandle *data, curl_lock_data type)
+{
+ struct Curl_share *share = data->share;
+
+ if(share == NULL)
+ return CURLSHE_INVALID;
+
+ if(share->specifier & (1<<type)) {
+ if(share->unlockfunc) /* only call this if set! */
+ share->unlockfunc (data, type, share->clientdata);
+ }
+
+ return CURLSHE_OK;
+}
diff --git a/libcurl/src/lib/share.h b/libcurl/src/lib/share.h
new file mode 100644
index 0000000..ea90977
--- /dev/null
+++ b/libcurl/src/lib/share.h
@@ -0,0 +1,61 @@
+#ifndef HEADER_CURL_SHARE_H
+#define HEADER_CURL_SHARE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include <curl/curl.h>
+#include "cookie.h"
+#include "urldata.h"
+
+/* SalfordC says "A structure member may not be volatile". Hence:
+ */
+#ifdef __SALFORDC__
+#define CURL_VOLATILE
+#else
+#define CURL_VOLATILE volatile
+#endif
+
+/* this struct is libcurl-private, don't export details */
+struct Curl_share {
+ unsigned int specifier;
+ CURL_VOLATILE unsigned int dirty;
+
+ curl_lock_function lockfunc;
+ curl_unlock_function unlockfunc;
+ void *clientdata;
+
+ struct curl_hash *hostcache;
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ struct CookieInfo *cookies;
+#endif
+
+ struct curl_ssl_session *sslsession;
+ size_t max_ssl_sessions;
+ long sessionage;
+};
+
+CURL_STATIC CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
+ curl_lock_access);
+CURL_STATIC CURLSHcode Curl_share_unlock (struct SessionHandle *, curl_lock_data);
+
+#endif /* HEADER_CURL_SHARE_H */
diff --git a/libcurl/src/lib/sigpipe.h b/libcurl/src/lib/sigpipe.h
new file mode 100644
index 0000000..e8d2acd
--- /dev/null
+++ b/libcurl/src/lib/sigpipe.h
@@ -0,0 +1,78 @@
+#ifndef HEADER_CURL_SIGPIPE_H
+#define HEADER_CURL_SIGPIPE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL)
+#include <signal.h>
+
+struct sigpipe_ignore {
+ struct sigaction old_pipe_act;
+ bool no_signal;
+};
+
+#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x
+
+/*
+ * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl
+ * internals, and then sigpipe_restore() will restore the situation when we
+ * return from libcurl again.
+ */
+static void sigpipe_ignore(struct SessionHandle *data,
+ struct sigpipe_ignore *ig)
+{
+ /* get a local copy of no_signal because the SessionHandle might not be
+ around when we restore */
+ ig->no_signal = data->set.no_signal;
+ if(!data->set.no_signal) {
+ struct sigaction action;
+ /* first, extract the existing situation */
+ memset(&ig->old_pipe_act, 0, sizeof(struct sigaction));
+ sigaction(SIGPIPE, NULL, &ig->old_pipe_act);
+ action = ig->old_pipe_act;
+ /* ignore this signal */
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+ }
+}
+
+/*
+ * sigpipe_restore() puts back the outside world's opinion of signal handler
+ * and SIGPIPE handling. It MUST only be called after a corresponding
+ * sigpipe_ignore() was used.
+ */
+static void sigpipe_restore(struct sigpipe_ignore *ig)
+{
+ if(!ig->no_signal)
+ /* restore the outside state */
+ sigaction(SIGPIPE, &ig->old_pipe_act, NULL);
+}
+
+#else
+/* for systems without sigaction */
+#define sigpipe_ignore(x,y) Curl_nop_stmt
+#define sigpipe_restore(x) Curl_nop_stmt
+#define SIGPIPE_VARIABLE(x)
+#endif
+
+#endif /* HEADER_CURL_SIGPIPE_H */
diff --git a/libcurl/src/lib/slist.c b/libcurl/src/lib/slist.c
new file mode 100644
index 0000000..78ecf54
--- /dev/null
+++ b/libcurl/src/lib/slist.c
@@ -0,0 +1,143 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "slist.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* returns last node in linked list */
+static struct curl_slist *slist_get_last(struct curl_slist *list)
+{
+ struct curl_slist *item;
+
+ /* if caller passed us a NULL, return now */
+ if(!list)
+ return NULL;
+
+ /* loop through to find the last item */
+ item = list;
+ while(item->next) {
+ item = item->next;
+ }
+ return item;
+}
+
+/*
+ * Curl_slist_append_nodup() appends a string to the linked list. Rather than
+ * copying the string in dynamic storage, it takes its ownership. The string
+ * should have been malloc()ated. Curl_slist_append_nodup always returns
+ * the address of the first record, so that you can use this function as an
+ * initialization function as well as an append function.
+ * If an error occurs, NULL is returned and the string argument is NOT
+ * released.
+ */
+CURL_STATIC struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data)
+{
+ struct curl_slist *last;
+ struct curl_slist *new_item;
+
+ DEBUGASSERT(data);
+
+ new_item = malloc(sizeof(struct curl_slist));
+ if(!new_item)
+ return NULL;
+
+ new_item->next = NULL;
+ new_item->data = data;
+
+ /* if this is the first item, then new_item *is* the list */
+ if(!list)
+ return new_item;
+
+ last = slist_get_last(list);
+ last->next = new_item;
+ return list;
+}
+
+/*
+ * curl_slist_append() appends a string to the linked list. It always returns
+ * the address of the first record, so that you can use this function as an
+ * initialization function as well as an append function. If you find this
+ * bothersome, then simply create a separate _init function and call it
+ * appropriately from within the program.
+ */
+struct curl_slist *curl_slist_append(struct curl_slist *list,
+ const char *data)
+{
+ char *dupdata = strdup(data);
+
+ if(!dupdata)
+ return NULL;
+
+ list = Curl_slist_append_nodup(list, dupdata);
+ if(!list)
+ free(dupdata);
+
+ return list;
+}
+
+/*
+ * Curl_slist_duplicate() duplicates a linked list. It always returns the
+ * address of the first record of the cloned list or NULL in case of an
+ * error (or if the input list was NULL).
+ */
+CURL_STATIC struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist)
+{
+ struct curl_slist *outlist = NULL;
+ struct curl_slist *tmp;
+
+ while(inlist) {
+ tmp = curl_slist_append(outlist, inlist->data);
+
+ if(!tmp) {
+ curl_slist_free_all(outlist);
+ return NULL;
+ }
+
+ outlist = tmp;
+ inlist = inlist->next;
+ }
+ return outlist;
+}
+
+/* be nice and clean up resources */
+void curl_slist_free_all(struct curl_slist *list)
+{
+ struct curl_slist *next;
+ struct curl_slist *item;
+
+ if(!list)
+ return;
+
+ item = list;
+ do {
+ next = item->next;
+ Curl_safefree(item->data);
+ free(item);
+ item = next;
+ } while(next);
+}
+
diff --git a/libcurl/src/lib/slist.h b/libcurl/src/lib/slist.h
new file mode 100644
index 0000000..b4fef87
--- /dev/null
+++ b/libcurl/src/lib/slist.h
@@ -0,0 +1,40 @@
+#ifndef HEADER_CURL_SLIST_H
+#define HEADER_CURL_SLIST_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Curl_slist_duplicate() duplicates a linked list. It always returns the
+ * address of the first record of the cloned list or NULL in case of an
+ * error (or if the input list was NULL).
+ */
+CURL_STATIC struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist);
+
+/*
+ * Curl_slist_append_nodup() takes ownership of the given string and appends
+ * it to the list.
+ */
+CURL_STATIC struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list,
+ char *data);
+
+#endif /* HEADER_CURL_SLIST_H */
+
diff --git a/libcurl/src/lib/smb.c b/libcurl/src/lib/smb.c
new file mode 100644
index 0000000..8cb3503
--- /dev/null
+++ b/libcurl/src/lib/smb.c
@@ -0,0 +1,970 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
+ * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4)
+
+#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
+
+#define BUILDING_CURL_SMB_C
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#define getpid _getpid
+#endif
+
+#include "smb.h"
+#include "urldata.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "connect.h"
+#include "progress.h"
+#include "transfer.h"
+#include "vtls/vtls.h"
+#include "curl_ntlm_core.h"
+#include "escape.h"
+#include "curl_endian.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* Local API functions */
+static CURLcode smb_setup_connection(struct connectdata *conn);
+static CURLcode smb_connect(struct connectdata *conn, bool *done);
+static CURLcode smb_connection_state(struct connectdata *conn, bool *done);
+static CURLcode smb_request_state(struct connectdata *conn, bool *done);
+static CURLcode smb_done(struct connectdata *conn, CURLcode status,
+ bool premature);
+static CURLcode smb_disconnect(struct connectdata *conn, bool dead);
+static int smb_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode smb_parse_url_path(struct connectdata *conn);
+
+/*
+ * SMB handler interface
+ */
+const struct Curl_handler Curl_handler_smb = {
+ "SMB", /* scheme */
+ smb_setup_connection, /* setup_connection */
+ ZERO_NULL, /* do_it */
+ smb_done, /* done */
+ ZERO_NULL, /* do_more */
+ smb_connect, /* connect_it */
+ smb_connection_state, /* connecting */
+ smb_request_state, /* doing */
+ smb_getsock, /* proto_getsock */
+ smb_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ smb_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMB, /* defport */
+ CURLPROTO_SMB, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * SMBS handler interface
+ */
+const struct Curl_handler Curl_handler_smbs = {
+ "SMBS", /* scheme */
+ smb_setup_connection, /* setup_connection */
+ ZERO_NULL, /* do_it */
+ smb_done, /* done */
+ ZERO_NULL, /* do_more */
+ smb_connect, /* connect_it */
+ smb_connection_state, /* connecting */
+ smb_request_state, /* doing */
+ smb_getsock, /* proto_getsock */
+ smb_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ smb_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMBS, /* defport */
+ CURLPROTO_SMBS, /* protocol */
+ PROTOPT_SSL /* flags */
+};
+#endif
+
+#define MAX_PAYLOAD_SIZE 0x8000
+#define MAX_MESSAGE_SIZE (MAX_PAYLOAD_SIZE + 0x1000)
+#define CLIENTNAME "curl"
+#define SERVICENAME "?????"
+
+/* Append a string to an SMB message */
+#define MSGCAT(str) \
+ strcpy(p, (str)); \
+ p += strlen(str);
+
+/* Append a null-terminated string to an SMB message */
+#define MSGCATNULL(str) \
+ strcpy(p, (str)); \
+ p += strlen(str) + 1;
+
+/* SMB is mostly little endian */
+#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
+ defined(__OS400__)
+static unsigned short smb_swap16(unsigned short x)
+{
+ return (x << 8) | ((x >> 8) & 0xff);
+}
+
+static unsigned int smb_swap32(unsigned int x)
+{
+ return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) |
+ ((x >> 24) & 0xff);
+}
+
+#ifdef HAVE_LONGLONG
+static unsigned long long smb_swap64(unsigned long long x)
+{
+ return ((unsigned long long)smb_swap32(x) << 32) | smb_swap32(x >> 32);
+}
+#else
+static unsigned __int64 smb_swap64(unsigned __int64 x)
+{
+ return ((unsigned __int64)smb_swap32(x) << 32) | smb_swap32(x >> 32);
+}
+#endif
+#else
+# define smb_swap16(x) (x)
+# define smb_swap32(x) (x)
+# define smb_swap64(x) (x)
+#endif
+
+/* SMB request state */
+enum smb_req_state {
+ SMB_REQUESTING,
+ SMB_TREE_CONNECT,
+ SMB_OPEN,
+ SMB_DOWNLOAD,
+ SMB_UPLOAD,
+ SMB_CLOSE,
+ SMB_TREE_DISCONNECT,
+ SMB_DONE
+};
+
+/* SMB request data */
+struct smb_request {
+ enum smb_req_state state;
+ char *share;
+ char *path;
+ unsigned short tid; /* Even if we connect to the same tree as another */
+ unsigned short fid; /* request, the tid will be different */
+ CURLcode result;
+};
+
+static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
+{
+ struct smb_conn *smb = &conn->proto.smbc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* For debug purposes */
+ static const char * const names[] = {
+ "SMB_NOT_CONNECTED",
+ "SMB_CONNECTING",
+ "SMB_NEGOTIATE",
+ "SMB_SETUP",
+ "SMB_CONNECTED",
+ /* LAST */
+ };
+
+ if(smb->state != newstate)
+ infof(conn->data, "SMB conn %p state change from %s to %s\n",
+ (void *)smb, names[smb->state], names[newstate]);
+#endif
+
+ smb->state = newstate;
+}
+
+static void request_state(struct connectdata *conn,
+ enum smb_req_state newstate)
+{
+ struct smb_request *req = conn->data->req.protop;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* For debug purposes */
+ static const char * const names[] = {
+ "SMB_REQUESTING",
+ "SMB_TREE_CONNECT",
+ "SMB_OPEN",
+ "SMB_DOWNLOAD",
+ "SMB_UPLOAD",
+ "SMB_CLOSE",
+ "SMB_TREE_DISCONNECT",
+ "SMB_DONE",
+ /* LAST */
+ };
+
+ if(req->state != newstate)
+ infof(conn->data, "SMB request %p state change from %s to %s\n",
+ (void *)req, names[req->state], names[newstate]);
+#endif
+
+ req->state = newstate;
+}
+
+static CURLcode smb_setup_connection(struct connectdata *conn)
+{
+ struct smb_request *req;
+
+ /* Initialize the request state */
+ conn->data->req.protop = req = calloc(1, sizeof(struct smb_request));
+ if(!req)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Parse the URL path */
+ return smb_parse_url_path(conn);
+}
+
+static CURLcode smb_connect(struct connectdata *conn, bool *done)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ char *slash;
+
+ (void) done;
+
+ /* Check we have a username and password to authenticate with */
+ if(!conn->bits.user_passwd)
+ return CURLE_LOGIN_DENIED;
+
+ /* Initialize the connection state */
+ memset(smbc, 0, sizeof(*smbc));
+ smbc->state = SMB_CONNECTING;
+ smbc->recv_buf = malloc(MAX_MESSAGE_SIZE);
+ if(!smbc->recv_buf)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Multiple requests are allowed with this connection */
+ connkeep(conn, "SMB default");
+
+ /* Parse the username, domain, and password */
+ slash = strchr(conn->user, '/');
+ if(!slash)
+ slash = strchr(conn->user, '\\');
+
+ if(slash) {
+ smbc->user = slash + 1;
+ smbc->domain = strdup(conn->user);
+ if(!smbc->domain)
+ return CURLE_OUT_OF_MEMORY;
+ smbc->domain[slash - conn->user] = 0;
+ }
+ else {
+ smbc->user = conn->user;
+ smbc->domain = strdup(conn->host.name);
+ if(!smbc->domain)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ char *buf = smbc->recv_buf;
+ ssize_t bytes_read;
+ size_t nbt_size;
+ size_t msg_size;
+ size_t len = MAX_MESSAGE_SIZE - smbc->got;
+ CURLcode result;
+
+ result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read);
+ if(result)
+ return result;
+
+ if(!bytes_read)
+ return CURLE_OK;
+
+ smbc->got += bytes_read;
+
+ /* Check for a 32-bit nbt header */
+ if(smbc->got < sizeof(unsigned int))
+ return CURLE_OK;
+
+ nbt_size = Curl_read16_be((unsigned char *)(buf + sizeof(unsigned short))) +
+ sizeof(unsigned int);
+ if(smbc->got < nbt_size)
+ return CURLE_OK;
+
+ msg_size = sizeof(struct smb_header);
+ if(nbt_size >= msg_size + 1) {
+ /* Add the word count */
+ msg_size += 1 + ((unsigned char) buf[msg_size]) * sizeof(unsigned short);
+ if(nbt_size >= msg_size + sizeof(unsigned short)) {
+ /* Add the byte count */
+ msg_size += sizeof(unsigned short) +
+ Curl_read16_le((unsigned char *)&buf[msg_size]);
+ if(nbt_size < msg_size)
+ return CURLE_READ_ERROR;
+ }
+ }
+
+ *msg = buf;
+
+ return CURLE_OK;
+}
+
+static void smb_pop_message(struct connectdata *conn)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+
+ smbc->got = 0;
+}
+
+static void smb_format_message(struct connectdata *conn, struct smb_header *h,
+ unsigned char cmd, size_t len)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_request *req = conn->data->req.protop;
+ unsigned int pid;
+
+ memset(h, 0, sizeof(*h));
+ h->nbt_length = htons((unsigned short) (sizeof(*h) - sizeof(unsigned int) +
+ len));
+ memcpy((char *)h->magic, "\xffSMB", 4);
+ h->command = cmd;
+ h->flags = SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES;
+ h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME);
+ h->uid = smb_swap16(smbc->uid);
+ h->tid = smb_swap16(req->tid);
+ pid = getpid();
+ h->pid_high = smb_swap16((unsigned short)(pid >> 16));
+ h->pid = smb_swap16((unsigned short) pid);
+}
+
+static CURLcode smb_send(struct connectdata *conn, ssize_t len,
+ size_t upload_size)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ ssize_t bytes_written;
+ CURLcode result;
+
+ result = Curl_write(conn, FIRSTSOCKET, conn->data->state.uploadbuffer,
+ len, &bytes_written);
+ if(result)
+ return result;
+
+ if(bytes_written != len) {
+ smbc->send_size = len;
+ smbc->sent = bytes_written;
+ }
+
+ smbc->upload_size = upload_size;
+
+ return CURLE_OK;
+}
+
+static CURLcode smb_flush(struct connectdata *conn)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ ssize_t bytes_written;
+ ssize_t len = smbc->send_size - smbc->sent;
+ CURLcode result;
+
+ if(!smbc->send_size)
+ return CURLE_OK;
+
+ result = Curl_write(conn, FIRSTSOCKET,
+ conn->data->state.uploadbuffer + smbc->sent,
+ len, &bytes_written);
+ if(result)
+ return result;
+
+ if(bytes_written != len)
+ smbc->sent += bytes_written;
+ else
+ smbc->send_size = 0;
+
+ return CURLE_OK;
+}
+
+static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd,
+ const void *msg, size_t msg_len)
+{
+ smb_format_message(conn, (struct smb_header *)conn->data->state.uploadbuffer,
+ cmd, msg_len);
+ memcpy(conn->data->state.uploadbuffer + sizeof(struct smb_header),
+ msg, msg_len);
+
+ return smb_send(conn, sizeof(struct smb_header) + msg_len, 0);
+}
+
+static CURLcode smb_send_negotiate(struct connectdata *conn)
+{
+ const char *msg = "\x00\x0c\x00\x02NT LM 0.12";
+
+ return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15);
+}
+
+static CURLcode smb_send_setup(struct connectdata *conn)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_setup msg;
+ char *p = msg.bytes;
+ unsigned char lm_hash[21];
+ unsigned char lm[24];
+ unsigned char nt_hash[21];
+ unsigned char nt[24];
+
+ size_t byte_count = sizeof(lm) + sizeof(nt);
+ byte_count += strlen(smbc->user) + strlen(smbc->domain);
+ byte_count += strlen(OS) + strlen(CLIENTNAME) + 4; /* 4 null chars */
+ if(byte_count > sizeof(msg.bytes))
+ return CURLE_FILESIZE_EXCEEDED;
+
+ Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash);
+ Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm);
+#if USE_NTRESPONSES
+ Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash);
+ Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt);
+#else
+ memset(nt, 0, sizeof(nt));
+#endif
+
+ memset(&msg, 0, sizeof(msg));
+ msg.word_count = SMB_WC_SETUP_ANDX;
+ msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
+ msg.max_buffer_size = smb_swap16(MAX_MESSAGE_SIZE);
+ msg.max_mpx_count = smb_swap16(1);
+ msg.vc_number = smb_swap16(1);
+ msg.session_key = smb_swap32(smbc->session_key);
+ msg.capabilities = smb_swap32(SMB_CAP_LARGE_FILES);
+ msg.lengths[0] = smb_swap16(sizeof(lm));
+ msg.lengths[1] = smb_swap16(sizeof(nt));
+ memcpy(p, lm, sizeof(lm));
+ p += sizeof(lm);
+ memcpy(p, nt, sizeof(nt));
+ p += sizeof(nt);
+ MSGCATNULL(smbc->user);
+ MSGCATNULL(smbc->domain);
+ MSGCATNULL(OS);
+ MSGCATNULL(CLIENTNAME);
+ byte_count = p - msg.bytes;
+ msg.byte_count = smb_swap16((unsigned short)byte_count);
+
+ return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg,
+ sizeof(msg) - sizeof(msg.bytes) + byte_count);
+}
+
+static CURLcode smb_send_tree_connect(struct connectdata *conn)
+{
+ struct smb_request *req = conn->data->req.protop;
+ struct smb_tree_connect msg;
+ char *p = msg.bytes;
+
+ size_t byte_count = strlen(conn->host.name) + strlen(req->share);
+ byte_count += strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
+ if(byte_count > sizeof(msg.bytes))
+ return CURLE_FILESIZE_EXCEEDED;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.word_count = SMB_WC_TREE_CONNECT_ANDX;
+ msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
+ msg.pw_len = 0;
+ MSGCAT("\\\\");
+ MSGCAT(conn->host.name);
+ MSGCAT("\\");
+ MSGCATNULL(req->share);
+ MSGCATNULL(SERVICENAME); /* Match any type of service */
+ byte_count = p - msg.bytes;
+ msg.byte_count = smb_swap16((unsigned short)byte_count);
+
+ return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg,
+ sizeof(msg) - sizeof(msg.bytes) + byte_count);
+}
+
+static CURLcode smb_send_open(struct connectdata *conn)
+{
+ struct smb_request *req = conn->data->req.protop;
+ struct smb_nt_create msg;
+ size_t byte_count;
+
+ if((strlen(req->path) + 1) > sizeof(msg.bytes))
+ return CURLE_FILESIZE_EXCEEDED;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.word_count = SMB_WC_NT_CREATE_ANDX;
+ msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
+ byte_count = strlen(req->path);
+ msg.name_length = smb_swap16((unsigned short)byte_count);
+ msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
+ if(conn->data->set.upload) {
+ msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
+ msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
+ }
+ else {
+ msg.access = smb_swap32(SMB_GENERIC_READ);
+ msg.create_disposition = smb_swap32(SMB_FILE_OPEN);
+ }
+ msg.byte_count = smb_swap16((unsigned short) ++byte_count);
+ strcpy(msg.bytes, req->path);
+
+ return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg,
+ sizeof(msg) - sizeof(msg.bytes) + byte_count);
+}
+
+static CURLcode smb_send_close(struct connectdata *conn)
+{
+ struct smb_request *req = conn->data->req.protop;
+ struct smb_close msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.word_count = SMB_WC_CLOSE;
+ msg.fid = smb_swap16(req->fid);
+
+ return smb_send_message(conn, SMB_COM_CLOSE, &msg, sizeof(msg));
+}
+
+static CURLcode smb_send_tree_disconnect(struct connectdata *conn)
+{
+ struct smb_tree_disconnect msg;
+
+ memset(&msg, 0, sizeof(msg));
+
+ return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
+}
+
+static CURLcode smb_send_read(struct connectdata *conn)
+{
+ struct smb_request *req = conn->data->req.protop;
+ curl_off_t offset = conn->data->req.offset;
+ struct smb_read msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.word_count = SMB_WC_READ_ANDX;
+ msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
+ msg.fid = smb_swap16(req->fid);
+ msg.offset = smb_swap32((unsigned int) offset);
+ msg.offset_high = smb_swap32((unsigned int) (offset >> 32));
+ msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
+ msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
+
+ return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg));
+}
+
+static CURLcode smb_send_write(struct connectdata *conn)
+{
+ struct smb_write *msg = (struct smb_write *)conn->data->state.uploadbuffer;
+ struct smb_request *req = conn->data->req.protop;
+ curl_off_t offset = conn->data->req.offset;
+
+ curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
+ if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
+ upload_size = MAX_PAYLOAD_SIZE - 1;
+
+ memset(msg, 0, sizeof(*msg));
+ msg->word_count = SMB_WC_WRITE_ANDX;
+ msg->andx.command = SMB_COM_NO_ANDX_COMMAND;
+ msg->fid = smb_swap16(req->fid);
+ msg->offset = smb_swap32((unsigned int) offset);
+ msg->offset_high = smb_swap32((unsigned int) (offset >> 32));
+ msg->data_length = smb_swap16((unsigned short) upload_size);
+ msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int));
+ msg->byte_count = smb_swap16((unsigned short) (upload_size + 1));
+
+ smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX,
+ sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size);
+
+ return smb_send(conn, sizeof(*msg), (size_t) upload_size);
+}
+
+static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ CURLcode result;
+
+ /* Check if there is data in the transfer buffer */
+ if(!smbc->send_size && smbc->upload_size) {
+ int nread = smbc->upload_size > BUFSIZE ? BUFSIZE :
+ (int) smbc->upload_size;
+ conn->data->req.upload_fromhere = conn->data->state.uploadbuffer;
+ result = Curl_fillreadbuffer(conn, nread, &nread);
+ if(result && result != CURLE_AGAIN)
+ return result;
+ if(!nread)
+ return CURLE_OK;
+
+ smbc->upload_size -= nread;
+ smbc->send_size = nread;
+ smbc->sent = 0;
+ }
+
+ /* Check if there is data to send */
+ if(smbc->send_size) {
+ result = smb_flush(conn);
+ if(result)
+ return result;
+ }
+
+ /* Check if there is still data to be sent */
+ if(smbc->send_size || smbc->upload_size)
+ return CURLE_AGAIN;
+
+ return smb_recv_message(conn, msg);
+}
+
+static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_negotiate_response *nrsp;
+ struct smb_header *h;
+ CURLcode result;
+ void *msg = NULL;
+
+ if(smbc->state == SMB_CONNECTING) {
+#ifdef USE_SSL
+ if((conn->handler->flags & PROTOPT_SSL)) {
+ bool ssl_done;
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done);
+ if(result && result != CURLE_AGAIN)
+ return result;
+ if(!ssl_done)
+ return CURLE_OK;
+ }
+#endif
+
+ result = smb_send_negotiate(conn);
+ if(result) {
+ connclose(conn, "SMB: failed to send negotiate message");
+ return result;
+ }
+
+ conn_state(conn, SMB_NEGOTIATE);
+ }
+
+ /* Send the previous message and check for a response */
+ result = smb_send_and_recv(conn, &msg);
+ if(result && result != CURLE_AGAIN) {
+ connclose(conn, "SMB: failed to communicate");
+ return result;
+ }
+
+ if(!msg)
+ return CURLE_OK;
+
+ h = msg;
+
+ switch(smbc->state) {
+ case SMB_NEGOTIATE:
+ if(h->status) {
+ connclose(conn, "SMB: negotiation failed");
+ return CURLE_COULDNT_CONNECT;
+ }
+ nrsp = msg;
+ memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge));
+ smbc->session_key = smb_swap32(nrsp->session_key);
+ result = smb_send_setup(conn);
+ if(result) {
+ connclose(conn, "SMB: failed to send setup message");
+ return result;
+ }
+ conn_state(conn, SMB_SETUP);
+ break;
+
+ case SMB_SETUP:
+ if(h->status) {
+ connclose(conn, "SMB: authentication failed");
+ return CURLE_LOGIN_DENIED;
+ }
+ smbc->uid = smb_swap16(h->uid);
+ conn_state(conn, SMB_CONNECTED);
+ *done = true;
+ break;
+
+ default:
+ smb_pop_message(conn);
+ return CURLE_OK; /* ignore */
+ }
+
+ smb_pop_message(conn);
+
+ return CURLE_OK;
+}
+
+static CURLcode smb_request_state(struct connectdata *conn, bool *done)
+{
+ struct smb_request *req = conn->data->req.protop;
+ struct smb_header *h;
+ enum smb_req_state next_state = SMB_DONE;
+ unsigned short len;
+ unsigned short off;
+ CURLcode result;
+ void *msg = NULL;
+
+ /* Start the request */
+ if(req->state == SMB_REQUESTING) {
+ result = smb_send_tree_connect(conn);
+ if(result) {
+ connclose(conn, "SMB: failed to send tree connect message");
+ return result;
+ }
+
+ request_state(conn, SMB_TREE_CONNECT);
+ }
+
+ /* Send the previous message and check for a response */
+ result = smb_send_and_recv(conn, &msg);
+ if(result && result != CURLE_AGAIN) {
+ connclose(conn, "SMB: failed to communicate");
+ return result;
+ }
+
+ if(!msg)
+ return CURLE_OK;
+
+ h = msg;
+
+ switch(req->state) {
+ case SMB_TREE_CONNECT:
+ if(h->status) {
+ req->result = CURLE_REMOTE_FILE_NOT_FOUND;
+ if(h->status == smb_swap32(SMB_ERR_NOACCESS))
+ req->result = CURLE_REMOTE_ACCESS_DENIED;
+ break;
+ }
+ req->tid = smb_swap16(h->tid);
+ next_state = SMB_OPEN;
+ break;
+
+ case SMB_OPEN:
+ if(h->status) {
+ req->result = CURLE_REMOTE_FILE_NOT_FOUND;
+ next_state = SMB_TREE_DISCONNECT;
+ break;
+ }
+ req->fid = smb_swap16(((struct smb_nt_create_response *)msg)->fid);
+ conn->data->req.offset = 0;
+ if(conn->data->set.upload) {
+ conn->data->req.size = conn->data->state.infilesize;
+ Curl_pgrsSetUploadSize(conn->data, conn->data->req.size);
+ next_state = SMB_UPLOAD;
+ }
+ else {
+ conn->data->req.size =
+ smb_swap64(((struct smb_nt_create_response *)msg)->end_of_file);
+ Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
+ next_state = SMB_DOWNLOAD;
+ }
+ break;
+
+ case SMB_DOWNLOAD:
+ if(h->status) {
+ req->result = CURLE_RECV_ERROR;
+ next_state = SMB_CLOSE;
+ break;
+ }
+ len = Curl_read16_le(((unsigned char *) msg) +
+ sizeof(struct smb_header) + 11);
+ off = Curl_read16_le(((unsigned char *) msg) +
+ sizeof(struct smb_header) + 13);
+ if(len > 0) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ (char *)msg + off + sizeof(unsigned int),
+ len);
+ if(result) {
+ req->result = result;
+ next_state = SMB_CLOSE;
+ break;
+ }
+ }
+ conn->data->req.bytecount += len;
+ conn->data->req.offset += len;
+ Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount);
+ next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
+ break;
+
+ case SMB_UPLOAD:
+ if(h->status) {
+ req->result = CURLE_UPLOAD_FAILED;
+ next_state = SMB_CLOSE;
+ break;
+ }
+ len = Curl_read16_le(((unsigned char *) msg) +
+ sizeof(struct smb_header) + 5);
+ conn->data->req.bytecount += len;
+ conn->data->req.offset += len;
+ Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount);
+ if(conn->data->req.bytecount >= conn->data->req.size)
+ next_state = SMB_CLOSE;
+ else
+ next_state = SMB_UPLOAD;
+ break;
+
+ case SMB_CLOSE:
+ /* We don't care if the close failed, proceed to tree disconnect anyway */
+ next_state = SMB_TREE_DISCONNECT;
+ break;
+
+ case SMB_TREE_DISCONNECT:
+ next_state = SMB_DONE;
+ break;
+
+ default:
+ smb_pop_message(conn);
+ return CURLE_OK; /* ignore */
+ }
+
+ smb_pop_message(conn);
+
+ switch(next_state) {
+ case SMB_OPEN:
+ result = smb_send_open(conn);
+ break;
+
+ case SMB_DOWNLOAD:
+ result = smb_send_read(conn);
+ break;
+
+ case SMB_UPLOAD:
+ result = smb_send_write(conn);
+ break;
+
+ case SMB_CLOSE:
+ result = smb_send_close(conn);
+ break;
+
+ case SMB_TREE_DISCONNECT:
+ result = smb_send_tree_disconnect(conn);
+ break;
+
+ case SMB_DONE:
+ result = req->result;
+ *done = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if(result) {
+ connclose(conn, "SMB: failed to send message");
+ return result;
+ }
+
+ request_state(conn, next_state);
+
+ return CURLE_OK;
+}
+
+static CURLcode smb_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ struct smb_request *req = conn->data->req.protop;
+
+ (void) premature;
+
+ Curl_safefree(req->share);
+ Curl_safefree(conn->data->req.protop);
+
+ return status;
+}
+
+static CURLcode smb_disconnect(struct connectdata *conn, bool dead)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_request *req = conn->data->req.protop;
+
+ (void) dead;
+
+ Curl_safefree(smbc->domain);
+ Curl_safefree(smbc->recv_buf);
+
+ /* smb_done is not always called, so cleanup the request */
+ if(req) {
+ Curl_safefree(req->share);
+ Curl_safefree(conn->data->req.protop);
+ }
+
+ return CURLE_OK;
+}
+
+static int smb_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ socks[0] = conn->sock[FIRSTSOCKET];
+
+ if(smbc->send_size || smbc->upload_size)
+ return GETSOCK_WRITESOCK(0);
+
+ return GETSOCK_READSOCK(0);
+}
+
+static CURLcode smb_parse_url_path(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smb_request *req = data->req.protop;
+ char *path;
+ char *slash;
+
+ /* URL decode the path */
+ result = Curl_urldecode(data, data->state.path, 0, &path, NULL, TRUE);
+ if(result)
+ return result;
+
+ /* Parse the path for the share */
+ req->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path);
+ if(!req->share) {
+ free(path);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ slash = strchr(req->share, '/');
+ if(!slash)
+ slash = strchr(req->share, '\\');
+
+ /* The share must be present */
+ if(!slash) {
+ free(path);
+
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Parse the path for the file path converting any forward slashes into
+ backslashes */
+ *slash++ = 0;
+ req->path = slash;
+ for(; *slash; slash++) {
+ if(*slash == '/')
+ *slash = '\\';
+ }
+
+ free(path);
+
+ return CURLE_OK;
+}
+
+#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
+
+#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */
diff --git a/libcurl/src/lib/smb.h b/libcurl/src/lib/smb.h
new file mode 100644
index 0000000..7852fa1
--- /dev/null
+++ b/libcurl/src/lib/smb.h
@@ -0,0 +1,271 @@
+#ifndef HEADER_CURL_SMB_H
+#define HEADER_CURL_SMB_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+enum smb_conn_state {
+ SMB_NOT_CONNECTED = 0,
+ SMB_CONNECTING,
+ SMB_NEGOTIATE,
+ SMB_SETUP,
+ SMB_CONNECTED
+};
+
+struct smb_conn {
+ enum smb_conn_state state;
+ char *user;
+ char *domain;
+ unsigned char challenge[8];
+ unsigned int session_key;
+ unsigned short uid;
+ char *recv_buf;
+ size_t upload_size;
+ size_t send_size;
+ size_t sent;
+ size_t got;
+};
+
+/*
+ * Definitions for SMB protocol data structures
+ */
+#ifdef BUILDING_CURL_SMB_C
+
+#if defined(_MSC_VER) || defined(__ILEC400__)
+# define PACK
+# pragma pack(push)
+# pragma pack(1)
+#elif defined(__GNUC__)
+# define PACK __attribute__((packed))
+#else
+# define PACK
+#endif
+
+#define SMB_COM_CLOSE 0x04
+#define SMB_COM_READ_ANDX 0x2e
+#define SMB_COM_WRITE_ANDX 0x2f
+#define SMB_COM_TREE_DISCONNECT 0x71
+#define SMB_COM_NEGOTIATE 0x72
+#define SMB_COM_SETUP_ANDX 0x73
+#define SMB_COM_TREE_CONNECT_ANDX 0x75
+#define SMB_COM_NT_CREATE_ANDX 0xa2
+#define SMB_COM_NO_ANDX_COMMAND 0xff
+
+#define SMB_WC_CLOSE 0x03
+#define SMB_WC_READ_ANDX 0x0c
+#define SMB_WC_WRITE_ANDX 0x0e
+#define SMB_WC_SETUP_ANDX 0x0d
+#define SMB_WC_TREE_CONNECT_ANDX 0x04
+#define SMB_WC_NT_CREATE_ANDX 0x18
+
+#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10
+#define SMB_FLAGS_CASELESS_PATHNAMES 0x08
+#define SMB_FLAGS2_UNICODE_STRINGS 0x8000
+#define SMB_FLAGS2_IS_LONG_NAME 0x0040
+#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001
+
+#define SMB_CAP_LARGE_FILES 0x08
+#define SMB_GENERIC_WRITE 0x40000000
+#define SMB_GENERIC_READ 0x80000000
+#define SMB_FILE_SHARE_ALL 0x07
+#define SMB_FILE_OPEN 0x01
+#define SMB_FILE_OVERWRITE_IF 0x05
+
+#define SMB_ERR_NOACCESS 0x00050001
+
+struct smb_header {
+ unsigned char nbt_type;
+ unsigned char nbt_flags;
+ unsigned short nbt_length;
+ unsigned char magic[4];
+ unsigned char command;
+ unsigned int status;
+ unsigned char flags;
+ unsigned short flags2;
+ unsigned short pid_high;
+ unsigned char signature[8];
+ unsigned short pad;
+ unsigned short tid;
+ unsigned short pid;
+ unsigned short uid;
+ unsigned short mid;
+} PACK;
+
+struct smb_negotiate_response {
+ struct smb_header h;
+ unsigned char word_count;
+ unsigned short dialect_index;
+ unsigned char security_mode;
+ unsigned short max_mpx_count;
+ unsigned short max_number_vcs;
+ unsigned int max_buffer_size;
+ unsigned int max_raw_size;
+ unsigned int session_key;
+ unsigned int capabilities;
+ unsigned int system_time_low;
+ unsigned int system_time_high;
+ unsigned short server_time_zone;
+ unsigned char encryption_key_length;
+ unsigned short byte_count;
+ char bytes[1];
+} PACK;
+
+struct andx {
+ unsigned char command;
+ unsigned char pad;
+ unsigned short offset;
+} PACK;
+
+struct smb_setup {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short max_buffer_size;
+ unsigned short max_mpx_count;
+ unsigned short vc_number;
+ unsigned int session_key;
+ unsigned short lengths[2];
+ unsigned int pad;
+ unsigned int capabilities;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_tree_connect {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short flags;
+ unsigned short pw_len;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_nt_create {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned char pad;
+ unsigned short name_length;
+ unsigned int flags;
+ unsigned int root_fid;
+ unsigned int access;
+#ifdef HAVE_LONGLONG
+ unsigned long long allocation_size;
+#else
+ unsigned __int64 allocation_size;
+#endif
+ unsigned int ext_file_attributes;
+ unsigned int share_access;
+ unsigned int create_disposition;
+ unsigned int create_options;
+ unsigned int impersonation_level;
+ unsigned char security_flags;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_nt_create_response {
+ struct smb_header h;
+ unsigned char word_count;
+ struct andx andx;
+ unsigned char op_lock_level;
+ unsigned short fid;
+ unsigned int create_disposition;
+#ifdef HAVE_LONGLONG
+ unsigned long long create_time;
+ unsigned long long last_access_time;
+ unsigned long long last_write_time;
+ unsigned long long last_change_time;
+#else
+ unsigned __int64 create_time;
+ unsigned __int64 last_access_time;
+ unsigned __int64 last_write_time;
+ unsigned __int64 last_change_time;
+#endif
+ unsigned int ext_file_attributes;
+#ifdef HAVE_LONGLONG
+ unsigned long long allocation_size;
+ unsigned long long end_of_file;
+#else
+ unsigned __int64 allocation_size;
+ unsigned __int64 end_of_file;
+#endif
+} PACK;
+
+struct smb_read {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short fid;
+ unsigned int offset;
+ unsigned short max_bytes;
+ unsigned short min_bytes;
+ unsigned int timeout;
+ unsigned short remaining;
+ unsigned int offset_high;
+ unsigned short byte_count;
+} PACK;
+
+struct smb_write {
+ struct smb_header h;
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short fid;
+ unsigned int offset;
+ unsigned int timeout;
+ unsigned short write_mode;
+ unsigned short remaining;
+ unsigned short pad;
+ unsigned short data_length;
+ unsigned short data_offset;
+ unsigned int offset_high;
+ unsigned short byte_count;
+ unsigned char pad2;
+} PACK;
+
+struct smb_close {
+ unsigned char word_count;
+ unsigned short fid;
+ unsigned int last_mtime;
+ unsigned short byte_count;
+} PACK;
+
+struct smb_tree_disconnect {
+ unsigned char word_count;
+ unsigned short byte_count;
+} PACK;
+
+#if defined(_MSC_VER) || defined(__ILEC400__)
+# pragma pack(pop)
+#endif
+
+#endif /* BUILDING_CURL_SMB_C */
+
+#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4)
+
+#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
+
+extern const struct Curl_handler Curl_handler_smb;
+extern const struct Curl_handler Curl_handler_smbs;
+
+#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
+
+#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */
+
+#endif /* HEADER_CURL_SMB_H */
diff --git a/libcurl/src/lib/smtp.c b/libcurl/src/lib/smtp.c
new file mode 100644
index 0000000..e827a0e
--- /dev/null
+++ b/libcurl/src/lib/smtp.c
@@ -0,0 +1,1671 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC1870 SMTP Service Extension for Message Size
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC3207 SMTP over TLS
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ * RFC4954 SMTP Authentication
+ * RFC5321 SMTP protocol
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft SMTP URL Interface <draft-earhart-url-smtp-00.txt>
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_SMTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "smtp.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "select.h"
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "curl_gethostname.h"
+#include "curl_sasl.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local API functions */
+static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done);
+static CURLcode smtp_do(struct connectdata *conn, bool *done);
+static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+ bool premature);
+static CURLcode smtp_connect(struct connectdata *conn, bool *done);
+static CURLcode smtp_disconnect(struct connectdata *conn, bool dead);
+static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done);
+static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
+static CURLcode smtp_setup_connection(struct connectdata *conn);
+static CURLcode smtp_parse_url_options(struct connectdata *conn);
+static CURLcode smtp_parse_url_path(struct connectdata *conn);
+static CURLcode smtp_parse_custom_request(struct connectdata *conn);
+static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech,
+ const char *initresp);
+static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp);
+static void smtp_get_message(char *buffer, char** outptr);
+
+/*
+ * SMTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_smtp = {
+ "SMTP", /* scheme */
+ smtp_setup_connection, /* setup_connection */
+ smtp_do, /* do_it */
+ smtp_done, /* done */
+ ZERO_NULL, /* do_more */
+ smtp_connect, /* connect_it */
+ smtp_multi_statemach, /* connecting */
+ smtp_doing, /* doing */
+ smtp_getsock, /* proto_getsock */
+ smtp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ smtp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTP, /* defport */
+ CURLPROTO_SMTP, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * SMTPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_smtps = {
+ "SMTPS", /* scheme */
+ smtp_setup_connection, /* setup_connection */
+ smtp_do, /* do_it */
+ smtp_done, /* done */
+ ZERO_NULL, /* do_more */
+ smtp_connect, /* connect_it */
+ smtp_multi_statemach, /* connecting */
+ smtp_doing, /* doing */
+ smtp_getsock, /* proto_getsock */
+ smtp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ smtp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTPS, /* defport */
+ CURLPROTO_SMTPS, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL
+ | PROTOPT_NOURLQUERY /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed SMTP protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_smtp_proxy = {
+ "SMTP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed SMTPS protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_smtps_proxy = {
+ "SMTPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTPS, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+/* SASL parameters for the smtp protocol */
+static const struct SASLproto saslsmtp = {
+ "smtp", /* The service name */
+ 334, /* Code received when continuation is expected */
+ 235, /* Code to receive upon authentication success */
+ 512 - 8, /* Maximum initial response length (no max) */
+ smtp_perform_auth, /* Send authentication command */
+ smtp_continue_auth, /* Send authentication continuation */
+ smtp_get_message /* Get SASL response message */
+};
+
+#ifdef USE_SSL
+static void smtp_to_smtps(struct connectdata *conn)
+{
+ conn->handler = &Curl_handler_smtps;
+}
+#else
+#define smtp_to_smtps(x) Curl_nop_stmt
+#endif
+
+/***********************************************************************
+ *
+ * smtp_endofresp()
+ *
+ * Checks for an ending SMTP status code at the start of the given string, but
+ * also detects various capabilities from the EHLO response including the
+ * supported authentication mechanisms.
+ */
+static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *resp)
+{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ bool result = FALSE;
+
+ /* Nothing for us */
+ if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
+ return FALSE;
+
+ /* Do we have a command response? This should be the response code followed
+ by a space and optionally some text as per RFC-5321 and as outlined in
+ Section 4. Examples of RFC-4954 but some e-mail servers ignore this and
+ only send the response code instead as per Section 4.2. */
+ if(line[3] == ' ' || len == 5) {
+ result = TRUE;
+ *resp = curlx_sltosi(strtol(line, NULL, 10));
+
+ /* Make sure real server never sends internal value */
+ if(*resp == 1)
+ *resp = 0;
+ }
+ /* Do we have a multiline (continuation) response? */
+ else if(line[3] == '-' &&
+ (smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) {
+ result = TRUE;
+ *resp = 1; /* Internal response code */
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_get_message()
+ *
+ * Gets the authentication message from the response buffer.
+ */
+static void smtp_get_message(char *buffer, char** outptr)
+{
+ size_t len = 0;
+ char* message = NULL;
+
+ /* Find the start of the message */
+ for(message = buffer + 4; *message == ' ' || *message == '\t'; message++)
+ ;
+
+ /* Find the end of the message */
+ for(len = strlen(message); len--;)
+ if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+ message[len] != '\t')
+ break;
+
+ /* Terminate the message */
+ if(++len) {
+ message[len] = '\0';
+ }
+
+ *outptr = message;
+}
+
+/***********************************************************************
+ *
+ * state()
+ *
+ * This is the ONLY way to change SMTP state!
+ */
+static void state(struct connectdata *conn, smtpstate newstate)
+{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[] = {
+ "STOP",
+ "SERVERGREET",
+ "EHLO",
+ "HELO",
+ "STARTTLS",
+ "UPGRADETLS",
+ "AUTH",
+ "COMMAND",
+ "MAIL",
+ "RCPT",
+ "DATA",
+ "POSTDATA",
+ "QUIT",
+ /* LAST */
+ };
+
+ if(smtpc->state != newstate)
+ infof(conn->data, "SMTP %p state change from %s to %s\n",
+ (void *)smtpc, names[smtpc->state], names[newstate]);
+#endif
+
+ smtpc->state = newstate;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_ehlo()
+ *
+ * Sends the EHLO command to not only initialise communication with the ESMTP
+ * server but to also obtain a list of server side supported capabilities.
+ */
+static CURLcode smtp_perform_ehlo(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */
+ smtpc->sasl.authused = SASL_AUTH_NONE; /* Clear the authentication mechanism
+ used for esmtp connections */
+ smtpc->tls_supported = FALSE; /* Clear the TLS capability */
+ smtpc->auth_supported = FALSE; /* Clear the AUTH capability */
+
+ /* Send the EHLO command */
+ result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain);
+
+ if(!result)
+ state(conn, SMTP_EHLO);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_helo()
+ *
+ * Sends the HELO command to initialise communication with the SMTP server.
+ */
+static CURLcode smtp_perform_helo(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ smtpc->sasl.authused = SASL_AUTH_NONE; /* No authentication mechanism used
+ in smtp connections */
+
+ /* Send the HELO command */
+ result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain);
+
+ if(!result)
+ state(conn, SMTP_HELO);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_starttls()
+ *
+ * Sends the STLS command to start the upgrade to TLS.
+ */
+static CURLcode smtp_perform_starttls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the STARTTLS command */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS");
+
+ if(!result)
+ state(conn, SMTP_STARTTLS);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_upgrade_tls()
+ *
+ * Performs the upgrade to TLS.
+ */
+static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ /* Start the SSL connection */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
+
+ if(!result) {
+ if(smtpc->state != SMTP_UPGRADETLS)
+ state(conn, SMTP_UPGRADETLS);
+
+ if(smtpc->ssldone) {
+ smtp_to_smtps(conn);
+ result = smtp_perform_ehlo(conn);
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_auth()
+ *
+ * Sends an AUTH command allowing the client to login with the given SASL
+ * authentication mechanism.
+ */
+static CURLcode smtp_perform_auth(struct connectdata *conn,
+ const char *mech,
+ const char *initresp)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ if(initresp) { /* AUTH <mech> ...<crlf> */
+ /* Send the AUTH command with the initial response */
+ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
+ }
+ else {
+ /* Send the AUTH command */
+ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_continue_auth()
+ *
+ * Sends SASL continuation data or cancellation.
+ */
+static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp)
+{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ return Curl_pp_sendf(&smtpc->pp, "%s", resp);
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_authentication()
+ *
+ * Initiates the authentication sequence, with the appropriate SASL
+ * authentication mechanism.
+ */
+static CURLcode smtp_perform_authentication(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ saslprogress progress;
+
+ /* Check we have enough data to authenticate with, and the
+ server supports authentiation, and end the connect phase if not */
+ if(!smtpc->auth_supported ||
+ !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) {
+ state(conn, SMTP_STOP);
+ return result;
+ }
+
+ /* Calculate the SASL login details */
+ result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress);
+
+ if(!result) {
+ if(progress == SASL_INPROGRESS)
+ state(conn, SMTP_AUTH);
+ else {
+ /* Other mechanisms not supported */
+ infof(conn->data, "No known authentication mechanisms supported!\n");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_command()
+ *
+ * Sends a SMTP based command.
+ */
+static CURLcode smtp_perform_command(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ /* Send the command */
+ if(smtp->rcpt)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s",
+ smtp->custom && smtp->custom[0] != '\0' ?
+ smtp->custom : "VRFY",
+ smtp->rcpt->data);
+ else
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s",
+ smtp->custom && smtp->custom[0] != '\0' ?
+ smtp->custom : "HELP");
+
+ if(!result)
+ state(conn, SMTP_COMMAND);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_mail()
+ *
+ * Sends an MAIL command to initiate the upload of a message.
+ */
+static CURLcode smtp_perform_mail(struct connectdata *conn)
+{
+ char *from = NULL;
+ char *auth = NULL;
+ char *size = NULL;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ /* Calculate the FROM parameter */
+ if(!data->set.str[STRING_MAIL_FROM])
+ /* Null reverse-path, RFC-5321, sect. 3.6.3 */
+ from = strdup("<>");
+ else if(data->set.str[STRING_MAIL_FROM][0] == '<')
+ from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
+ else
+ from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
+
+ if(!from)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Calculate the optional AUTH parameter */
+ if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) {
+ if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
+ auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
+ else
+ /* Empty AUTH, RFC-2554, sect. 5 */
+ auth = strdup("<>");
+
+ if(!auth) {
+ free(from);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Calculate the optional SIZE parameter */
+ if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) {
+ size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
+
+ if(!size) {
+ free(from);
+ free(auth);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Send the MAIL command */
+ if(!auth && !size)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s", from);
+ else if(auth && !size)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s AUTH=%s", from, auth);
+ else if(auth && size)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
+ else
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s SIZE=%s", from, size);
+
+ free(from);
+ free(auth);
+ free(size);
+
+ if(!result)
+ state(conn, SMTP_MAIL);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_rcpt_to()
+ *
+ * Sends a RCPT TO command for a given recipient as part of the message upload
+ * process.
+ */
+static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ /* Send the RCPT TO command */
+ if(smtp->rcpt->data[0] == '<')
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
+ smtp->rcpt->data);
+ else
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
+ smtp->rcpt->data);
+ if(!result)
+ state(conn, SMTP_RCPT);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_quit()
+ *
+ * Performs the quit action prior to sclose() being called.
+ */
+static CURLcode smtp_perform_quit(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the QUIT command */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT");
+
+ if(!result)
+ state(conn, SMTP_QUIT);
+
+ return result;
+}
+
+/* For the initial server greeting */
+static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "Got unexpected smtp-server response: %d", smtpcode);
+ result = CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+ else
+ result = smtp_perform_ehlo(conn);
+
+ return result;
+}
+
+/* For STARTTLS responses */
+static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 220) {
+ if(data->set.use_ssl != CURLUSESSL_TRY) {
+ failf(data, "STARTTLS denied. %c", smtpcode);
+ result = CURLE_USE_SSL_FAILED;
+ }
+ else
+ result = smtp_perform_authentication(conn);
+ }
+ else
+ result = smtp_perform_upgrade_tls(conn);
+
+ return result;
+}
+
+/* For EHLO responses */
+static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *line = data->state.buffer;
+ size_t len = strlen(line);
+ size_t wordlen;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2 && smtpcode != 1) {
+ if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use)
+ result = smtp_perform_helo(conn);
+ else {
+ failf(data, "Remote access denied: %d", smtpcode);
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ }
+ }
+ else {
+ line += 4;
+ len -= 4;
+
+ /* Does the server support the STARTTLS capability? */
+ if(len >= 8 && !memcmp(line, "STARTTLS", 8))
+ smtpc->tls_supported = TRUE;
+
+ /* Does the server support the SIZE capability? */
+ else if(len >= 4 && !memcmp(line, "SIZE", 4))
+ smtpc->size_supported = TRUE;
+
+ /* Does the server support authentication? */
+ else if(len >= 5 && !memcmp(line, "AUTH ", 5)) {
+ smtpc->auth_supported = TRUE;
+
+ /* Advance past the AUTH keyword */
+ line += 5;
+ len -= 5;
+
+ /* Loop through the data line */
+ for(;;) {
+ size_t llen;
+ unsigned int mechbit;
+
+ while(len &&
+ (*line == ' ' || *line == '\t' ||
+ *line == '\r' || *line == '\n')) {
+
+ line++;
+ len--;
+ }
+
+ if(!len)
+ break;
+
+ /* Extract the word */
+ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
+ line[wordlen] != '\t' && line[wordlen] != '\r' &&
+ line[wordlen] != '\n';)
+ wordlen++;
+
+ /* Test the word for a matching authentication mechanism */
+ if((mechbit = Curl_sasl_decode_mech(line, wordlen, &llen)) &&
+ llen == wordlen)
+ smtpc->sasl.authmechs |= mechbit;
+
+ line += wordlen;
+ len -= wordlen;
+ }
+ }
+
+ if(smtpcode != 1) {
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but SSL is requested */
+ if(smtpc->tls_supported)
+ /* Switch to TLS connection now */
+ result = smtp_perform_starttls(conn);
+ else if(data->set.use_ssl == CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = smtp_perform_authentication(conn);
+ else {
+ failf(data, "STARTTLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
+ }
+ else
+ result = smtp_perform_authentication(conn);
+ }
+ }
+
+ return result;
+}
+
+/* For HELO responses */
+static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "Remote access denied: %d", smtpcode);
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, SMTP_STOP);
+
+ return result;
+}
+
+/* For SASL authentication responses */
+static CURLcode smtp_state_auth_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ saslprogress progress;
+
+ (void)instate; /* no use for this yet */
+
+ result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress);
+ if(!result)
+ switch(progress) {
+ case SASL_DONE:
+ state(conn, SMTP_STOP); /* Authenticated */
+ break;
+ case SASL_IDLE: /* No mechanism left after cancellation */
+ failf(data, "Authentication cancelled");
+ result = CURLE_LOGIN_DENIED;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+/* For command responses */
+static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+ char *line = data->state.buffer;
+ size_t len = strlen(line);
+
+ (void)instate; /* no use for this yet */
+
+ if((smtp->rcpt && smtpcode/100 != 2 && smtpcode != 553 && smtpcode != 1) ||
+ (!smtp->rcpt && smtpcode/100 != 2 && smtpcode != 1)) {
+ failf(data, "Command failed: %d", smtpcode);
+ result = CURLE_RECV_ERROR;
+ }
+ else {
+ /* Temporarily add the LF character back and send as body to the client */
+ if(!data->set.opt_no_body) {
+ line[len] = '\n';
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ line[len] = '\0';
+ }
+
+ if(smtpcode != 1) {
+ if(smtp->rcpt) {
+ smtp->rcpt = smtp->rcpt->next;
+
+ if(smtp->rcpt) {
+ /* Send the next command */
+ result = smtp_perform_command(conn);
+ }
+ else
+ /* End of DO phase */
+ state(conn, SMTP_STOP);
+ }
+ else
+ /* End of DO phase */
+ state(conn, SMTP_STOP);
+ }
+ }
+
+ return result;
+}
+
+/* For MAIL responses */
+static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "MAIL failed: %d", smtpcode);
+ result = CURLE_SEND_ERROR;
+ }
+ else
+ /* Start the RCPT TO command */
+ result = smtp_perform_rcpt_to(conn);
+
+ return result;
+}
+
+/* For RCPT responses */
+static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "RCPT failed: %d", smtpcode);
+ result = CURLE_SEND_ERROR;
+ }
+ else {
+ smtp->rcpt = smtp->rcpt->next;
+
+ if(smtp->rcpt)
+ /* Send the next RCPT TO command */
+ result = smtp_perform_rcpt_to(conn);
+ else {
+ /* Send the DATA command */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
+
+ if(!result)
+ state(conn, SMTP_DATA);
+ }
+ }
+
+ return result;
+}
+
+/* For DATA response */
+static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 354) {
+ failf(data, "DATA failed: %d", smtpcode);
+ result = CURLE_SEND_ERROR;
+ }
+ else {
+ /* Set the progress upload size */
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* SMTP upload */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+
+ /* End of DO phase */
+ state(conn, SMTP_STOP);
+ }
+
+ return result;
+}
+
+/* For POSTDATA responses, which are received after the entire DATA
+ part has been sent to the server */
+static CURLcode smtp_state_postdata_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 250)
+ result = CURLE_RECV_ERROR;
+
+ /* End of DONE phase */
+ state(conn, SMTP_STOP);
+
+ return result;
+}
+
+static CURLcode smtp_statemach_act(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ struct SessionHandle *data = conn->data;
+ int smtpcode;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct pingpong *pp = &smtpc->pp;
+ size_t nread = 0;
+
+ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
+ if(smtpc->state == SMTP_UPGRADETLS)
+ return smtp_perform_upgrade_tls(conn);
+
+ /* Flush any data that needs to be sent */
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ do {
+ /* Read the response from the server */
+ result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
+ if(result)
+ return result;
+
+ /* Store the latest response for later retrieval if necessary */
+ if(smtpc->state != SMTP_QUIT && smtpcode != 1)
+ data->info.httpcode = smtpcode;
+
+ if(!smtpcode)
+ break;
+
+ /* We have now received a full SMTP server response */
+ switch(smtpc->state) {
+ case SMTP_SERVERGREET:
+ result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_EHLO:
+ result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_HELO:
+ result = smtp_state_helo_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_STARTTLS:
+ result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH:
+ result = smtp_state_auth_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_COMMAND:
+ result = smtp_state_command_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_MAIL:
+ result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_RCPT:
+ result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_DATA:
+ result = smtp_state_data_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_POSTDATA:
+ result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, SMTP_STOP);
+ break;
+ }
+ } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
+
+ return result;
+}
+
+/* Called repeatedly until done from multi.c */
+static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
+ if(result || !smtpc->ssldone)
+ return result;
+ }
+
+ result = Curl_pp_statemach(&smtpc->pp, FALSE);
+ *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode smtp_block_statemach(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ while(smtpc->state != SMTP_STOP && !result)
+ result = Curl_pp_statemach(&smtpc->pp, TRUE);
+
+ return result;
+}
+
+/* Allocate and initialize the SMTP struct for the current SessionHandle if
+ required */
+static CURLcode smtp_init(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp;
+
+ smtp = data->req.protop = calloc(sizeof(struct SMTP), 1);
+ if(!smtp)
+ result = CURLE_OUT_OF_MEMORY;
+
+ return result;
+}
+
+/* For the SMTP "protocol connect" and "doing" phases only */
+static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.smtpc.pp, socks, numsocks);
+}
+
+/***********************************************************************
+ *
+ * smtp_connect()
+ *
+ * This function should do everything that is to be considered a part of
+ * the connection phase.
+ *
+ * The variable pointed to by 'done' will be TRUE if the protocol-layer
+ * connect phase is done when this function returns, or FALSE if not.
+ */
+static CURLcode smtp_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct pingpong *pp = &smtpc->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections in SMTP */
+ connkeep(conn, "SMTP default");
+
+ /* Set the default response time-out */
+ pp->response_time = RESP_TIMEOUT;
+ pp->statemach_act = smtp_statemach_act;
+ pp->endofresp = smtp_endofresp;
+ pp->conn = conn;
+
+ /* Initialize the SASL storage */
+ Curl_sasl_init(&smtpc->sasl, &saslsmtp);
+
+ /* Initialise the pingpong layer */
+ Curl_pp_init(pp);
+
+ /* Parse the URL options */
+ result = smtp_parse_url_options(conn);
+ if(result)
+ return result;
+
+ /* Parse the URL path */
+ result = smtp_parse_url_path(conn);
+ if(result)
+ return result;
+
+ /* Start off waiting for the server greeting response */
+ state(conn, SMTP_SERVERGREET);
+
+ result = smtp_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+ struct pingpong *pp = &conn->proto.smtpc.pp;
+ char *eob;
+ ssize_t len;
+ ssize_t bytes_written;
+
+ (void)premature;
+
+ if(!smtp || !pp->conn)
+ /* When the easy handle is removed from the multi interface while libcurl
+ is still trying to resolve the host name, the SMTP struct is not yet
+ initialized. However, the removal action calls Curl_done() which in
+ turn calls this function, so we simply return success. */
+ return CURLE_OK;
+
+ if(status) {
+ connclose(conn, "SMTP done with bad status"); /* marked for closure */
+ result = status; /* use the already set error code */
+ }
+ else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
+ /* Calculate the EOB taking into account any terminating CRLF from the
+ previous line of the email or the CRLF of the DATA command when there
+ is "no mail data". RFC-5321, sect. 4.1.1.4.
+
+ Note: As some SSL backends, such as OpenSSL, will cause Curl_write() to
+ fail when using a different pointer following a previous write, that
+ returned CURLE_AGAIN, we duplicate the EOB now rather than when the
+ bytes written doesn't equal len. */
+ if(smtp->trailing_crlf || !conn->data->state.infilesize) {
+ eob = strdup(SMTP_EOB + 2);
+ len = SMTP_EOB_LEN - 2;
+ }
+ else {
+ eob = strdup(SMTP_EOB);
+ len = SMTP_EOB_LEN;
+ }
+
+ if(!eob)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the end of block data */
+ result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
+ if(result) {
+ free(eob);
+ return result;
+ }
+
+ if(bytes_written != len) {
+ /* The whole chunk was not sent so keep it around and adjust the
+ pingpong structure accordingly */
+ pp->sendthis = eob;
+ pp->sendsize = len;
+ pp->sendleft = len - bytes_written;
+ }
+ else {
+ /* Successfully sent so adjust the response timeout relative to now */
+ pp->response = Curl_tvnow();
+
+ free(eob);
+ }
+
+ state(conn, SMTP_POSTDATA);
+
+ /* Run the state-machine
+
+ TODO: when the multi interface is used, this _really_ should be using
+ the smtp_multi_statemach function but we have no general support for
+ non-blocking DONE operations, not in the multi state machine and with
+ Curl_done() invokes on several places in the code!
+ */
+ result = smtp_block_statemach(conn);
+ }
+
+ /* Cleanup our per-request based variables */
+ Curl_safefree(smtp->custom);
+
+ /* Clear the transfer mode for the next request */
+ smtp->transfer = FTPTRANSFER_BODY;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform()
+ *
+ * This is the actual DO function for SMTP. Transfer a mail, send a command
+ * or get some data according to the options previously setup.
+ */
+static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
+ bool *dophase_done)
+{
+ /* This is SMTP and no proxy */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(data->set.opt_no_body) {
+ /* Requested no body means no transfer */
+ smtp->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* Store the first recipient (or NULL if not specified) */
+ smtp->rcpt = data->set.mail_rcpt;
+
+ /* Start the first command in the DO phase */
+ if(data->set.upload && data->set.mail_rcpt)
+ /* MAIL transfer */
+ result = smtp_perform_mail(conn);
+ else
+ /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */
+ result = smtp_perform_command(conn);
+
+ if(result)
+ return result;
+
+ /* Run the state-machine */
+ result = smtp_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (smtp_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode smtp_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+
+ *done = FALSE; /* default to false */
+
+ /* Parse the custom request */
+ result = smtp_parse_custom_request(conn);
+ if(result)
+ return result;
+
+ result = smtp_regular_transfer(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_disconnect()
+ *
+ * Disconnect from an SMTP server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to. */
+
+ /* The SMTP session may or may not have been allocated/setup at this
+ point! */
+ if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart)
+ if(!smtp_perform_quit(conn))
+ (void)smtp_block_statemach(conn); /* ignore errors on QUIT */
+
+ /* Disconnect from the server */
+ Curl_pp_disconnect(&smtpc->pp);
+
+ /* Cleanup the SASL module */
+ Curl_sasl_cleanup(conn, smtpc->sasl.authused);
+
+ /* Cleanup our connection based variables */
+ Curl_safefree(smtpc->domain);
+
+ return CURLE_OK;
+}
+
+/* Call this when the DO phase has completed */
+static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected)
+{
+ struct SMTP *smtp = conn->data->req.protop;
+
+ (void)connected;
+
+ if(smtp->transfer != FTPTRANSFER_BODY)
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ return CURLE_OK;
+}
+
+/* Called from multi.c while DOing */
+static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = smtp_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = smtp_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ */
+static CURLcode smtp_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ struct SessionHandle *data = conn->data;
+
+ /* Make sure size is unknown at this point */
+ data->req.size = -1;
+
+ /* Set the progress data */
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ /* Carry out the perform */
+ result = smtp_perform(conn, &connected, dophase_done);
+
+ /* Perform post DO phase operations if necessary */
+ if(!result && *dophase_done)
+ result = smtp_dophase_done(conn, connected);
+
+ return result;
+}
+
+static CURLcode smtp_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode result;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel SMTP operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_smtp)
+ conn->handler = &Curl_handler_smtp_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_smtps_proxy;
+#else
+ failf(data, "SMTPS not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+ /* set it up as a HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+
+#else
+ failf(data, "SMTP over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ /* Initialise the SMTP layer */
+ result = smtp_init(conn);
+ if(result)
+ return result;
+
+ data->state.path++; /* don't include the initial slash */
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * smtp_parse_url_options()
+ *
+ * Parse the URL login options.
+ */
+static CURLcode smtp_parse_url_options(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *ptr = conn->options;
+
+ smtpc->sasl.resetprefs = TRUE;
+
+ while(!result && ptr && *ptr) {
+ const char *key = ptr;
+ const char *value;
+
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ value = ptr + 1;
+
+ while(*ptr && *ptr != ';')
+ ptr++;
+
+ if(strnequal(key, "AUTH=", 5))
+ result = Curl_sasl_parse_url_auth_option(&smtpc->sasl,
+ value, ptr - value);
+ else
+ result = CURLE_URL_MALFORMAT;
+
+ if(*ptr == ';')
+ ptr++;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ */
+static CURLcode smtp_parse_url_path(struct connectdata *conn)
+{
+ /* The SMTP struct is already initialised in smtp_connect() */
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *path = data->state.path;
+ char localhost[HOSTNAME_MAX + 1];
+
+ /* Calculate the path if necessary */
+ if(!*path) {
+ if(!Curl_gethostname(localhost, sizeof(localhost)))
+ path = localhost;
+ else
+ path = "localhost";
+ }
+
+ /* URL decode the path and use it as the domain in our EHLO */
+ return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
+}
+
+/***********************************************************************
+ *
+ * smtp_parse_custom_request()
+ *
+ * Parse the custom request.
+ */
+static CURLcode smtp_parse_custom_request(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+ const char *custom = data->set.str[STRING_CUSTOMREQUEST];
+
+ /* URL decode the custom request */
+ if(custom)
+ result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
+
+ return result;
+}
+
+CURL_STATIC CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
+{
+ /* When sending a SMTP payload we must detect CRLF. sequences making sure
+ they are sent as CRLF.. instead, as a . on the beginning of a line will
+ be deleted by the server when not part of an EOB terminator and a
+ genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of
+ data by the server
+ */
+ ssize_t i;
+ ssize_t si;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+ char *scratch = data->state.scratch;
+ char *newscratch = NULL;
+ char *oldscratch = NULL;
+ size_t eob_sent;
+
+ /* Do we need to allocate a scratch buffer? */
+ if(!scratch || data->set.crlf) {
+ oldscratch = scratch;
+
+ scratch = newscratch = malloc(2 * BUFSIZE);
+ if(!newscratch) {
+ failf(data, "Failed to alloc scratch buffer!");
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Have we already sent part of the EOB? */
+ eob_sent = smtp->eob;
+
+ /* This loop can be improved by some kind of Boyer-Moore style of
+ approach but that is saved for later... */
+ for(i = 0, si = 0; i < nread; i++) {
+ if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) {
+ smtp->eob++;
+
+ /* Is the EOB potentially the terminating CRLF? */
+ if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob)
+ smtp->trailing_crlf = TRUE;
+ else
+ smtp->trailing_crlf = FALSE;
+ }
+ else if(smtp->eob) {
+ /* A previous substring matched so output that first */
+ memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent);
+ si += smtp->eob - eob_sent;
+
+ /* Then compare the first byte */
+ if(SMTP_EOB[0] == data->req.upload_fromhere[i])
+ smtp->eob = 1;
+ else
+ smtp->eob = 0;
+
+ eob_sent = 0;
+
+ /* Reset the trailing CRLF flag as there was more data */
+ smtp->trailing_crlf = FALSE;
+ }
+
+ /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */
+ if(SMTP_EOB_FIND_LEN == smtp->eob) {
+ /* Copy the replacement data to the target buffer */
+ memcpy(&scratch[si], &SMTP_EOB_REPL[eob_sent],
+ SMTP_EOB_REPL_LEN - eob_sent);
+ si += SMTP_EOB_REPL_LEN - eob_sent;
+ smtp->eob = 0;
+ eob_sent = 0;
+ }
+ else if(!smtp->eob)
+ scratch[si++] = data->req.upload_fromhere[i];
+ }
+
+ if(smtp->eob - eob_sent) {
+ /* A substring matched before processing ended so output that now */
+ memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent);
+ si += smtp->eob - eob_sent;
+ }
+
+ /* Only use the new buffer if we replaced something */
+ if(si != nread) {
+ /* Upload from the new (replaced) buffer instead */
+ data->req.upload_fromhere = scratch;
+
+ /* Save the buffer so it can be freed later */
+ data->state.scratch = scratch;
+
+ /* Free the old scratch buffer */
+ free(oldscratch);
+
+ /* Set the new amount too */
+ data->req.upload_present = si;
+ }
+ else
+ free(newscratch);
+
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_SMTP */
diff --git a/libcurl/src/lib/smtp.h b/libcurl/src/lib/smtp.h
new file mode 100644
index 0000000..360740a
--- /dev/null
+++ b/libcurl/src/lib/smtp.h
@@ -0,0 +1,91 @@
+#ifndef HEADER_CURL_SMTP_H
+#define HEADER_CURL_SMTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+#include "curl_sasl.h"
+
+/****************************************************************************
+ * SMTP unique setup
+ ***************************************************************************/
+typedef enum {
+ SMTP_STOP, /* do nothing state, stops the state machine */
+ SMTP_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ SMTP_EHLO,
+ SMTP_HELO,
+ SMTP_STARTTLS,
+ SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ SMTP_AUTH,
+ SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */
+ SMTP_MAIL, /* MAIL FROM */
+ SMTP_RCPT, /* RCPT TO */
+ SMTP_DATA,
+ SMTP_POSTDATA,
+ SMTP_QUIT,
+ SMTP_LAST /* never used */
+} smtpstate;
+
+/* This SMTP struct is used in the SessionHandle. All SMTP data that is
+ connection-oriented must be in smtp_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct SMTP {
+ curl_pp_transfer transfer;
+ char *custom; /* Custom Request */
+ struct curl_slist *rcpt; /* Recipient list */
+ size_t eob; /* Number of bytes of the EOB (End Of Body) that
+ have been received so far */
+ bool trailing_crlf; /* Specifies if the tailing CRLF is present */
+};
+
+/* smtp_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct smtp_conn {
+ struct pingpong pp;
+ smtpstate state; /* Always use smtp.c:state() to change state! */
+ bool ssldone; /* Is connect() over SSL done? */
+ char *domain; /* Client address/name to send in the EHLO */
+ struct SASL sasl; /* SASL-related storage */
+ bool tls_supported; /* StartTLS capability supported by server */
+ bool size_supported; /* If server supports SIZE extension according to
+ RFC 1870 */
+ bool auth_supported; /* AUTH capability supported by server */
+};
+
+extern const struct Curl_handler Curl_handler_smtp;
+extern const struct Curl_handler Curl_handler_smtps;
+
+/* this is the 5-bytes End-Of-Body marker for SMTP */
+#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a"
+#define SMTP_EOB_LEN 5
+#define SMTP_EOB_FIND_LEN 3
+
+/* if found in data, replace it with this string instead */
+#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
+#define SMTP_EOB_REPL_LEN 4
+
+CURL_STATIC CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread);
+
+#endif /* HEADER_CURL_SMTP_H */
diff --git a/libcurl/src/lib/sockaddr.h b/libcurl/src/lib/sockaddr.h
new file mode 100644
index 0000000..6a2151c
--- /dev/null
+++ b/libcurl/src/lib/sockaddr.h
@@ -0,0 +1,43 @@
+#ifndef HEADER_CURL_SOCKADDR_H
+#define HEADER_CURL_SOCKADDR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+struct Curl_sockaddr_storage {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sa_in;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 sa_in6;
+#endif
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE
+ struct sockaddr_storage sa_stor;
+#else
+ char cbuf[256]; /* this should be big enough to fit a lot */
+#endif
+ } buffer;
+};
+
+#endif /* HEADER_CURL_SOCKADDR_H */
+
diff --git a/libcurl/src/lib/socks.c b/libcurl/src/lib/socks.c
new file mode 100644
index 0000000..9dfe097
--- /dev/null
+++ b/libcurl/src/lib/socks.c
@@ -0,0 +1,755 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_PROXY)
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "strequal.h"
+#include "select.h"
+#include "connect.h"
+#include "timeval.h"
+#include "socks.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Helper read-from-socket functions. Does the same as Curl_read() but it
+ * blocks until all bytes amount of buffersize will be read. No more, no less.
+ *
+ * This is STUPID BLOCKING behaviour which we frown upon, but right now this
+ * is what we have...
+ */
+int Curl_blockread_all(struct connectdata *conn, /* connection data */
+ curl_socket_t sockfd, /* read from this socket */
+ char *buf, /* store read data here */
+ ssize_t buffersize, /* max amount to read */
+ ssize_t *n) /* amount bytes read */
+{
+ ssize_t nread;
+ ssize_t allread = 0;
+ int result;
+ long timeleft;
+ *n = 0;
+ for(;;) {
+ timeleft = Curl_timeleft(conn->data, NULL, TRUE);
+ if(timeleft < 0) {
+ /* we already got the timeout */
+ result = CURLE_OPERATION_TIMEDOUT;
+ break;
+ }
+ if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, timeleft) <= 0) {
+ result = ~CURLE_OK;
+ break;
+ }
+ result = Curl_read_plain(sockfd, buf, buffersize, &nread);
+ if(CURLE_AGAIN == result)
+ continue;
+ else if(result)
+ break;
+
+ if(buffersize == nread) {
+ allread += nread;
+ *n = allread;
+ result = CURLE_OK;
+ break;
+ }
+ if(!nread) {
+ result = ~CURLE_OK;
+ break;
+ }
+
+ buffersize -= nread;
+ buf += nread;
+ allread += nread;
+ }
+ return result;
+}
+
+/*
+* This function logs in to a SOCKS4 proxy and sends the specifics to the final
+* destination server.
+*
+* Reference :
+* http://socks.permeo.com/protocol/socks4.protocol
+*
+* Note :
+* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
+* Nonsupport "Identification Protocol (RFC1413)"
+*/
+CURL_STATIC CURLcode Curl_SOCKS4(const char *proxy_name,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn,
+ bool protocol4a)
+{
+#define SOCKS4REQLEN 262
+ unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
+ id */
+ int result;
+ CURLcode code;
+ curl_socket_t sock = conn->sock[sockindex];
+ struct SessionHandle *data = conn->data;
+
+ if(Curl_timeleft(data, NULL, TRUE) < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ (void)curlx_nonblock(sock, FALSE);
+
+ infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
+
+ /*
+ * Compose socks4 request
+ *
+ * Request format
+ *
+ * +----+----+----+----+----+----+----+----+----+----+....+----+
+ * | VN | CD | DSTPORT | DSTIP | USERID |NULL|
+ * +----+----+----+----+----+----+----+----+----+----+....+----+
+ * # of bytes: 1 1 2 4 variable 1
+ */
+
+ socksreq[0] = 4; /* version (SOCKS4) */
+ socksreq[1] = 1; /* connect */
+ socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
+ socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
+
+ /* DNS resolve only for SOCKS4, not SOCKS4a */
+ if(!protocol4a) {
+ struct Curl_dns_entry *dns;
+ Curl_addrinfo *hp=NULL;
+ int rc;
+
+ rc = Curl_resolv(conn, hostname, remote_port, &dns);
+
+ if(rc == CURLRESOLV_ERROR)
+ return CURLE_COULDNT_RESOLVE_PROXY;
+
+ if(rc == CURLRESOLV_PENDING)
+ /* ignores the return code, but 'dns' remains NULL on failure */
+ (void)Curl_resolver_wait_resolv(conn, &dns);
+
+ /*
+ * We cannot use 'hostent' as a struct that Curl_resolv() returns. It
+ * returns a Curl_addrinfo pointer that may not always look the same.
+ */
+ if(dns)
+ hp=dns->addr;
+ if(hp) {
+ char buf[64];
+ unsigned short ip[4];
+ Curl_printable_address(hp, buf, sizeof(buf));
+
+ if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
+ &ip[0], &ip[1], &ip[2], &ip[3])) {
+ /* Set DSTIP */
+ socksreq[4] = (unsigned char)ip[0];
+ socksreq[5] = (unsigned char)ip[1];
+ socksreq[6] = (unsigned char)ip[2];
+ socksreq[7] = (unsigned char)ip[3];
+ }
+ else
+ hp = NULL; /* fail! */
+
+ infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf);
+
+ Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+
+ }
+ if(!hp) {
+ failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
+ hostname);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+ }
+
+ /*
+ * This is currently not supporting "Identification Protocol (RFC1413)".
+ */
+ socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
+ if(proxy_name) {
+ size_t plen = strlen(proxy_name);
+ if(plen >= sizeof(socksreq) - 8) {
+ failf(data, "Too long SOCKS proxy name, can't use!\n");
+ return CURLE_COULDNT_CONNECT;
+ }
+ /* copy the proxy name WITH trailing zero */
+ memcpy(socksreq + 8, proxy_name, plen+1);
+ }
+
+ /*
+ * Make connection
+ */
+ {
+ ssize_t actualread;
+ ssize_t written;
+ ssize_t hostnamelen = 0;
+ int packetsize = 9 +
+ (int)strlen((char*)socksreq + 8); /* size including NUL */
+
+ /* If SOCKS4a, set special invalid IP address 0.0.0.x */
+ if(protocol4a) {
+ socksreq[4] = 0;
+ socksreq[5] = 0;
+ socksreq[6] = 0;
+ socksreq[7] = 1;
+ /* If still enough room in buffer, also append hostname */
+ hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
+ if(packetsize + hostnamelen <= SOCKS4REQLEN)
+ strcpy((char*)socksreq + packetsize, hostname);
+ else
+ hostnamelen = 0; /* Flag: hostname did not fit in buffer */
+ }
+
+ /* Send request */
+ code = Curl_write_plain(conn, sock, (char *)socksreq,
+ packetsize + hostnamelen,
+ &written);
+ if(code || (written != packetsize + hostnamelen)) {
+ failf(data, "Failed to send SOCKS4 connect request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(protocol4a && hostnamelen == 0) {
+ /* SOCKS4a with very long hostname - send that name separately */
+ hostnamelen = (ssize_t)strlen(hostname) + 1;
+ code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen,
+ &written);
+ if(code || (written != hostnamelen)) {
+ failf(data, "Failed to send SOCKS4 connect request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ packetsize = 8; /* receive data size */
+
+ /* Receive response */
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
+ &actualread);
+ if(result || (actualread != packetsize)) {
+ failf(data, "Failed to receive SOCKS4 connect request ack.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /*
+ * Response format
+ *
+ * +----+----+----+----+----+----+----+----+
+ * | VN | CD | DSTPORT | DSTIP |
+ * +----+----+----+----+----+----+----+----+
+ * # of bytes: 1 1 2 4
+ *
+ * VN is the version of the reply code and should be 0. CD is the result
+ * code with one of the following values:
+ *
+ * 90: request granted
+ * 91: request rejected or failed
+ * 92: request rejected because SOCKS server cannot connect to
+ * identd on the client
+ * 93: request rejected because the client program and identd
+ * report different user-ids
+ */
+
+ /* wrong version ? */
+ if(socksreq[0] != 0) {
+ failf(data,
+ "SOCKS4 reply has wrong version, version should be 4.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* Result */
+ switch(socksreq[1]) {
+ case 90:
+ infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":"");
+ break;
+ case 91:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", request rejected or failed.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ case 92:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", request rejected because SOCKS server cannot connect to "
+ "identd on the client.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ case 93:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", request rejected because the client program and identd "
+ "report different user-ids.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ default:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", Unknown.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ (void)curlx_nonblock(sock, TRUE);
+
+ return CURLE_OK; /* Proxy was successful! */
+}
+
+/*
+ * This function logs in to a SOCKS5 proxy and sends the specifics to the final
+ * destination server.
+ */
+CURLcode Curl_SOCKS5(const char *proxy_name,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn)
+{
+ /*
+ According to the RFC1928, section "6. Replies". This is what a SOCK5
+ replies:
+
+ +----+-----+-------+------+----------+----------+
+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+ +----+-----+-------+------+----------+----------+
+ | 1 | 1 | X'00' | 1 | Variable | 2 |
+ +----+-----+-------+------+----------+----------+
+
+ Where:
+
+ o VER protocol version: X'05'
+ o REP Reply field:
+ o X'00' succeeded
+ */
+
+ unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
+ ssize_t actualread;
+ ssize_t written;
+ int result;
+ CURLcode code;
+ curl_socket_t sock = conn->sock[sockindex];
+ struct SessionHandle *data = conn->data;
+ long timeout;
+ bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
+ const size_t hostname_len = strlen(hostname);
+ ssize_t len = 0;
+
+ /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
+ if(!socks5_resolve_local && hostname_len > 255) {
+ infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
+ "length > 255 [actual len=%zu]\n", hostname_len);
+ socks5_resolve_local = TRUE;
+ }
+
+ /* get timeout */
+ timeout = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ (void)curlx_nonblock(sock, TRUE);
+
+ /* wait until socket gets connected */
+ result = Curl_socket_ready(CURL_SOCKET_BAD, sock, timeout);
+
+ if(-1 == result) {
+ failf(conn->data, "SOCKS5: no connection here");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(0 == result) {
+ failf(conn->data, "SOCKS5: connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ if(result & CURL_CSELECT_ERR) {
+ failf(conn->data, "SOCKS5: error occurred during connection");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ socksreq[0] = 5; /* version */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ socksreq[1] = (char)(proxy_name ? 3 : 2); /* number of methods (below) */
+ socksreq[2] = 0; /* no authentication */
+ socksreq[3] = 1; /* GSS-API */
+ socksreq[4] = 2; /* username/password */
+#else
+ socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
+ socksreq[2] = 0; /* no authentication */
+ socksreq[3] = 2; /* username/password */
+#endif
+
+ (void)curlx_nonblock(sock, FALSE);
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
+ &written);
+ if(code || (written != (2 + (int)socksreq[1]))) {
+ failf(data, "Unable to send initial SOCKS5 request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ (void)curlx_nonblock(sock, TRUE);
+
+ result = Curl_socket_ready(sock, CURL_SOCKET_BAD, timeout);
+
+ if(-1 == result) {
+ failf(conn->data, "SOCKS5 nothing to read");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(0 == result) {
+ failf(conn->data, "SOCKS5 read timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ if(result & CURL_CSELECT_ERR) {
+ failf(conn->data, "SOCKS5 read error occurred");
+ return CURLE_RECV_ERROR;
+ }
+
+ (void)curlx_nonblock(sock, FALSE);
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ if(result || (actualread != 2)) {
+ failf(data, "Unable to receive initial SOCKS5 response.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[0] != 5) {
+ failf(data, "Received invalid version in initial SOCKS5 response.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(socksreq[1] == 0) {
+ /* Nothing to do, no authentication needed */
+ ;
+ }
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ else if(socksreq[1] == 1) {
+ code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
+ if(code) {
+ failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+#endif
+ else if(socksreq[1] == 2) {
+ /* Needs user name and password */
+ size_t proxy_name_len, proxy_password_len;
+ if(proxy_name && proxy_password) {
+ proxy_name_len = strlen(proxy_name);
+ proxy_password_len = strlen(proxy_password);
+ }
+ else {
+ proxy_name_len = 0;
+ proxy_password_len = 0;
+ }
+
+ /* username/password request looks like
+ * +----+------+----------+------+----------+
+ * |VER | ULEN | UNAME | PLEN | PASSWD |
+ * +----+------+----------+------+----------+
+ * | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+ * +----+------+----------+------+----------+
+ */
+ len = 0;
+ socksreq[len++] = 1; /* username/pw subnegotiation version */
+ socksreq[len++] = (unsigned char) proxy_name_len;
+ if(proxy_name && proxy_name_len)
+ memcpy(socksreq + len, proxy_name, proxy_name_len);
+ len += proxy_name_len;
+ socksreq[len++] = (unsigned char) proxy_password_len;
+ if(proxy_password && proxy_password_len)
+ memcpy(socksreq + len, proxy_password, proxy_password_len);
+ len += proxy_password_len;
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
+ if(code || (len != written)) {
+ failf(data, "Failed to send SOCKS5 sub-negotiation request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ if(result || (actualread != 2)) {
+ failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] != 0) { /* status */
+ failf(data, "User was rejected by the SOCKS5 server (%d %d).",
+ socksreq[0], socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* Everything is good so far, user was authenticated! */
+ }
+ else {
+ /* error */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(socksreq[1] == 255) {
+#else
+ if(socksreq[1] == 1) {
+ failf(data,
+ "SOCKS5 GSSAPI per-message authentication is not supported.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(socksreq[1] == 255) {
+#endif
+ if(!proxy_name || !*proxy_name) {
+ failf(data,
+ "No authentication method was acceptable. (It is quite likely"
+ " that the SOCKS5 server wanted a username/password, since none"
+ " was supplied to the server on this connection.)");
+ }
+ else {
+ failf(data, "No authentication method was acceptable.");
+ }
+ return CURLE_COULDNT_CONNECT;
+ }
+ else {
+ failf(data,
+ "Undocumented SOCKS5 mode attempted to be used by server.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ /* Authentication is complete, now specify destination to the proxy */
+ len = 0;
+ socksreq[len++] = 5; /* version (SOCKS5) */
+ socksreq[len++] = 1; /* connect */
+ socksreq[len++] = 0; /* must be zero */
+
+ if(!socks5_resolve_local) {
+ socksreq[len++] = 3; /* ATYP: domain name = 3 */
+ socksreq[len++] = (char) hostname_len; /* address length */
+ memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */
+ len += hostname_len;
+ }
+ else {
+ struct Curl_dns_entry *dns;
+ Curl_addrinfo *hp = NULL;
+ int rc = Curl_resolv(conn, hostname, remote_port, &dns);
+
+ if(rc == CURLRESOLV_ERROR)
+ return CURLE_COULDNT_RESOLVE_HOST;
+
+ if(rc == CURLRESOLV_PENDING) {
+ /* this requires that we're in "wait for resolve" state */
+ code = Curl_resolver_wait_resolv(conn, &dns);
+ if(code)
+ return code;
+ }
+
+ /*
+ * We cannot use 'hostent' as a struct that Curl_resolv() returns. It
+ * returns a Curl_addrinfo pointer that may not always look the same.
+ */
+ if(dns)
+ hp=dns->addr;
+ if(hp) {
+ struct sockaddr_in *saddr_in;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *saddr_in6;
+#endif
+ int i;
+
+ if(hp->ai_family == AF_INET) {
+ socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
+
+ saddr_in = (struct sockaddr_in*)hp->ai_addr;
+ for(i = 0; i < 4; i++) {
+ socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i];
+ infof(data, "%d\n", socksreq[len-1]);
+ }
+ }
+#ifdef ENABLE_IPV6
+ else if(hp->ai_family == AF_INET6) {
+ socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
+
+ saddr_in6 = (struct sockaddr_in6*)hp->ai_addr;
+ for(i = 0; i < 16; i++) {
+ socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i];
+ }
+ }
+#endif
+ else
+ hp = NULL; /* fail! */
+
+ Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+ }
+ if(!hp) {
+ failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
+ hostname);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+ }
+
+ socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
+ socksreq[len++] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(conn->socks5_gssapi_enctype) {
+ failf(data, "SOCKS5 GSS-API protection not yet implemented.");
+ }
+ else
+#endif
+ code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
+
+ if(code || (len != written)) {
+ failf(data, "Failed to send SOCKS5 connect request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ len = 10; /* minimum packet size is 10 */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(conn->socks5_gssapi_enctype) {
+ failf(data, "SOCKS5 GSS-API protection not yet implemented.");
+ }
+ else
+#endif
+ result = Curl_blockread_all(conn, sock, (char *)socksreq,
+ len, &actualread);
+
+ if(result || (len != actualread)) {
+ failf(data, "Failed to receive SOCKS5 connect request ack.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[0] != 5) { /* version */
+ failf(data,
+ "SOCKS5 reply has wrong version, version should be 5.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+ if(socksreq[3] == 1) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ }
+ else if(socksreq[3] == 3) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %s:%d. (%d)",
+ hostname,
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ }
+ else if(socksreq[3] == 4) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
+ "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ (unsigned char)socksreq[8], (unsigned char)socksreq[9],
+ (unsigned char)socksreq[10], (unsigned char)socksreq[11],
+ (unsigned char)socksreq[12], (unsigned char)socksreq[13],
+ (unsigned char)socksreq[14], (unsigned char)socksreq[15],
+ (unsigned char)socksreq[16], (unsigned char)socksreq[17],
+ (unsigned char)socksreq[18], (unsigned char)socksreq[19],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ }
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* Fix: in general, returned BND.ADDR is variable length parameter by RFC
+ 1928, so the reply packet should be read until the end to avoid errors at
+ subsequent protocol level.
+
+ +----+-----+-------+------+----------+----------+
+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+ +----+-----+-------+------+----------+----------+
+ | 1 | 1 | X'00' | 1 | Variable | 2 |
+ +----+-----+-------+------+----------+----------+
+
+ ATYP:
+ o IP v4 address: X'01', BND.ADDR = 4 byte
+ o domain name: X'03', BND.ADDR = [ 1 byte length, string ]
+ o IP v6 address: X'04', BND.ADDR = 16 byte
+ */
+
+ /* Calculate real packet size */
+ if(socksreq[3] == 3) {
+ /* domain name */
+ int addrlen = (int) socksreq[4];
+ len = 5 + addrlen + 2;
+ }
+ else if(socksreq[3] == 4) {
+ /* IPv6 */
+ len = 4 + 16 + 2;
+ }
+
+ /* At this point we already read first 10 bytes */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(!conn->socks5_gssapi_enctype) {
+ /* decrypt_gssapi_blockread already read the whole packet */
+#endif
+ if(len > 10) {
+ len -= 10;
+ result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
+ len, &actualread);
+ if(result || (len != actualread)) {
+ failf(data, "Failed to receive SOCKS5 connect request ack.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ }
+#endif
+
+ (void)curlx_nonblock(sock, TRUE);
+ return CURLE_OK; /* Proxy was successful! */
+}
+
+#endif /* CURL_DISABLE_PROXY */
+
diff --git a/libcurl/src/lib/socks.h b/libcurl/src/lib/socks.h
new file mode 100644
index 0000000..39fdfe6
--- /dev/null
+++ b/libcurl/src/lib/socks.h
@@ -0,0 +1,77 @@
+#ifndef HEADER_CURL_SOCKS_H
+#define HEADER_CURL_SOCKS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURL_DISABLE_PROXY
+#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#else
+/*
+ * Helper read-from-socket functions. Does the same as Curl_read() but it
+ * blocks until all bytes amount of buffersize will be read. No more, no less.
+ *
+ * This is STUPID BLOCKING behaviour which we frown upon, but right now this
+ * is what we have...
+ */
+CURL_STATIC int Curl_blockread_all(struct connectdata *conn,
+ curl_socket_t sockfd,
+ char *buf,
+ ssize_t buffersize,
+ ssize_t *n);
+
+/*
+ * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
+ * final destination server.
+ */
+CURL_STATIC CURLcode Curl_SOCKS4(const char *proxy_name,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn,
+ bool protocol4a);
+
+/*
+ * This function logs in to a SOCKS5 proxy and sends the specifics to the
+ * final destination server.
+ */
+CURL_STATIC CURLcode Curl_SOCKS5(const char *proxy_name,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn);
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+/*
+ * This function handles the SOCKS5 GSS-API negotiation and initialisation
+ */
+CURL_STATIC CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+ struct connectdata *conn);
+#endif
+
+#endif /* CURL_DISABLE_PROXY */
+
+#endif /* HEADER_CURL_SOCKS_H */
+
diff --git a/libcurl/src/lib/socks_gssapi.c b/libcurl/src/lib/socks_gssapi.c
new file mode 100644
index 0000000..fb30b23
--- /dev/null
+++ b/libcurl/src/lib/socks_gssapi.c
@@ -0,0 +1,522 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_PROXY)
+
+#include "curl_gssapi.h"
+#include "urldata.h"
+#include "sendf.h"
+#include "connect.h"
+#include "timeval.h"
+#include "socks.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
+
+/*
+ * Helper GSS-API error functions.
+ */
+static int check_gss_err(struct SessionHandle *data,
+ OM_uint32 major_status,
+ OM_uint32 minor_status,
+ const char* function)
+{
+ if(GSS_ERROR(major_status)) {
+ OM_uint32 maj_stat, min_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ char buf[1024];
+ size_t len;
+
+ len = 0;
+ msg_ctx = 0;
+ while(!msg_ctx) {
+ /* convert major status code (GSS-API error) to text */
+ maj_stat = gss_display_status(&min_stat, major_status,
+ GSS_C_GSS_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx, &status_string);
+ if(maj_stat == GSS_S_COMPLETE) {
+ if(sizeof(buf) > len + status_string.length + 1) {
+ strcpy(buf+len, (char*) status_string.value);
+ len += status_string.length;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ break;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ }
+ if(sizeof(buf) > len + 3) {
+ strcpy(buf+len, ".\n");
+ len += 2;
+ }
+ msg_ctx = 0;
+ while(!msg_ctx) {
+ /* convert minor status code (underlying routine error) to text */
+ maj_stat = gss_display_status(&min_stat, minor_status,
+ GSS_C_MECH_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx, &status_string);
+ if(maj_stat == GSS_S_COMPLETE) {
+ if(sizeof(buf) > len + status_string.length)
+ strcpy(buf+len, (char*) status_string.value);
+ gss_release_buffer(&min_stat, &status_string);
+ break;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ }
+ failf(data, "GSS-API error: %s failed:\n%s", function, buf);
+ return 1;
+ }
+
+ return 0;
+}
+
+CURL_STATIC CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+ struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sock = conn->sock[sockindex];
+ CURLcode code;
+ ssize_t actualread;
+ ssize_t written;
+ int result;
+ OM_uint32 gss_major_status, gss_minor_status, gss_status;
+ OM_uint32 gss_ret_flags;
+ int gss_conf_state, gss_enc;
+ gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc* gss_token = GSS_C_NO_BUFFER;
+ gss_name_t server = GSS_C_NO_NAME;
+ gss_name_t gss_client_name = GSS_C_NO_NAME;
+ unsigned short us_length;
+ char *user=NULL;
+ unsigned char socksreq[4]; /* room for GSS-API exchange header only */
+ char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
+
+ /* GSS-API request looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ /* prepare service name */
+ if(strchr(serviceptr, '/')) {
+ service.value = malloc(strlen(serviceptr));
+ if(!service.value)
+ return CURLE_OUT_OF_MEMORY;
+ service.length = strlen(serviceptr);
+ memcpy(service.value, serviceptr, service.length);
+
+ gss_major_status = gss_import_name(&gss_minor_status, &service,
+ (gss_OID) GSS_C_NULL_OID, &server);
+ }
+ else {
+ service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2);
+ if(!service.value)
+ return CURLE_OUT_OF_MEMORY;
+ service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1;
+ snprintf(service.value, service.length+1, "%s@%s",
+ serviceptr, conn->proxy.name);
+
+ gss_major_status = gss_import_name(&gss_minor_status, &service,
+ GSS_C_NT_HOSTBASED_SERVICE, &server);
+ }
+
+ gss_release_buffer(&gss_status, &service); /* clear allocated memory */
+
+ if(check_gss_err(data, gss_major_status,
+ gss_minor_status, "gss_import_name()")) {
+ failf(data, "Failed to create service name.");
+ gss_release_name(&gss_status, &server);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* As long as we need to keep sending some context info, and there's no */
+ /* errors, keep sending it... */
+ for(;;) {
+ gss_major_status = Curl_gss_init_sec_context(data,
+ &gss_minor_status,
+ &gss_context,
+ server,
+ &Curl_krb5_mech_oid,
+ NULL,
+ gss_token,
+ &gss_send_token,
+ TRUE,
+ &gss_ret_flags);
+
+ if(gss_token != GSS_C_NO_BUFFER)
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ if(check_gss_err(data, gss_major_status,
+ gss_minor_status, "gss_init_sec_context")) {
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ failf(data, "Failed to initial GSS-API token.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(gss_send_token.length != 0) {
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 1; /* authentication message type */
+ us_length = htons((short)gss_send_token.length);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if(code || (4 != written)) {
+ failf(data, "Failed to send GSS-API authentication request.");
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)gss_send_token.value,
+ gss_send_token.length, &written);
+
+ if(code || ((ssize_t)gss_send_token.length != written)) {
+ failf(data, "Failed to send GSS-API authentication token.");
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ }
+
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ if(gss_major_status != GSS_S_CONTINUE_NEEDED) break;
+
+ /* analyse response */
+
+ /* GSS-API response looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result || (actualread != 4)) {
+ failf(data, "Failed to receive GSS-API authentication response.");
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 1) { /* status / messgae type */
+ failf(data, "Invalid GSS-API authentication response type (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ gss_recv_token.length=us_length;
+ gss_recv_token.value=malloc(us_length);
+ if(!gss_recv_token.value) {
+ failf(data,
+ "Could not allocate memory for GSS-API authentication "
+ "response token.");
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ gss_recv_token.length, &actualread);
+
+ if(result || (actualread != us_length)) {
+ failf(data, "Failed to receive GSS-API authentication token.");
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ gss_token = &gss_recv_token;
+ }
+
+ gss_release_name(&gss_status, &server);
+
+ /* Everything is good so far, user was authenticated! */
+ gss_major_status = gss_inquire_context (&gss_minor_status, gss_context,
+ &gss_client_name, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if(check_gss_err(data, gss_major_status,
+ gss_minor_status, "gss_inquire_context")) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ gss_release_name(&gss_status, &gss_client_name);
+ failf(data, "Failed to determine user name.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_major_status = gss_display_name(&gss_minor_status, gss_client_name,
+ &gss_send_token, NULL);
+ if(check_gss_err(data, gss_major_status,
+ gss_minor_status, "gss_display_name")) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ gss_release_name(&gss_status, &gss_client_name);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ failf(data, "Failed to determine user name.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ user=malloc(gss_send_token.length+1);
+ if(!user) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ gss_release_name(&gss_status, &gss_client_name);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ memcpy(user, gss_send_token.value, gss_send_token.length);
+ user[gss_send_token.length] = '\0';
+ gss_release_name(&gss_status, &gss_client_name);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user);
+ free(user);
+ user=NULL;
+
+ /* Do encryption */
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 2; /* encryption message type */
+
+ gss_enc = 0; /* no data protection */
+ /* do confidentiality protection if supported */
+ if(gss_ret_flags & GSS_C_CONF_FLAG)
+ gss_enc = 2;
+ /* else do integrity protection */
+ else if(gss_ret_flags & GSS_C_INTEG_FLAG)
+ gss_enc = 1;
+
+ infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
+ (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
+ /* force for the moment to no data protection */
+ gss_enc = 0;
+ /*
+ * Sending the encryption type in clear seems wrong. It should be
+ * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
+ * The NEC reference implementations on which this is based is
+ * therefore at fault
+ *
+ * +------+------+------+.......................+
+ * + ver | mtyp | len | token |
+ * +------+------+------+.......................+
+ * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
+ * +------+------+------+.......................+
+ *
+ * Where:
+ *
+ * - "ver" is the protocol version number, here 1 to represent the
+ * first version of the SOCKS/GSS-API protocol
+ *
+ * - "mtyp" is the message type, here 2 to represent a protection
+ * -level negotiation message
+ *
+ * - "len" is the length of the "token" field in octets
+ *
+ * - "token" is the GSS-API encapsulated protection level
+ *
+ * The token is produced by encapsulating an octet containing the
+ * required protection level using gss_seal()/gss_wrap() with conf_req
+ * set to FALSE. The token is verified using gss_unseal()/
+ * gss_unwrap().
+ *
+ */
+ if(data->set.socks5_gssapi_nec) {
+ us_length = htons((short)1);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+ }
+ else {
+ gss_send_token.length = 1;
+ gss_send_token.value = malloc(1);
+ if(!gss_send_token.value) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(gss_send_token.value, &gss_enc, 1);
+
+ gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0,
+ GSS_C_QOP_DEFAULT, &gss_send_token,
+ &gss_conf_state, &gss_w_token);
+
+ if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) {
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ failf(data, "Failed to wrap GSS-API encryption value into token.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_release_buffer(&gss_status, &gss_send_token);
+
+ us_length = htons((short)gss_w_token.length);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if(code || (4 != written)) {
+ failf(data, "Failed to send GSS-API encryption request.");
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(data->set.socks5_gssapi_nec) {
+ memcpy(socksreq, &gss_enc, 1);
+ code = Curl_write_plain(conn, sock, socksreq, 1, &written);
+ if(code || ( 1 != written)) {
+ failf(data, "Failed to send GSS-API encryption type.");
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+ else {
+ code = Curl_write_plain(conn, sock, (char *)gss_w_token.value,
+ gss_w_token.length, &written);
+ if(code || ((ssize_t)gss_w_token.length != written)) {
+ failf(data, "Failed to send GSS-API encryption type.");
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_release_buffer(&gss_status, &gss_w_token);
+ }
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result || (actualread != 4)) {
+ failf(data, "Failed to receive GSS-API encryption response.");
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 2) { /* status / messgae type */
+ failf(data, "Invalid GSS-API encryption response type (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ gss_recv_token.length= us_length;
+ gss_recv_token.value=malloc(gss_recv_token.length);
+ if(!gss_recv_token.value) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ gss_recv_token.length, &actualread);
+
+ if(result || (actualread != us_length)) {
+ failf(data, "Failed to receive GSS-API encryptrion type.");
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(!data->set.socks5_gssapi_nec) {
+ gss_major_status = gss_unwrap(&gss_minor_status, gss_context,
+ &gss_recv_token, &gss_w_token,
+ 0, GSS_C_QOP_DEFAULT);
+
+ if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) {
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ failf(data, "Failed to unwrap GSS-API encryption value into token.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_release_buffer(&gss_status, &gss_recv_token);
+
+ if(gss_w_token.length != 1) {
+ failf(data, "Invalid GSS-API encryption response length (%d).",
+ gss_w_token.length);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(socksreq, gss_w_token.value, gss_w_token.length);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ }
+ else {
+ if(gss_recv_token.length != 1) {
+ failf(data, "Invalid GSS-API encryption response length (%d).",
+ gss_recv_token.length);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(socksreq, gss_recv_token.value, gss_recv_token.length);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ }
+
+ infof(data, "SOCKS5 access with%s protection granted.\n",
+ (socksreq[0]==0)?"out GSS-API data":
+ ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality"));
+
+ conn->socks5_gssapi_enctype = socksreq[0];
+ if(socksreq[0] == 0)
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+
+ return CURLE_OK;
+}
+
+#endif /* HAVE_GSSAPI && !CURL_DISABLE_PROXY */
diff --git a/libcurl/src/lib/socks_sspi.c b/libcurl/src/lib/socks_sspi.c
new file mode 100644
index 0000000..2ada80a
--- /dev/null
+++ b/libcurl/src/lib/socks_sspi.c
@@ -0,0 +1,601 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY)
+
+#include "urldata.h"
+#include "sendf.h"
+#include "connect.h"
+#include "strerror.h"
+#include "timeval.h"
+#include "socks.h"
+#include "curl_sspi.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Helper sspi error functions.
+ */
+static int check_sspi_err(struct connectdata *conn,
+ SECURITY_STATUS status,
+ const char* function)
+{
+ if(status != SEC_E_OK &&
+ status != SEC_I_COMPLETE_AND_CONTINUE &&
+ status != SEC_I_COMPLETE_NEEDED &&
+ status != SEC_I_CONTINUE_NEEDED) {
+ failf(conn->data, "SSPI error: %s failed: %s", function,
+ Curl_sspi_strerror(conn, status));
+ return 1;
+ }
+ return 0;
+}
+
+/* This is the SSPI-using version of this function */
+CURL_STATIC CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+ struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sock = conn->sock[sockindex];
+ CURLcode code;
+ ssize_t actualread;
+ ssize_t written;
+ int result;
+ /* Needs GSS-API authentication */
+ SECURITY_STATUS status;
+ unsigned long sspi_ret_flags = 0;
+ int gss_enc;
+ SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
+ SecBufferDesc input_desc, output_desc, wrap_desc;
+ SecPkgContext_Sizes sspi_sizes;
+ CredHandle cred_handle;
+ CtxtHandle sspi_context;
+ PCtxtHandle context_handle = NULL;
+ SecPkgCredentials_Names names;
+ TimeStamp expiry;
+ char *service_name = NULL;
+ unsigned short us_length;
+ unsigned long qop;
+ unsigned char socksreq[4]; /* room for GSS-API exchange header only */
+ char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
+
+ /* GSS-API request looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ /* prepare service name */
+ if(strchr(service, '/')) {
+ service_name = malloc(strlen(service));
+ if(!service_name)
+ return CURLE_OUT_OF_MEMORY;
+ memcpy(service_name, service, strlen(service));
+ }
+ else {
+ service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
+ if(!service_name)
+ return CURLE_OUT_OF_MEMORY;
+ snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2,
+ "%s/%s", service, conn->proxy.name);
+ }
+
+ input_desc.cBuffers = 1;
+ input_desc.pBuffers = &sspi_recv_token;
+ input_desc.ulVersion = SECBUFFER_VERSION;
+
+ sspi_recv_token.BufferType = SECBUFFER_TOKEN;
+ sspi_recv_token.cbBuffer = 0;
+ sspi_recv_token.pvBuffer = NULL;
+
+ output_desc.cBuffers = 1;
+ output_desc.pBuffers = &sspi_send_token;
+ output_desc.ulVersion = SECBUFFER_VERSION;
+
+ sspi_send_token.BufferType = SECBUFFER_TOKEN;
+ sspi_send_token.cbBuffer = 0;
+ sspi_send_token.pvBuffer = NULL;
+
+ wrap_desc.cBuffers = 3;
+ wrap_desc.pBuffers = sspi_w_token;
+ wrap_desc.ulVersion = SECBUFFER_VERSION;
+
+ cred_handle.dwLower = 0;
+ cred_handle.dwUpper = 0;
+
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT("Kerberos"),
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &cred_handle,
+ &expiry);
+
+ if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) {
+ failf(data, "Failed to acquire credentials.");
+ free(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* As long as we need to keep sending some context info, and there's no */
+ /* errors, keep sending it... */
+ for(;;) {
+ TCHAR *sname;
+
+ sname = Curl_convert_UTF8_to_tchar(service_name);
+ if(!sname)
+ return CURLE_OUT_OF_MEMORY;
+
+ status = s_pSecFn->InitializeSecurityContext(&cred_handle,
+ context_handle,
+ sname,
+ ISC_REQ_MUTUAL_AUTH |
+ ISC_REQ_ALLOCATE_MEMORY |
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT,
+ 0,
+ SECURITY_NATIVE_DREP,
+ &input_desc,
+ 0,
+ &sspi_context,
+ &output_desc,
+ &sspi_ret_flags,
+ &expiry);
+
+ Curl_unicodefree(sname);
+
+ if(sspi_recv_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ sspi_recv_token.pvBuffer = NULL;
+ sspi_recv_token.cbBuffer = 0;
+ }
+
+ if(check_sspi_err(conn, status, "InitializeSecurityContext")) {
+ free(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ failf(data, "Failed to initialise security context.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(sspi_send_token.cbBuffer != 0) {
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 1; /* authentication message type */
+ us_length = htons((short)sspi_send_token.cbBuffer);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if(code || (4 != written)) {
+ failf(data, "Failed to send SSPI authentication request.");
+ free(service_name);
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, &written);
+ if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
+ failf(data, "Failed to send SSPI authentication token.");
+ free(service_name);
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ }
+
+ if(sspi_send_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ sspi_send_token.pvBuffer = NULL;
+ }
+ sspi_send_token.cbBuffer = 0;
+
+ if(sspi_recv_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ sspi_recv_token.pvBuffer = NULL;
+ }
+ sspi_recv_token.cbBuffer = 0;
+
+ if(status != SEC_I_CONTINUE_NEEDED)
+ break;
+
+ /* analyse response */
+
+ /* GSS-API response looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result || (actualread != 4)) {
+ failf(data, "Failed to receive SSPI authentication response.");
+ free(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ free(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 1) { /* status / messgae type */
+ failf(data, "Invalid SSPI authentication response type (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ free(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ sspi_recv_token.cbBuffer = us_length;
+ sspi_recv_token.pvBuffer = malloc(us_length);
+
+ if(!sspi_recv_token.pvBuffer) {
+ free(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
+ sspi_recv_token.cbBuffer, &actualread);
+
+ if(result || (actualread != us_length)) {
+ failf(data, "Failed to receive SSPI authentication token.");
+ free(service_name);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ context_handle = &sspi_context;
+ }
+
+ free(service_name);
+
+ /* Everything is good so far, user was authenticated! */
+ status = s_pSecFn->QueryCredentialsAttributes(&cred_handle,
+ SECPKG_CRED_ATTR_NAMES,
+ &names);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ if(check_sspi_err(conn, status, "QueryCredentialAttributes")) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ s_pSecFn->FreeContextBuffer(names.sUserName);
+ failf(data, "Failed to determine user name.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",
+ names.sUserName);
+ s_pSecFn->FreeContextBuffer(names.sUserName);
+
+ /* Do encryption */
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 2; /* encryption message type */
+
+ gss_enc = 0; /* no data protection */
+ /* do confidentiality protection if supported */
+ if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
+ gss_enc = 2;
+ /* else do integrity protection */
+ else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
+ gss_enc = 1;
+
+ infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
+ (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") );
+ /* force to no data protection, avoid encryption/decryption for now */
+ gss_enc = 0;
+ /*
+ * Sending the encryption type in clear seems wrong. It should be
+ * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
+ * The NEC reference implementations on which this is based is
+ * therefore at fault
+ *
+ * +------+------+------+.......................+
+ * + ver | mtyp | len | token |
+ * +------+------+------+.......................+
+ * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
+ * +------+------+------+.......................+
+ *
+ * Where:
+ *
+ * - "ver" is the protocol version number, here 1 to represent the
+ * first version of the SOCKS/GSS-API protocol
+ *
+ * - "mtyp" is the message type, here 2 to represent a protection
+ * -level negotiation message
+ *
+ * - "len" is the length of the "token" field in octets
+ *
+ * - "token" is the GSS-API encapsulated protection level
+ *
+ * The token is produced by encapsulating an octet containing the
+ * required protection level using gss_seal()/gss_wrap() with conf_req
+ * set to FALSE. The token is verified using gss_unseal()/
+ * gss_unwrap().
+ *
+ */
+
+ if(data->set.socks5_gssapi_nec) {
+ us_length = htons((short)1);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+ }
+ else {
+ status = s_pSecFn->QueryContextAttributes(&sspi_context,
+ SECPKG_ATTR_SIZES,
+ &sspi_sizes);
+ if(check_sspi_err(conn, status, "QueryContextAttributes")) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ failf(data, "Failed to query security context attributes.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
+ sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
+ sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer);
+
+ if(!sspi_w_token[0].pvBuffer) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ sspi_w_token[1].cbBuffer = 1;
+ sspi_w_token[1].pvBuffer = malloc(1);
+ if(!sspi_w_token[1].pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1);
+ sspi_w_token[2].BufferType = SECBUFFER_PADDING;
+ sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
+ sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize);
+ if(!sspi_w_token[2].pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ status = s_pSecFn->EncryptMessage(&sspi_context,
+ KERB_WRAP_NO_ENCRYPT,
+ &wrap_desc,
+ 0);
+ if(check_sspi_err(conn, status, "EncryptMessage")) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ failf(data, "Failed to query security context attributes.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer
+ + sspi_w_token[1].cbBuffer
+ + sspi_w_token[2].cbBuffer;
+ sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer);
+ if(!sspi_send_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer,
+ sspi_w_token[0].cbBuffer);
+ memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer,
+ sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
+ memcpy((PUCHAR) sspi_send_token.pvBuffer
+ +sspi_w_token[0].cbBuffer
+ +sspi_w_token[1].cbBuffer,
+ sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
+
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ sspi_w_token[0].pvBuffer = NULL;
+ sspi_w_token[0].cbBuffer = 0;
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ sspi_w_token[1].pvBuffer = NULL;
+ sspi_w_token[1].cbBuffer = 0;
+ s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
+ sspi_w_token[2].pvBuffer = NULL;
+ sspi_w_token[2].cbBuffer = 0;
+
+ us_length = htons((short)sspi_send_token.cbBuffer);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if(code || (4 != written)) {
+ failf(data, "Failed to send SSPI encryption request.");
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(data->set.socks5_gssapi_nec) {
+ memcpy(socksreq, &gss_enc, 1);
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
+ if(code || (1 != written)) {
+ failf(data, "Failed to send SSPI encryption type.");
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+ else {
+ code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, &written);
+ if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
+ failf(data, "Failed to send SSPI encryption type.");
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ }
+
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result || (actualread != 4)) {
+ failf(data, "Failed to receive SSPI encryption response.");
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 2) { /* status / message type */
+ failf(data, "Invalid SSPI encryption response type (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ sspi_w_token[0].cbBuffer = us_length;
+ sspi_w_token[0].pvBuffer = malloc(us_length);
+ if(!sspi_w_token[0].pvBuffer) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
+ sspi_w_token[0].cbBuffer, &actualread);
+
+ if(result || (actualread != us_length)) {
+ failf(data, "Failed to receive SSPI encryption type.");
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+
+ if(!data->set.socks5_gssapi_nec) {
+ wrap_desc.cBuffers = 2;
+ sspi_w_token[0].BufferType = SECBUFFER_STREAM;
+ sspi_w_token[1].BufferType = SECBUFFER_DATA;
+ sspi_w_token[1].cbBuffer = 0;
+ sspi_w_token[1].pvBuffer = NULL;
+
+ status = s_pSecFn->DecryptMessage(&sspi_context,
+ &wrap_desc,
+ 0,
+ &qop);
+
+ if(check_sspi_err(conn, status, "DecryptMessage")) {
+ if(sspi_w_token[0].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ if(sspi_w_token[1].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ failf(data, "Failed to query security context attributes.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(sspi_w_token[1].cbBuffer != 1) {
+ failf(data, "Invalid SSPI encryption response length (%lu).",
+ (unsigned long)sspi_w_token[1].cbBuffer);
+ if(sspi_w_token[0].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ if(sspi_w_token[1].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ }
+ else {
+ if(sspi_w_token[0].cbBuffer != 1) {
+ failf(data, "Invalid SSPI encryption response length (%lu).",
+ (unsigned long)sspi_w_token[0].cbBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+ memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ }
+
+ infof(data, "SOCKS5 access with%s protection granted.\n",
+ (socksreq[0]==0)?"out GSS-API data":
+ ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality"));
+
+ /* For later use if encryption is required
+ conn->socks5_gssapi_enctype = socksreq[0];
+ if(socksreq[0] != 0)
+ conn->socks5_sspi_context = sspi_context;
+ else {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ conn->socks5_sspi_context = sspi_context;
+ }
+ */
+ return CURLE_OK;
+}
+#endif
diff --git a/libcurl/src/lib/speedcheck.c b/libcurl/src/lib/speedcheck.c
new file mode 100644
index 0000000..8c27417
--- /dev/null
+++ b/libcurl/src/lib/speedcheck.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "speedcheck.h"
+
+CURL_STATIC void Curl_speedinit(struct SessionHandle *data)
+{
+ memset(&data->state.keeps_speed, 0, sizeof(struct timeval));
+}
+
+CURL_STATIC CURLcode Curl_speedcheck(struct SessionHandle *data,
+ struct timeval now)
+{
+ if((data->progress.current_speed >= 0) &&
+ data->set.low_speed_time &&
+ (Curl_tvlong(data->state.keeps_speed) != 0) &&
+ (data->progress.current_speed < data->set.low_speed_limit)) {
+ long howlong = Curl_tvdiff(now, data->state.keeps_speed);
+ long nextcheck = (data->set.low_speed_time * 1000) - howlong;
+
+ /* We are now below the "low speed limit". If we are below it
+ for "low speed time" seconds we consider that enough reason
+ to abort the download. */
+ if(nextcheck <= 0) {
+ /* we have been this slow for long enough, now die */
+ failf(data,
+ "Operation too slow. "
+ "Less than %ld bytes/sec transferred the last %ld seconds",
+ data->set.low_speed_limit,
+ data->set.low_speed_time);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ else {
+ /* wait complete low_speed_time */
+ Curl_expire_latest(data, nextcheck);
+ }
+ }
+ else {
+ /* we keep up the required speed all right */
+ data->state.keeps_speed = now;
+
+ if(data->set.low_speed_limit)
+ /* if there is a low speed limit enabled, we set the expire timer to
+ make this connection's speed get checked again no later than when
+ this time is up */
+ Curl_expire_latest(data, data->set.low_speed_time*1000);
+ }
+ return CURLE_OK;
+}
diff --git a/libcurl/src/lib/speedcheck.h b/libcurl/src/lib/speedcheck.h
new file mode 100644
index 0000000..f53bdd1
--- /dev/null
+++ b/libcurl/src/lib/speedcheck.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_SPEEDCHECK_H
+#define HEADER_CURL_SPEEDCHECK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "timeval.h"
+
+CURL_STATIC void Curl_speedinit(struct SessionHandle *data);
+CURL_STATIC CURLcode Curl_speedcheck(struct SessionHandle *data,
+ struct timeval now);
+
+#endif /* HEADER_CURL_SPEEDCHECK_H */
diff --git a/libcurl/src/lib/splay.c b/libcurl/src/lib/splay.c
new file mode 100644
index 0000000..6f8227e
--- /dev/null
+++ b/libcurl/src/lib/splay.c
@@ -0,0 +1,288 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1997 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "splay.h"
+
+/*
+ * This macro compares two node keys i and j and returns:
+ *
+ * negative value: when i is smaller than j
+ * zero : when i is equal to j
+ * positive when : when i is larger than j
+ */
+#define compare(i,j) Curl_splaycomparekeys((i),(j))
+
+/*
+ * Splay using the key i (which may or may not be in the tree.) The starting
+ * root is t.
+ */
+CURL_STATIC struct Curl_tree *Curl_splay(struct timeval i,
+ struct Curl_tree *t)
+{
+ struct Curl_tree N, *l, *r, *y;
+ long comp;
+
+ if(t == NULL)
+ return t;
+ N.smaller = N.larger = NULL;
+ l = r = &N;
+
+ for(;;) {
+ comp = compare(i, t->key);
+ if(comp < 0) {
+ if(t->smaller == NULL)
+ break;
+ if(compare(i, t->smaller->key) < 0) {
+ y = t->smaller; /* rotate smaller */
+ t->smaller = y->larger;
+ y->larger = t;
+ t = y;
+ if(t->smaller == NULL)
+ break;
+ }
+ r->smaller = t; /* link smaller */
+ r = t;
+ t = t->smaller;
+ }
+ else if(comp > 0) {
+ if(t->larger == NULL)
+ break;
+ if(compare(i, t->larger->key) > 0) {
+ y = t->larger; /* rotate larger */
+ t->larger = y->smaller;
+ y->smaller = t;
+ t = y;
+ if(t->larger == NULL)
+ break;
+ }
+ l->larger = t; /* link larger */
+ l = t;
+ t = t->larger;
+ }
+ else
+ break;
+ }
+
+ l->larger = t->smaller; /* assemble */
+ r->smaller = t->larger;
+ t->smaller = N.larger;
+ t->larger = N.smaller;
+
+ return t;
+}
+
+/* Insert key i into the tree t. Return a pointer to the resulting tree or
+ * NULL if something went wrong.
+ *
+ * @unittest: 1309
+ */
+CURL_STATIC struct Curl_tree *Curl_splayinsert(struct timeval i,
+ struct Curl_tree *t,
+ struct Curl_tree *node)
+{
+ static const struct timeval KEY_NOTUSED = {-1, -1}; /* will *NEVER* appear */
+
+ if(node == NULL)
+ return t;
+
+ if(t != NULL) {
+ t = Curl_splay(i, t);
+ if(compare(i, t->key)==0) {
+ /* There already exists a node in the tree with the very same key. Build
+ a linked list of nodes. We make the new 'node' struct the new master
+ node and make the previous node the first one in the 'same' list. */
+
+ node->same = t;
+ node->key = i;
+ node->smaller = t->smaller;
+ node->larger = t->larger;
+
+ t->smaller = node; /* in the sub node for this same key, we use the
+ smaller pointer to point back to the master
+ node */
+
+ t->key = KEY_NOTUSED; /* and we set the key in the sub node to NOTUSED
+ to quickly identify this node as a subnode */
+
+ return node; /* new root node */
+ }
+ }
+
+ if(t == NULL) {
+ node->smaller = node->larger = NULL;
+ }
+ else if(compare(i, t->key) < 0) {
+ node->smaller = t->smaller;
+ node->larger = t;
+ t->smaller = NULL;
+
+ }
+ else {
+ node->larger = t->larger;
+ node->smaller = t;
+ t->larger = NULL;
+ }
+ node->key = i;
+
+ node->same = NULL; /* no identical node (yet) */
+ return node;
+}
+
+/* Finds and deletes the best-fit node from the tree. Return a pointer to the
+ resulting tree. best-fit means the node with the given or lower key */
+CURL_STATIC struct Curl_tree *Curl_splaygetbest(struct timeval i,
+ struct Curl_tree *t,
+ struct Curl_tree **removed)
+{
+ struct Curl_tree *x;
+
+ if(!t) {
+ *removed = NULL; /* none removed since there was no root */
+ return NULL;
+ }
+
+ t = Curl_splay(i, t);
+ if(compare(i, t->key) < 0) {
+ /* too big node, try the smaller chain */
+ if(t->smaller)
+ t=Curl_splay(t->smaller->key, t);
+ else {
+ /* fail */
+ *removed = NULL;
+ return t;
+ }
+ }
+
+ if(compare(i, t->key) >= 0) { /* found it */
+ /* FIRST! Check if there is a list with identical keys */
+ x = t->same;
+ if(x) {
+ /* there is, pick one from the list */
+
+ /* 'x' is the new root node */
+
+ x->key = t->key;
+ x->larger = t->larger;
+ x->smaller = t->smaller;
+
+ *removed = t;
+ return x; /* new root */
+ }
+
+ if(t->smaller == NULL) {
+ x = t->larger;
+ }
+ else {
+ x = Curl_splay(i, t->smaller);
+ x->larger = t->larger;
+ }
+ *removed = t;
+
+ return x;
+ }
+ else {
+ *removed = NULL; /* no match */
+ return t; /* It wasn't there */
+ }
+}
+
+
+/* Deletes the very node we point out from the tree if it's there. Stores a
+ * pointer to the new resulting tree in 'newroot'.
+ *
+ * Returns zero on success and non-zero on errors! TODO: document error codes.
+ * When returning error, it does not touch the 'newroot' pointer.
+ *
+ * NOTE: when the last node of the tree is removed, there's no tree left so
+ * 'newroot' will be made to point to NULL.
+ *
+ * @unittest: 1309
+ */
+CURL_STATIC int Curl_splayremovebyaddr(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot)
+{
+ static const struct timeval KEY_NOTUSED = {-1, -1}; /* will *NEVER* appear */
+ struct Curl_tree *x;
+
+ if(!t || !removenode)
+ return 1;
+
+ if(compare(KEY_NOTUSED, removenode->key) == 0) {
+ /* Key set to NOTUSED means it is a subnode within a 'same' linked list
+ and thus we can unlink it easily. The 'smaller' link of a subnode
+ links to the parent node. */
+ if(removenode->smaller == NULL)
+ return 3;
+
+ removenode->smaller->same = removenode->same;
+ if(removenode->same)
+ removenode->same->smaller = removenode->smaller;
+
+ /* Ensures that double-remove gets caught. */
+ removenode->smaller = NULL;
+
+ /* voila, we're done! */
+ *newroot = t; /* return the same root */
+ return 0;
+ }
+
+ t = Curl_splay(removenode->key, t);
+
+ /* First make sure that we got the same root node as the one we want
+ to remove, as otherwise we might be trying to remove a node that
+ isn't actually in the tree.
+
+ We cannot just compare the keys here as a double remove in quick
+ succession of a node with key != KEY_NOTUSED && same != NULL
+ could return the same key but a different node. */
+ if(t != removenode)
+ return 2;
+
+ /* Check if there is a list with identical sizes, as then we're trying to
+ remove the root node of a list of nodes with identical keys. */
+ x = t->same;
+ if(x) {
+ /* 'x' is the new root node, we just make it use the root node's
+ smaller/larger links */
+
+ x->key = t->key;
+ x->larger = t->larger;
+ x->smaller = t->smaller;
+ }
+ else {
+ /* Remove the root node */
+ if(t->smaller == NULL)
+ x = t->larger;
+ else {
+ x = Curl_splay(removenode->key, t->smaller);
+ x->larger = t->larger;
+ }
+ }
+
+ *newroot = x; /* store new root pointer */
+
+ return 0;
+}
+
diff --git a/libcurl/src/lib/splay.h b/libcurl/src/lib/splay.h
new file mode 100644
index 0000000..7ca5ffa
--- /dev/null
+++ b/libcurl/src/lib/splay.h
@@ -0,0 +1,66 @@
+#ifndef HEADER_CURL_SPLAY_H
+#define HEADER_CURL_SPLAY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1997 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+struct Curl_tree {
+ struct Curl_tree *smaller; /* smaller node */
+ struct Curl_tree *larger; /* larger node */
+ struct Curl_tree *same; /* points to a node with identical key */
+ struct timeval key; /* this node's "sort" key */
+ void *payload; /* data the splay code doesn't care about */
+};
+
+CURL_STATIC struct Curl_tree *Curl_splay(struct timeval i,
+ struct Curl_tree *t);
+
+CURL_STATIC struct Curl_tree *Curl_splayinsert(struct timeval key,
+ struct Curl_tree *t,
+ struct Curl_tree *newnode);
+
+#if 0
+CURL_STATIC struct Curl_tree *Curl_splayremove(struct timeval key,
+ struct Curl_tree *t,
+ struct Curl_tree **removed);
+#endif
+
+CURL_STATIC struct Curl_tree *Curl_splaygetbest(struct timeval key,
+ struct Curl_tree *t,
+ struct Curl_tree **removed);
+
+CURL_STATIC int Curl_splayremovebyaddr(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot);
+
+#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \
+ ( ((i.tv_sec) > (j.tv_sec)) ? 1 : \
+ ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \
+ ( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0 ))))
+
+#ifdef DEBUGBUILD
+CURL_STATIC void Curl_splayprint(struct Curl_tree * t, int d, char output);
+#else
+#define Curl_splayprint(x,y,z) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_SPLAY_H */
diff --git a/libcurl/src/lib/ssh.c b/libcurl/src/lib/ssh.c
new file mode 100644
index 0000000..bd16c7f
--- /dev/null
+++ b/libcurl/src/lib/ssh.c
@@ -0,0 +1,3341 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* #define CURL_LIBSSH2_DEBUG */
+
+#include "curl_setup.h"
+
+#ifdef USE_LIBSSH2
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "ssh.h"
+#include "url.h"
+#include "speedcheck.h"
+#include "getinfo.h"
+
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "inet_ntop.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "strtoofft.h"
+#include "multiif.h"
+#include "select.h"
+#include "warnless.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef WIN32
+# undef PATH_MAX
+# define PATH_MAX MAX_PATH
+# ifndef R_OK
+# define R_OK 4
+# endif
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* just an extra precaution since there are systems that
+ have their definition hidden well */
+#endif
+
+#define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
+
+#define sftp_libssh2_realpath(s,p,t,m) \
+ libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
+ (t), (m), LIBSSH2_SFTP_REALPATH)
+
+/* Local functions: */
+static const char *sftp_libssh2_strerror(int err);
+static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
+static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
+static LIBSSH2_FREE_FUNC(my_libssh2_free);
+
+static CURLcode get_pathname(const char **cpp, char **path);
+
+static CURLcode ssh_connect(struct connectdata *conn, bool *done);
+static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
+static CURLcode ssh_do(struct connectdata *conn, bool *done);
+
+static CURLcode ssh_getworkingpath(struct connectdata *conn,
+ char *homedir, /* when SFTP is used */
+ char **path);
+
+static CURLcode scp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode scp_doing(struct connectdata *conn,
+ bool *dophase_done);
+static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
+
+static CURLcode sftp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode sftp_doing(struct connectdata *conn,
+ bool *dophase_done);
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
+static
+CURLcode sftp_perform(struct connectdata *conn,
+ bool *connected,
+ bool *dophase_done);
+
+static int ssh_getsock(struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks number
+ of sockets */
+ int numsocks);
+
+static int ssh_perform_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks
+ number of sockets */
+ int numsocks);
+
+static CURLcode ssh_setup_connection(struct connectdata *conn);
+
+/*
+ * SCP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_scp = {
+ "SCP", /* scheme */
+ ssh_setup_connection, /* setup_connection */
+ ssh_do, /* do_it */
+ scp_done, /* done */
+ ZERO_NULL, /* do_more */
+ ssh_connect, /* connect_it */
+ ssh_multi_statemach, /* connecting */
+ scp_doing, /* doing */
+ ssh_getsock, /* proto_getsock */
+ ssh_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ssh_perform_getsock, /* perform_getsock */
+ scp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SSH, /* defport */
+ CURLPROTO_SCP, /* protocol */
+ PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
+ | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+/*
+ * SFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_sftp = {
+ "SFTP", /* scheme */
+ ssh_setup_connection, /* setup_connection */
+ ssh_do, /* do_it */
+ sftp_done, /* done */
+ ZERO_NULL, /* do_more */
+ ssh_connect, /* connect_it */
+ ssh_multi_statemach, /* connecting */
+ sftp_doing, /* doing */
+ ssh_getsock, /* proto_getsock */
+ ssh_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ssh_perform_getsock, /* perform_getsock */
+ sftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SSH, /* defport */
+ CURLPROTO_SFTP, /* protocol */
+ PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
+ | PROTOPT_NOURLQUERY /* flags */
+};
+
+static void
+kbd_callback(const char *name, int name_len, const char *instruction,
+ int instruction_len, int num_prompts,
+ const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
+ LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
+ void **abstract)
+{
+ struct connectdata *conn = (struct connectdata *)*abstract;
+
+#ifdef CURL_LIBSSH2_DEBUG
+ fprintf(stderr, "name=%s\n", name);
+ fprintf(stderr, "name_len=%d\n", name_len);
+ fprintf(stderr, "instruction=%s\n", instruction);
+ fprintf(stderr, "instruction_len=%d\n", instruction_len);
+ fprintf(stderr, "num_prompts=%d\n", num_prompts);
+#else
+ (void)name;
+ (void)name_len;
+ (void)instruction;
+ (void)instruction_len;
+#endif /* CURL_LIBSSH2_DEBUG */
+ if(num_prompts == 1) {
+ responses[0].text = strdup(conn->passwd);
+ responses[0].length = curlx_uztoui(strlen(conn->passwd));
+ }
+ (void)prompts;
+ (void)abstract;
+} /* kbd_callback */
+
+static CURLcode sftp_libssh2_error_to_CURLE(int err)
+{
+ switch (err) {
+ case LIBSSH2_FX_OK:
+ return CURLE_OK;
+
+ case LIBSSH2_FX_NO_SUCH_FILE:
+ case LIBSSH2_FX_NO_SUCH_PATH:
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+
+ case LIBSSH2_FX_PERMISSION_DENIED:
+ case LIBSSH2_FX_WRITE_PROTECT:
+ case LIBSSH2_FX_LOCK_CONFlICT:
+ return CURLE_REMOTE_ACCESS_DENIED;
+
+ case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
+ case LIBSSH2_FX_QUOTA_EXCEEDED:
+ return CURLE_REMOTE_DISK_FULL;
+
+ case LIBSSH2_FX_FILE_ALREADY_EXISTS:
+ return CURLE_REMOTE_FILE_EXISTS;
+
+ case LIBSSH2_FX_DIR_NOT_EMPTY:
+ return CURLE_QUOTE_ERROR;
+
+ default:
+ break;
+ }
+
+ return CURLE_SSH;
+}
+
+static CURLcode libssh2_session_error_to_CURLE(int err)
+{
+ switch (err) {
+ /* Ordered by order of appearance in libssh2.h */
+ case LIBSSH2_ERROR_NONE:
+ return CURLE_OK;
+
+ case LIBSSH2_ERROR_SOCKET_NONE:
+ return CURLE_COULDNT_CONNECT;
+
+ case LIBSSH2_ERROR_ALLOC:
+ return CURLE_OUT_OF_MEMORY;
+
+ case LIBSSH2_ERROR_SOCKET_SEND:
+ return CURLE_SEND_ERROR;
+
+ case LIBSSH2_ERROR_HOSTKEY_INIT:
+ case LIBSSH2_ERROR_HOSTKEY_SIGN:
+ case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
+ case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ case LIBSSH2_ERROR_PASSWORD_EXPIRED:
+ return CURLE_LOGIN_DENIED;
+
+ case LIBSSH2_ERROR_SOCKET_TIMEOUT:
+ case LIBSSH2_ERROR_TIMEOUT:
+ return CURLE_OPERATION_TIMEDOUT;
+
+ case LIBSSH2_ERROR_EAGAIN:
+ return CURLE_AGAIN;
+ }
+
+ /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
+ error code, and possibly add a few new SSH-related one. We must however
+ not return or even depend on libssh2 errors in the public libcurl API */
+
+ return CURLE_SSH;
+}
+
+static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
+{
+ (void)abstract; /* arg not used */
+ return malloc(count);
+}
+
+static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
+{
+ (void)abstract; /* arg not used */
+ return realloc(ptr, count);
+}
+
+static LIBSSH2_FREE_FUNC(my_libssh2_free)
+{
+ (void)abstract; /* arg not used */
+ if(ptr) /* ssh2 agent sometimes call free with null ptr */
+ free(ptr);
+}
+
+/*
+ * SSH State machine related code
+ */
+/* This is the ONLY way to change SSH state! */
+static void state(struct connectdata *conn, sshstate nowstate)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[] = {
+ "SSH_STOP",
+ "SSH_INIT",
+ "SSH_S_STARTUP",
+ "SSH_HOSTKEY",
+ "SSH_AUTHLIST",
+ "SSH_AUTH_PKEY_INIT",
+ "SSH_AUTH_PKEY",
+ "SSH_AUTH_PASS_INIT",
+ "SSH_AUTH_PASS",
+ "SSH_AUTH_AGENT_INIT",
+ "SSH_AUTH_AGENT_LIST",
+ "SSH_AUTH_AGENT",
+ "SSH_AUTH_HOST_INIT",
+ "SSH_AUTH_HOST",
+ "SSH_AUTH_KEY_INIT",
+ "SSH_AUTH_KEY",
+ "SSH_AUTH_DONE",
+ "SSH_SFTP_INIT",
+ "SSH_SFTP_REALPATH",
+ "SSH_SFTP_QUOTE_INIT",
+ "SSH_SFTP_POSTQUOTE_INIT",
+ "SSH_SFTP_QUOTE",
+ "SSH_SFTP_NEXT_QUOTE",
+ "SSH_SFTP_QUOTE_STAT",
+ "SSH_SFTP_QUOTE_SETSTAT",
+ "SSH_SFTP_QUOTE_SYMLINK",
+ "SSH_SFTP_QUOTE_MKDIR",
+ "SSH_SFTP_QUOTE_RENAME",
+ "SSH_SFTP_QUOTE_RMDIR",
+ "SSH_SFTP_QUOTE_UNLINK",
+ "SSH_SFTP_TRANS_INIT",
+ "SSH_SFTP_UPLOAD_INIT",
+ "SSH_SFTP_CREATE_DIRS_INIT",
+ "SSH_SFTP_CREATE_DIRS",
+ "SSH_SFTP_CREATE_DIRS_MKDIR",
+ "SSH_SFTP_READDIR_INIT",
+ "SSH_SFTP_READDIR",
+ "SSH_SFTP_READDIR_LINK",
+ "SSH_SFTP_READDIR_BOTTOM",
+ "SSH_SFTP_READDIR_DONE",
+ "SSH_SFTP_DOWNLOAD_INIT",
+ "SSH_SFTP_DOWNLOAD_STAT",
+ "SSH_SFTP_CLOSE",
+ "SSH_SFTP_SHUTDOWN",
+ "SSH_SCP_TRANS_INIT",
+ "SSH_SCP_UPLOAD_INIT",
+ "SSH_SCP_DOWNLOAD_INIT",
+ "SSH_SCP_DONE",
+ "SSH_SCP_SEND_EOF",
+ "SSH_SCP_WAIT_EOF",
+ "SSH_SCP_WAIT_CLOSE",
+ "SSH_SCP_CHANNEL_FREE",
+ "SSH_SESSION_DISCONNECT",
+ "SSH_SESSION_FREE",
+ "QUIT"
+ };
+
+ if(sshc->state != nowstate) {
+ infof(conn->data, "SFTP %p state change from %s to %s\n",
+ (void *)sshc, names[sshc->state], names[nowstate]);
+ }
+#endif
+
+ sshc->state = nowstate;
+}
+
+/* figure out the path to work with in this particular request */
+static CURLcode ssh_getworkingpath(struct connectdata *conn,
+ char *homedir, /* when SFTP is used */
+ char **path) /* returns the allocated
+ real path to work with */
+{
+ struct SessionHandle *data = conn->data;
+ char *real_path = NULL;
+ char *working_path;
+ int working_path_len;
+
+ working_path = curl_easy_unescape(data, data->state.path, 0,
+ &working_path_len);
+ if(!working_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Check for /~/ , indicating relative to the user's home directory */
+ if(conn->handler->protocol & CURLPROTO_SCP) {
+ real_path = malloc(working_path_len+1);
+ if(real_path == NULL) {
+ free(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
+ /* It is referenced to the home directory, so strip the leading '/~/' */
+ memcpy(real_path, working_path+3, 4 + working_path_len-3);
+ else
+ memcpy(real_path, working_path, 1 + working_path_len);
+ }
+ else if(conn->handler->protocol & CURLPROTO_SFTP) {
+ if((working_path_len > 1) && (working_path[1] == '~')) {
+ size_t homelen = strlen(homedir);
+ real_path = malloc(homelen + working_path_len + 1);
+ if(real_path == NULL) {
+ free(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ /* It is referenced to the home directory, so strip the
+ leading '/' */
+ memcpy(real_path, homedir, homelen);
+ real_path[homelen] = '/';
+ real_path[homelen+1] = '\0';
+ if(working_path_len > 3) {
+ memcpy(real_path+homelen+1, working_path + 3,
+ 1 + working_path_len -3);
+ }
+ }
+ else {
+ real_path = malloc(working_path_len+1);
+ if(real_path == NULL) {
+ free(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(real_path, working_path, 1+working_path_len);
+ }
+ }
+
+ free(working_path);
+
+ /* store the pointer for the caller to receive */
+ *path = real_path;
+
+ return CURLE_OK;
+}
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+static int sshkeycallback(CURL *easy,
+ const struct curl_khkey *knownkey, /* known */
+ const struct curl_khkey *foundkey, /* found */
+ enum curl_khmatch match,
+ void *clientp)
+{
+ (void)easy;
+ (void)knownkey;
+ (void)foundkey;
+ (void)clientp;
+
+ /* we only allow perfect matches, and we reject everything else */
+ return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
+}
+#endif
+
+/*
+ * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
+ * with 32bit size_t.
+ */
+#ifdef HAVE_LIBSSH2_SFTP_SEEK64
+#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
+#else
+#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
+#endif
+
+/*
+ * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
+ * architectures so we check of the necessary function is present.
+ */
+#ifndef HAVE_LIBSSH2_SCP_SEND64
+#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
+#else
+#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
+ (libssh2_uint64_t)d, 0, 0)
+#endif
+
+/*
+ * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
+ */
+#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
+#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
+#endif
+
+static CURLcode ssh_knownhost(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ struct SessionHandle *data = conn->data;
+
+ if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
+ /* we're asked to verify the host against a file */
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ int rc;
+ int keytype;
+ size_t keylen;
+ const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
+ &keylen, &keytype);
+ int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
+ int keybit = 0;
+
+ if(remotekey) {
+ /*
+ * A subject to figure out is what host name we need to pass in here.
+ * What host name does OpenSSH store in its file if an IDN name is
+ * used?
+ */
+ struct libssh2_knownhost *host;
+ enum curl_khmatch keymatch;
+ curl_sshkeycallback func =
+ data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
+ struct curl_khkey knownkey;
+ struct curl_khkey *knownkeyp = NULL;
+ struct curl_khkey foundkey;
+
+ keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
+ LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
+ keycheck = libssh2_knownhost_checkp(sshc->kh,
+ conn->host.name,
+ (conn->remote_port != PORT_SSH)?
+ conn->remote_port:-1,
+ remotekey, keylen,
+ LIBSSH2_KNOWNHOST_TYPE_PLAIN|
+ LIBSSH2_KNOWNHOST_KEYENC_RAW|
+ keybit,
+ &host);
+#else
+ keycheck = libssh2_knownhost_check(sshc->kh,
+ conn->host.name,
+ remotekey, keylen,
+ LIBSSH2_KNOWNHOST_TYPE_PLAIN|
+ LIBSSH2_KNOWNHOST_KEYENC_RAW|
+ keybit,
+ &host);
+#endif
+
+ infof(data, "SSH host check: %d, key: %s\n", keycheck,
+ (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
+ host->key:"<none>");
+
+ /* setup 'knownkey' */
+ if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
+ knownkey.key = host->key;
+ knownkey.len = 0;
+ knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
+ CURLKHTYPE_RSA : CURLKHTYPE_DSS;
+ knownkeyp = &knownkey;
+ }
+
+ /* setup 'foundkey' */
+ foundkey.key = remotekey;
+ foundkey.len = keylen;
+ foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
+ CURLKHTYPE_RSA : CURLKHTYPE_DSS;
+
+ /*
+ * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
+ * curl_khmatch enum are ever modified, we need to introduce a
+ * translation table here!
+ */
+ keymatch = (enum curl_khmatch)keycheck;
+
+ /* Ask the callback how to behave */
+ rc = func(data, knownkeyp, /* from the knownhosts file */
+ &foundkey, /* from the remote host */
+ keymatch, data->set.ssh_keyfunc_userp);
+ }
+ else
+ /* no remotekey means failure! */
+ rc = CURLKHSTAT_REJECT;
+
+ switch(rc) {
+ default: /* unknown return codes will equal reject */
+ /* FALLTHROUGH */
+ case CURLKHSTAT_REJECT:
+ state(conn, SSH_SESSION_FREE);
+ /* FALLTHROUGH */
+ case CURLKHSTAT_DEFER:
+ /* DEFER means bail out but keep the SSH_HOSTKEY state */
+ result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
+ break;
+ case CURLKHSTAT_FINE:
+ case CURLKHSTAT_FINE_ADD_TO_FILE:
+ /* proceed */
+ if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
+ /* the found host+key didn't match but has been told to be fine
+ anyway so we add it in memory */
+ int addrc = libssh2_knownhost_add(sshc->kh,
+ conn->host.name, NULL,
+ remotekey, keylen,
+ LIBSSH2_KNOWNHOST_TYPE_PLAIN|
+ LIBSSH2_KNOWNHOST_KEYENC_RAW|
+ keybit, NULL);
+ if(addrc)
+ infof(data, "Warning adding the known host %s failed!\n",
+ conn->host.name);
+ else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
+ /* now we write the entire in-memory list of known hosts to the
+ known_hosts file */
+ int wrc =
+ libssh2_knownhost_writefile(sshc->kh,
+ data->set.str[STRING_SSH_KNOWNHOSTS],
+ LIBSSH2_KNOWNHOST_FILE_OPENSSH);
+ if(wrc) {
+ infof(data, "Warning, writing %s failed!\n",
+ data->set.str[STRING_SSH_KNOWNHOSTS]);
+ }
+ }
+ }
+ break;
+ }
+ }
+#else /* HAVE_LIBSSH2_KNOWNHOST_API */
+ (void)conn;
+#endif
+ return result;
+}
+
+static CURLcode ssh_check_fingerprint(struct connectdata *conn)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ struct SessionHandle *data = conn->data;
+ const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
+ char md5buffer[33];
+ int i;
+
+ const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
+ LIBSSH2_HOSTKEY_HASH_MD5);
+
+ if(fingerprint) {
+ /* The fingerprint points to static storage (!), don't free() it. */
+ for(i = 0; i < 16; i++)
+ snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
+ infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
+ }
+
+ /* Before we authenticate we check the hostkey's MD5 fingerprint
+ * against a known fingerprint, if available.
+ */
+ if(pubkey_md5 && strlen(pubkey_md5) == 32) {
+ if(!fingerprint || !strequal(md5buffer, pubkey_md5)) {
+ if(fingerprint)
+ failf(data,
+ "Denied establishing ssh session: mismatch md5 fingerprint. "
+ "Remote %s is not equal to %s", md5buffer, pubkey_md5);
+ else
+ failf(data,
+ "Denied establishing ssh session: md5 fingerprint not available");
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
+ return sshc->actualcode;
+ }
+ else {
+ infof(data, "MD5 checksum match!\n");
+ /* as we already matched, we skip the check for known hosts */
+ return CURLE_OK;
+ }
+ }
+ else
+ return ssh_knownhost(conn);
+}
+
+/*
+ * ssh_statemach_act() runs the SSH state machine as far as it can without
+ * blocking and without reaching the end. The data the pointer 'block' points
+ * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
+ * meaning it wants to be called again when the socket is ready
+ */
+
+static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SSHPROTO *sftp_scp = data->req.protop;
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ char *new_readdir_line;
+ int rc = LIBSSH2_ERROR_NONE;
+ int err;
+ int seekerr = CURL_SEEKFUNC_OK;
+ *block = 0; /* we're not blocking by default */
+
+ do {
+
+ switch(sshc->state) {
+ case SSH_INIT:
+ sshc->secondCreateDirs = 0;
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_OK;
+
+ /* Set libssh2 to non-blocking, since everything internally is
+ non-blocking */
+ libssh2_session_set_blocking(sshc->ssh_session, 0);
+
+ state(conn, SSH_S_STARTUP);
+ /* fall-through */
+
+ case SSH_S_STARTUP:
+ rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ failf(data, "Failure establishing ssh session");
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_FAILED_INIT;
+ break;
+ }
+
+ state(conn, SSH_HOSTKEY);
+
+ /* fall-through */
+ case SSH_HOSTKEY:
+ /*
+ * Before we authenticate we should check the hostkey's fingerprint
+ * against our known hosts. How that is handled (reading from file,
+ * whatever) is up to us.
+ */
+ result = ssh_check_fingerprint(conn);
+ if(!result)
+ state(conn, SSH_AUTHLIST);
+ /* ssh_check_fingerprint sets state appropriately on error */
+ break;
+
+ case SSH_AUTHLIST:
+ /*
+ * Figure out authentication methods
+ * NB: As soon as we have provided a username to an openssh server we
+ * must never change it later. Thus, always specify the correct username
+ * here, even though the libssh2 docs kind of indicate that it should be
+ * possible to get a 'generic' list (not user-specific) of authentication
+ * methods, presumably with a blank username. That won't work in my
+ * experience.
+ * So always specify it here.
+ */
+ sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(strlen(conn->user)));
+
+ if(!sshc->authlist) {
+ if(libssh2_userauth_authenticated(sshc->ssh_session)) {
+ sshc->authed = TRUE;
+ infof(data, "SSH user accepted with no authentication\n");
+ state(conn, SSH_AUTH_DONE);
+ break;
+ }
+ else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = libssh2_session_error_to_CURLE(err);
+ break;
+ }
+ }
+ infof(data, "SSH authentication methods available: %s\n",
+ sshc->authlist);
+
+ state(conn, SSH_AUTH_PKEY_INIT);
+ break;
+
+ case SSH_AUTH_PKEY_INIT:
+ /*
+ * Check the supported auth types in the order I feel is most secure
+ * with the requested type of authentication
+ */
+ sshc->authed = FALSE;
+
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
+ (strstr(sshc->authlist, "publickey") != NULL)) {
+ char *home = NULL;
+ bool out_of_memory = FALSE;
+
+ sshc->rsa_pub = sshc->rsa = NULL;
+
+ /* To ponder about: should really the lib be messing about with the
+ HOME environment variable etc? */
+ home = curl_getenv("HOME");
+
+ if(data->set.str[STRING_SSH_PRIVATE_KEY])
+ sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
+ else {
+ /* If no private key file is specified, try some common paths. */
+ if(home) {
+ /* Try ~/.ssh first. */
+ sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
+ if(!sshc->rsa)
+ out_of_memory = TRUE;
+ else if(access(sshc->rsa, R_OK) != 0) {
+ Curl_safefree(sshc->rsa);
+ sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
+ if(!sshc->rsa)
+ out_of_memory = TRUE;
+ else if(access(sshc->rsa, R_OK) != 0) {
+ Curl_safefree(sshc->rsa);
+ }
+ }
+ }
+ if(!out_of_memory && !sshc->rsa) {
+ /* Nothing found; try the current dir. */
+ sshc->rsa = strdup("id_rsa");
+ if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
+ Curl_safefree(sshc->rsa);
+ sshc->rsa = strdup("id_dsa");
+ if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
+ Curl_safefree(sshc->rsa);
+ /* Out of guesses. Set to the empty string to avoid
+ * surprising info messages. */
+ sshc->rsa = strdup("");
+ }
+ }
+ }
+ }
+
+ /*
+ * Unless the user explicitly specifies a public key file, let
+ * libssh2 extract the public key from the private key file.
+ * This is done by simply passing sshc->rsa_pub = NULL.
+ */
+ if(data->set.str[STRING_SSH_PUBLIC_KEY]) {
+ sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
+ if(!sshc->rsa_pub)
+ out_of_memory = TRUE;
+ }
+
+ if(out_of_memory || sshc->rsa == NULL) {
+ free(home);
+ Curl_safefree(sshc->rsa);
+ Curl_safefree(sshc->rsa_pub);
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
+ if(!sshc->passphrase)
+ sshc->passphrase = "";
+
+ free(home);
+
+ infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
+ infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
+
+ state(conn, SSH_AUTH_PKEY);
+ }
+ else {
+ state(conn, SSH_AUTH_PASS_INIT);
+ }
+ break;
+
+ case SSH_AUTH_PKEY:
+ /* The function below checks if the files exists, no need to stat() here.
+ */
+ rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(
+ strlen(conn->user)),
+ sshc->rsa_pub,
+ sshc->rsa, sshc->passphrase);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+
+ if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized SSH public key authentication\n");
+ state(conn, SSH_AUTH_DONE);
+ }
+ else {
+ char *err_msg;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "SSH public key authentication failed: %s\n", err_msg);
+ state(conn, SSH_AUTH_PASS_INIT);
+ }
+ break;
+
+ case SSH_AUTH_PASS_INIT:
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
+ (strstr(sshc->authlist, "password") != NULL)) {
+ state(conn, SSH_AUTH_PASS);
+ }
+ else {
+ state(conn, SSH_AUTH_HOST_INIT);
+ }
+ break;
+
+ case SSH_AUTH_PASS:
+ rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
+ curlx_uztoui(strlen(conn->user)),
+ conn->passwd,
+ curlx_uztoui(strlen(conn->passwd)),
+ NULL);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized password authentication\n");
+ state(conn, SSH_AUTH_DONE);
+ }
+ else {
+ state(conn, SSH_AUTH_HOST_INIT);
+ }
+ break;
+
+ case SSH_AUTH_HOST_INIT:
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
+ (strstr(sshc->authlist, "hostbased") != NULL)) {
+ state(conn, SSH_AUTH_HOST);
+ }
+ else {
+ state(conn, SSH_AUTH_AGENT_INIT);
+ }
+ break;
+
+ case SSH_AUTH_HOST:
+ state(conn, SSH_AUTH_AGENT_INIT);
+ break;
+
+ case SSH_AUTH_AGENT_INIT:
+#ifdef HAVE_LIBSSH2_AGENT_API
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
+ && (strstr(sshc->authlist, "publickey") != NULL)) {
+
+ /* Connect to the ssh-agent */
+ /* The agent could be shared by a curl thread i believe
+ but nothing obvious as keys can be added/removed at any time */
+ if(!sshc->ssh_agent) {
+ sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
+ if(!sshc->ssh_agent) {
+ infof(data, "Could not create agent object\n");
+
+ state(conn, SSH_AUTH_KEY_INIT);
+ break;
+ }
+ }
+
+ rc = libssh2_agent_connect(sshc->ssh_agent);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ break;
+ if(rc < 0) {
+ infof(data, "Failure connecting to agent\n");
+ state(conn, SSH_AUTH_KEY_INIT);
+ }
+ else {
+ state(conn, SSH_AUTH_AGENT_LIST);
+ }
+ }
+ else
+#endif /* HAVE_LIBSSH2_AGENT_API */
+ state(conn, SSH_AUTH_KEY_INIT);
+ break;
+
+ case SSH_AUTH_AGENT_LIST:
+#ifdef HAVE_LIBSSH2_AGENT_API
+ rc = libssh2_agent_list_identities(sshc->ssh_agent);
+
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ break;
+ if(rc < 0) {
+ infof(data, "Failure requesting identities to agent\n");
+ state(conn, SSH_AUTH_KEY_INIT);
+ }
+ else {
+ state(conn, SSH_AUTH_AGENT);
+ sshc->sshagent_prev_identity = NULL;
+ }
+#endif
+ break;
+
+ case SSH_AUTH_AGENT:
+#ifdef HAVE_LIBSSH2_AGENT_API
+ /* as prev_identity evolves only after an identity user auth finished we
+ can safely request it again as long as EAGAIN is returned here or by
+ libssh2_agent_userauth */
+ rc = libssh2_agent_get_identity(sshc->ssh_agent,
+ &sshc->sshagent_identity,
+ sshc->sshagent_prev_identity);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ break;
+
+ if(rc == 0) {
+ rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
+ sshc->sshagent_identity);
+
+ if(rc < 0) {
+ if(rc != LIBSSH2_ERROR_EAGAIN) {
+ /* tried and failed? go to next identity */
+ sshc->sshagent_prev_identity = sshc->sshagent_identity;
+ }
+ break;
+ }
+ }
+
+ if(rc < 0)
+ infof(data, "Failure requesting identities to agent\n");
+ else if(rc == 1)
+ infof(data, "No identity would match\n");
+
+ if(rc == LIBSSH2_ERROR_NONE) {
+ sshc->authed = TRUE;
+ infof(data, "Agent based authentication successful\n");
+ state(conn, SSH_AUTH_DONE);
+ }
+ else
+ state(conn, SSH_AUTH_KEY_INIT);
+#endif
+ break;
+
+ case SSH_AUTH_KEY_INIT:
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
+ && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
+ state(conn, SSH_AUTH_KEY);
+ }
+ else {
+ state(conn, SSH_AUTH_DONE);
+ }
+ break;
+
+ case SSH_AUTH_KEY:
+ /* Authentication failed. Continue with keyboard-interactive now. */
+ rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(
+ strlen(conn->user)),
+ &kbd_callback);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized keyboard interactive authentication\n");
+ }
+ state(conn, SSH_AUTH_DONE);
+ break;
+
+ case SSH_AUTH_DONE:
+ if(!sshc->authed) {
+ failf(data, "Authentication failure");
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_LOGIN_DENIED;
+ break;
+ }
+
+ /*
+ * At this point we have an authenticated ssh session.
+ */
+ infof(data, "Authentication complete\n");
+
+ Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+
+ conn->sockfd = sock;
+ conn->writesockfd = CURL_SOCKET_BAD;
+
+ if(conn->handler->protocol == CURLPROTO_SFTP) {
+ state(conn, SSH_SFTP_INIT);
+ break;
+ }
+ infof(data, "SSH CONNECT phase done\n");
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_SFTP_INIT:
+ /*
+ * Start the libssh2 sftp session
+ */
+ sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
+ if(!sshc->sftp_session) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ char *err_msg;
+
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ failf(data, "Failure initializing sftp session: %s", err_msg);
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_FAILED_INIT;
+ break;
+ }
+ }
+ state(conn, SSH_SFTP_REALPATH);
+ break;
+
+ case SSH_SFTP_REALPATH:
+ {
+ char tempHome[PATH_MAX];
+
+ /*
+ * Get the "home" directory
+ */
+ rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
+ tempHome, PATH_MAX-1);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc > 0) {
+ /* It seems that this string is not always NULL terminated */
+ tempHome[rc] = '\0';
+ sshc->homedir = strdup(tempHome);
+ if(!sshc->homedir) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ }
+ else {
+ /* Return the error type */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
+ err, (int)result));
+ state(conn, SSH_STOP);
+ break;
+ }
+ }
+ /* This is the last step in the SFTP connect phase. Do note that while
+ we get the homedir here, we get the "workingpath" in the DO action
+ since the homedir will remain the same between request but the
+ working path will not. */
+ DEBUGF(infof(data, "SSH CONNECT phase done\n"));
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_SFTP_QUOTE_INIT:
+
+ result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ if(result) {
+ sshc->actualcode = result;
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ if(data->set.quote) {
+ infof(data, "Sending quote commands\n");
+ sshc->quote_item = data->set.quote;
+ state(conn, SSH_SFTP_QUOTE);
+ }
+ else {
+ state(conn, SSH_SFTP_TRANS_INIT);
+ }
+ break;
+
+ case SSH_SFTP_POSTQUOTE_INIT:
+ if(data->set.postquote) {
+ infof(data, "Sending quote commands\n");
+ sshc->quote_item = data->set.postquote;
+ state(conn, SSH_SFTP_QUOTE);
+ }
+ else {
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SFTP_QUOTE:
+ /* Send any quote commands */
+ {
+ const char *cp;
+
+ /*
+ * Support some of the "FTP" commands
+ */
+ char *cmd = sshc->quote_item->data;
+ sshc->acceptfail = FALSE;
+
+ /* if a command starts with an asterisk, which a legal SFTP command never
+ can, the command will be allowed to fail without it causing any
+ aborts or cancels etc. It will cause libcurl to act as if the command
+ is successful, whatever the server reponds. */
+
+ if(cmd[0] == '*') {
+ cmd++;
+ sshc->acceptfail = TRUE;
+ }
+
+ if(curl_strequal("pwd", cmd)) {
+ /* output debug output if that is requested */
+ char *tmp = aprintf("257 \"%s\" is current directory.\n",
+ sftp_scp->path);
+ if(!tmp) {
+ result = CURLE_OUT_OF_MEMORY;
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ break;
+ }
+ if(data->set.verbose) {
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+ }
+ /* this sends an FTP-like "header" to the header callback so that the
+ current directory can be read very similar to how it is read when
+ using ordinary FTP. */
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ free(tmp);
+ if(result) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ }
+ else
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+ }
+ else if(cmd) {
+ /*
+ * the arguments following the command must be separated from the
+ * command with a space so we can check for it unconditionally
+ */
+ cp = strchr(cmd, ' ');
+ if(cp == NULL) {
+ failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+
+ /*
+ * also, every command takes at least one argument so we get that
+ * first argument right now
+ */
+ result = get_pathname(&cp, &sshc->quote_path1);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error: Bad first parameter");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+
+ /*
+ * SFTP is a binary protocol, so we don't send text commands
+ * to the server. Instead, we scan for commands used by
+ * OpenSSH's sftp program and call the appropriate libssh2
+ * functions.
+ */
+ if(curl_strnequal(cmd, "chgrp ", 6) ||
+ curl_strnequal(cmd, "chmod ", 6) ||
+ curl_strnequal(cmd, "chown ", 6) ) {
+ /* attribute change */
+
+ /* sshc->quote_path1 contains the mode to set */
+ /* get the destination */
+ result = get_pathname(&cp, &sshc->quote_path2);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in chgrp/chmod/chown: "
+ "Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+ memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+ state(conn, SSH_SFTP_QUOTE_STAT);
+ break;
+ }
+ else if(curl_strnequal(cmd, "ln ", 3) ||
+ curl_strnequal(cmd, "symlink ", 8)) {
+ /* symbolic linking */
+ /* sshc->quote_path1 is the source */
+ /* get the destination */
+ result = get_pathname(&cp, &sshc->quote_path2);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data,
+ "Syntax error in ln/symlink: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+ state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ break;
+ }
+ else if(curl_strnequal(cmd, "mkdir ", 6)) {
+ /* create dir */
+ state(conn, SSH_SFTP_QUOTE_MKDIR);
+ break;
+ }
+ else if(curl_strnequal(cmd, "rename ", 7)) {
+ /* rename file */
+ /* first param is the source path */
+ /* second param is the dest. path */
+ result = get_pathname(&cp, &sshc->quote_path2);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in rename: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+ state(conn, SSH_SFTP_QUOTE_RENAME);
+ break;
+ }
+ else if(curl_strnequal(cmd, "rmdir ", 6)) {
+ /* delete dir */
+ state(conn, SSH_SFTP_QUOTE_RMDIR);
+ break;
+ }
+ else if(curl_strnequal(cmd, "rm ", 3)) {
+ state(conn, SSH_SFTP_QUOTE_UNLINK);
+ break;
+ }
+
+ failf(data, "Unknown SFTP command");
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+ if(!sshc->quote_item) {
+ state(conn, SSH_SFTP_TRANS_INIT);
+ }
+ break;
+
+ case SSH_SFTP_NEXT_QUOTE:
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+
+ sshc->quote_item = sshc->quote_item->next;
+
+ if(sshc->quote_item) {
+ state(conn, SSH_SFTP_QUOTE);
+ }
+ else {
+ if(sshc->nextstate != SSH_NO_STATE) {
+ state(conn, sshc->nextstate);
+ sshc->nextstate = SSH_NO_STATE;
+ }
+ else {
+ state(conn, SSH_SFTP_TRANS_INIT);
+ }
+ }
+ break;
+
+ case SSH_SFTP_QUOTE_STAT:
+ {
+ char *cmd = sshc->quote_item->data;
+ sshc->acceptfail = FALSE;
+
+ /* if a command starts with an asterisk, which a legal SFTP command never
+ can, the command will be allowed to fail without it causing any
+ aborts or cancels etc. It will cause libcurl to act as if the command
+ is successful, whatever the server reponds. */
+
+ if(cmd[0] == '*') {
+ cmd++;
+ sshc->acceptfail = TRUE;
+ }
+
+ if(!curl_strnequal(cmd, "chmod", 5)) {
+ /* Since chown and chgrp only set owner OR group but libssh2 wants to
+ * set them both at once, we need to obtain the current ownership
+ * first. This takes an extra protocol round trip.
+ */
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_STAT,
+ &sshc->quote_attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Attempt to get SFTP stats failed: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+
+ /* Now set the new attributes... */
+ if(curl_strnequal(cmd, "chgrp", 5)) {
+ sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
+ sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ !sshc->acceptfail) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: chgrp gid not a number");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+ else if(curl_strnequal(cmd, "chmod", 5)) {
+ sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
+ sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ /* permissions are octal */
+ if(sshc->quote_attrs.permissions == 0 &&
+ !ISDIGIT(sshc->quote_path1[0])) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: chmod permissions not a number");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+ else if(curl_strnequal(cmd, "chown", 5)) {
+ sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
+ sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ !sshc->acceptfail) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: chown uid not a number");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+
+ /* Now send the completed structure... */
+ state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ break;
+ }
+
+ case SSH_SFTP_QUOTE_SETSTAT:
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_SETSTAT,
+ &sshc->quote_attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Attempt to set SFTP stats failed: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_SYMLINK:
+ rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_SYMLINK);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "symlink command failed: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_MKDIR:
+ rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ data->set.new_directory_perms);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_RENAME:
+ rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_RENAME_OVERWRITE |
+ LIBSSH2_SFTP_RENAME_ATOMIC |
+ LIBSSH2_SFTP_RENAME_NATIVE);
+
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_RMDIR:
+ rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)));
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_UNLINK:
+ rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)));
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_TRANS_INIT:
+ if(data->set.upload)
+ state(conn, SSH_SFTP_UPLOAD_INIT);
+ else {
+ if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
+ state(conn, SSH_SFTP_READDIR_INIT);
+ else
+ state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ }
+ break;
+
+ case SSH_SFTP_UPLOAD_INIT:
+ {
+ unsigned long flags;
+ /*
+ * NOTE!!! libssh2 requires that the destination path is a full path
+ * that includes the destination file and name OR ends in a "/"
+ * If this is not done the destination file will be named the
+ * same name as the last directory in the path.
+ */
+
+ if(data->state.resume_from != 0) {
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+ if(data->state.resume_from < 0) {
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ LIBSSH2_SFTP_STAT, &attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ data->state.resume_from = 0;
+ }
+ else {
+ curl_off_t size = attrs.filesize;
+ if(size < 0) {
+ failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ data->state.resume_from = attrs.filesize;
+ }
+ }
+ }
+
+ if(data->set.ftp_append)
+ /* Try to open for append, but create if nonexisting */
+ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
+ else if(data->state.resume_from > 0)
+ /* If we have restart position then open for append */
+ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
+ else
+ /* Clear file before writing (normal behaviour) */
+ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
+
+ sshc->sftp_handle =
+ libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ flags, data->set.new_file_perms,
+ LIBSSH2_SFTP_OPENFILE);
+
+ if(!sshc->sftp_handle) {
+ rc = libssh2_session_last_errno(sshc->ssh_session);
+
+ if(LIBSSH2_ERROR_EAGAIN == rc)
+ break;
+ else {
+ if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
+ /* only when there was an SFTP protocol error can we extract
+ the sftp error! */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ else
+ err = -1; /* not an sftp error at all */
+
+ if(sshc->secondCreateDirs) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = err>= LIBSSH2_FX_OK?
+ sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
+ failf(data, "Creating the dir/file failed: %s",
+ sftp_libssh2_strerror(err));
+ break;
+ }
+ else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
+ (err == LIBSSH2_FX_FAILURE) ||
+ (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
+ (data->set.ftp_create_missing_dirs &&
+ (strlen(sftp_scp->path) > 1))) {
+ /* try to create the path remotely */
+ sshc->secondCreateDirs = 1;
+ state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ break;
+ }
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = err>= LIBSSH2_FX_OK?
+ sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
+ if(!sshc->actualcode) {
+ /* Sometimes, for some reason libssh2_sftp_last_error() returns
+ zero even though libssh2_sftp_open() failed previously! We need
+ to work around that! */
+ sshc->actualcode = CURLE_SSH;
+ err=-1;
+ }
+ failf(data, "Upload failed: %s (%d/%d)",
+ err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
+ err, rc);
+ break;
+ }
+ }
+
+ /* If we have a restart point then we need to seek to the correct
+ position. */
+ if(data->state.resume_from > 0) {
+ /* Let's read off the proper amount of bytes from the input. */
+ if(conn->seek_func) {
+ seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+ SEEK_SET);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
+ BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ conn->fread_func(data->state.buffer, 1, readthisamountnow,
+ conn->fread_in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ } while(passed < data->state.resume_from);
+ }
+ }
+
+ /* now, decrease the size of the read */
+ if(data->state.infilesize > 0) {
+ data->state.infilesize -= data->state.resume_from;
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+
+ SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+ }
+ if(data->state.infilesize > 0) {
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+ /* upload data */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->sockfd = conn->writesockfd;
+
+ if(result) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = result;
+ }
+ else {
+ /* store this original bitmask setup to use later on if we can't
+ figure out a "real" bitmask */
+ sshc->orig_waitfor = data->req.keepon;
+
+ /* we want to use the _sending_ function even when the socket turns
+ out readable as the underlying libssh2 sftp send function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_OUT;
+
+ /* since we don't really wait for anything at this point, we want the
+ state machine to move on as soon as possible so we set a very short
+ timeout here */
+ Curl_expire(data, 1);
+
+ state(conn, SSH_STOP);
+ }
+ break;
+ }
+
+ case SSH_SFTP_CREATE_DIRS_INIT:
+ if(strlen(sftp_scp->path) > 1) {
+ sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
+ state(conn, SSH_SFTP_CREATE_DIRS);
+ }
+ else {
+ state(conn, SSH_SFTP_UPLOAD_INIT);
+ }
+ break;
+
+ case SSH_SFTP_CREATE_DIRS:
+ sshc->slash_pos = strchr(sshc->slash_pos, '/');
+ if(sshc->slash_pos) {
+ *sshc->slash_pos = 0;
+
+ infof(data, "Creating directory '%s'\n", sftp_scp->path);
+ state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ break;
+ }
+ else {
+ state(conn, SSH_SFTP_UPLOAD_INIT);
+ }
+ break;
+
+ case SSH_SFTP_CREATE_DIRS_MKDIR:
+ /* 'mode' - parameter is preliminary - default to 0644 */
+ rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ data->set.new_directory_perms);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ *sshc->slash_pos = '/';
+ ++sshc->slash_pos;
+ if(rc == -1) {
+ /*
+ * Abort if failure wasn't that the dir already exists or the
+ * permission was denied (creation might succeed further down the
+ * path) - retry on unspecific FAILURE also
+ */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
+ (err != LIBSSH2_FX_FAILURE) &&
+ (err != LIBSSH2_FX_PERMISSION_DENIED)) {
+ result = sftp_libssh2_error_to_CURLE(err);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = result?result:CURLE_SSH;
+ break;
+ }
+ }
+ state(conn, SSH_SFTP_CREATE_DIRS);
+ break;
+
+ case SSH_SFTP_READDIR_INIT:
+ Curl_pgrsSetDownloadSize(data, -1);
+ if(data->set.opt_no_body) {
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ /*
+ * This is a directory that we are trying to get, so produce a directory
+ * listing
+ */
+ sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
+ sftp_scp->path,
+ curlx_uztoui(
+ strlen(sftp_scp->path)),
+ 0, 0, LIBSSH2_SFTP_OPENDIR);
+ if(!sshc->sftp_handle) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ failf(data, "Could not open directory for reading: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ break;
+ }
+ }
+ if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
+ Curl_safefree(sshc->readdir_filename);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ state(conn, SSH_SFTP_READDIR);
+ break;
+
+ case SSH_SFTP_READDIR:
+ sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
+ sshc->readdir_filename,
+ PATH_MAX,
+ sshc->readdir_longentry,
+ PATH_MAX,
+ &sshc->readdir_attrs);
+ if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ if(sshc->readdir_len > 0) {
+ sshc->readdir_filename[sshc->readdir_len] = '\0';
+
+ if(data->set.ftp_list_only) {
+ char *tmpLine;
+
+ tmpLine = aprintf("%s\n", sshc->readdir_filename);
+ if(tmpLine == NULL) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ tmpLine, sshc->readdir_len+1);
+ free(tmpLine);
+
+ if(result) {
+ state(conn, SSH_STOP);
+ break;
+ }
+ /* since this counts what we send to the client, we include the
+ newline in this counter */
+ data->req.bytecount += sshc->readdir_len+1;
+
+ /* output debug output if that is requested */
+ if(data->set.verbose) {
+ Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
+ sshc->readdir_len, conn);
+ }
+ }
+ else {
+ sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+ sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
+ sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
+ if(!sshc->readdir_line) {
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ memcpy(sshc->readdir_line, sshc->readdir_longentry,
+ sshc->readdir_currLen);
+ if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFLNK)) {
+ sshc->readdir_linkPath = malloc(PATH_MAX + 1);
+ if(sshc->readdir_linkPath == NULL) {
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
+ sshc->readdir_filename);
+ state(conn, SSH_SFTP_READDIR_LINK);
+ break;
+ }
+ state(conn, SSH_SFTP_READDIR_BOTTOM);
+ break;
+ }
+ }
+ else if(sshc->readdir_len == 0) {
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_READDIR_DONE);
+ break;
+ }
+ else if(sshc->readdir_len <= 0) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ failf(data, "Could not open remote file for reading: %s :: %d",
+ sftp_libssh2_strerror(err),
+ libssh2_session_last_errno(sshc->ssh_session));
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ break;
+ }
+ break;
+
+ case SSH_SFTP_READDIR_LINK:
+ sshc->readdir_len =
+ libssh2_sftp_symlink_ex(sshc->sftp_session,
+ sshc->readdir_linkPath,
+ curlx_uztoui(strlen(sshc->readdir_linkPath)),
+ sshc->readdir_filename,
+ PATH_MAX, LIBSSH2_SFTP_READLINK);
+ if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ Curl_safefree(sshc->readdir_linkPath);
+
+ /* get room for the filename and extra output */
+ sshc->readdir_totalLen += 4 + sshc->readdir_len;
+ new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen);
+ if(!new_readdir_line) {
+ Curl_safefree(sshc->readdir_line);
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ sshc->readdir_line = new_readdir_line;
+
+ sshc->readdir_currLen += snprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen,
+ " -> %s",
+ sshc->readdir_filename);
+
+ state(conn, SSH_SFTP_READDIR_BOTTOM);
+ break;
+
+ case SSH_SFTP_READDIR_BOTTOM:
+ sshc->readdir_currLen += snprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen, "\n");
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ sshc->readdir_line,
+ sshc->readdir_currLen);
+
+ if(!result) {
+
+ /* output debug output if that is requested */
+ if(data->set.verbose) {
+ Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
+ sshc->readdir_currLen, conn);
+ }
+ data->req.bytecount += sshc->readdir_currLen;
+ }
+ Curl_safefree(sshc->readdir_line);
+ if(result) {
+ state(conn, SSH_STOP);
+ }
+ else
+ state(conn, SSH_SFTP_READDIR);
+ break;
+
+ case SSH_SFTP_READDIR_DONE:
+ if(libssh2_sftp_closedir(sshc->sftp_handle) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ sshc->sftp_handle = NULL;
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_SFTP_DOWNLOAD_INIT:
+ /*
+ * Work on getting the specified file
+ */
+ sshc->sftp_handle =
+ libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ LIBSSH2_FXF_READ, data->set.new_file_perms,
+ LIBSSH2_SFTP_OPENFILE);
+ if(!sshc->sftp_handle) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ failf(data, "Could not open remote file for reading: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ break;
+ }
+ }
+ state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ break;
+
+ case SSH_SFTP_DOWNLOAD_STAT:
+ {
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ LIBSSH2_SFTP_STAT, &attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc ||
+ !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
+ (attrs.filesize == 0)) {
+ /*
+ * libssh2_sftp_open() didn't return an error, so maybe the server
+ * just doesn't support stat()
+ * OR the server doesn't return a file size with a stat()
+ * OR file size is 0
+ */
+ data->req.size = -1;
+ data->req.maxdownload = -1;
+ Curl_pgrsSetDownloadSize(data, -1);
+ }
+ else {
+ curl_off_t size = attrs.filesize;
+
+ if(size < 0) {
+ failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ if(conn->data->state.use_range) {
+ curl_off_t from, to;
+ char *ptr;
+ char *ptr2;
+
+ from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
+ while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ ptr++;
+ to=curlx_strtoofft(ptr, &ptr2, 0);
+ if((ptr == ptr2) /* no "to" value given */
+ || (to >= size)) {
+ to = size - 1;
+ }
+ if(from < 0) {
+ /* from is relative to end of file */
+ from += size;
+ }
+ if(from >= size) {
+ failf(data, "Offset (%"
+ CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
+ CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ if(from > to) {
+ from = to;
+ size = 0;
+ }
+ else {
+ size = to - from + 1;
+ }
+
+ SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
+ }
+ data->req.size = size;
+ data->req.maxdownload = size;
+ Curl_pgrsSetDownloadSize(data, size);
+ }
+
+ /* We can resume if we can seek to the resume position */
+ if(data->state.resume_from) {
+ if(data->state.resume_from < 0) {
+ /* We're supposed to download the last abs(from) bytes */
+ if((curl_off_t)attrs.filesize < -data->state.resume_from) {
+ failf(data, "Offset (%"
+ CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
+ CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, attrs.filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ /* download from where? */
+ data->state.resume_from += attrs.filesize;
+ }
+ else {
+ if((curl_off_t)attrs.filesize < data->state.resume_from) {
+ failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
+ ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, attrs.filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ }
+ /* Does a completed file need to be seeked and started or closed ? */
+ /* Now store the number of bytes we are expected to download */
+ data->req.size = attrs.filesize - data->state.resume_from;
+ data->req.maxdownload = attrs.filesize - data->state.resume_from;
+ Curl_pgrsSetDownloadSize(data,
+ attrs.filesize - data->state.resume_from);
+ SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+ }
+ }
+
+ /* Setup the actual download */
+ if(data->req.size == 0) {
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ infof(data, "File already completely downloaded\n");
+ state(conn, SSH_STOP);
+ break;
+ }
+ else {
+ Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
+ FALSE, NULL, -1, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->writesockfd = conn->sockfd;
+
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh2 recv function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_IN;
+ }
+ if(result) {
+ /* this should never occur; the close state should be entered
+ at the time the error occurs */
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = result;
+ }
+ else {
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SFTP_CLOSE:
+ if(sshc->sftp_handle) {
+ rc = libssh2_sftp_close(sshc->sftp_handle);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to close libssh2 file\n");
+ }
+ sshc->sftp_handle = NULL;
+ }
+ if(sftp_scp)
+ Curl_safefree(sftp_scp->path);
+
+ DEBUGF(infof(data, "SFTP DONE done\n"));
+
+ /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
+ After nextstate is executed, the control should come back to
+ SSH_SFTP_CLOSE to pass the correct result back */
+ if(sshc->nextstate != SSH_NO_STATE &&
+ sshc->nextstate != SSH_SFTP_CLOSE) {
+ state(conn, sshc->nextstate);
+ sshc->nextstate = SSH_SFTP_CLOSE;
+ }
+ else {
+ state(conn, SSH_STOP);
+ result = sshc->actualcode;
+ }
+ break;
+
+ case SSH_SFTP_SHUTDOWN:
+ /* during times we get here due to a broken transfer and then the
+ sftp_handle might not have been taken down so make sure that is done
+ before we proceed */
+
+ if(sshc->sftp_handle) {
+ rc = libssh2_sftp_close(sshc->sftp_handle);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to close libssh2 file\n");
+ }
+ sshc->sftp_handle = NULL;
+ }
+ if(sshc->sftp_session) {
+ rc = libssh2_sftp_shutdown(sshc->sftp_session);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to stop libssh2 sftp subsystem\n");
+ }
+ sshc->sftp_session = NULL;
+ }
+
+ Curl_safefree(sshc->homedir);
+ conn->data->state.most_recent_ftp_entrypath = NULL;
+
+ state(conn, SSH_SESSION_DISCONNECT);
+ break;
+
+ case SSH_SCP_TRANS_INIT:
+ result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ if(result) {
+ sshc->actualcode = result;
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ if(data->set.upload) {
+ if(data->state.infilesize < 0) {
+ failf(data, "SCP requires a known file size for upload");
+ sshc->actualcode = CURLE_UPLOAD_FAILED;
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ break;
+ }
+ state(conn, SSH_SCP_UPLOAD_INIT);
+ }
+ else {
+ state(conn, SSH_SCP_DOWNLOAD_INIT);
+ }
+ break;
+
+ case SSH_SCP_UPLOAD_INIT:
+ /*
+ * libssh2 requires that the destination path is a full path that
+ * includes the destination file and name OR ends in a "/" . If this is
+ * not done the destination file will be named the same name as the last
+ * directory in the path.
+ */
+ sshc->ssh_channel =
+ SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
+ data->state.infilesize);
+ if(!sshc->ssh_channel) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ int ssh_err;
+ char *err_msg;
+
+ ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0));
+ failf(conn->data, "%s", err_msg);
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
+ break;
+ }
+ }
+
+ /* upload data */
+ Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
+ FIRSTSOCKET, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->sockfd = conn->writesockfd;
+
+ if(result) {
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = result;
+ }
+ else {
+ /* store this original bitmask setup to use later on if we can't
+ figure out a "real" bitmask */
+ sshc->orig_waitfor = data->req.keepon;
+
+ /* we want to use the _sending_ function even when the socket turns
+ out readable as the underlying libssh2 scp send function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_OUT;
+
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SCP_DOWNLOAD_INIT:
+ {
+ /*
+ * We must check the remote file; if it is a directory no values will
+ * be set in sb
+ */
+ struct stat sb;
+ curl_off_t bytecount;
+
+ /* clear the struct scp recv will fill in */
+ memset(&sb, 0, sizeof(struct stat));
+
+ /* get a fresh new channel from the ssh layer */
+ sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
+ sftp_scp->path, &sb);
+ if(!sshc->ssh_channel) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ int ssh_err;
+ char *err_msg;
+
+ ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0));
+ failf(conn->data, "%s", err_msg);
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
+ break;
+ }
+ }
+
+ /* download data */
+ bytecount = (curl_off_t)sb.st_size;
+ data->req.maxdownload = (curl_off_t)sb.st_size;
+ Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->writesockfd = conn->sockfd;
+
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh2 recv function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_IN;
+
+ if(result) {
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = result;
+ }
+ else
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SCP_DONE:
+ if(data->set.upload)
+ state(conn, SSH_SCP_SEND_EOF);
+ else
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ break;
+
+ case SSH_SCP_SEND_EOF:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_send_eof(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ infof(data, "Failed to send libssh2 channel EOF\n");
+ }
+ }
+ state(conn, SSH_SCP_WAIT_EOF);
+ break;
+
+ case SSH_SCP_WAIT_EOF:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_wait_eof(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ infof(data, "Failed to get channel EOF: %d\n", rc);
+ }
+ }
+ state(conn, SSH_SCP_WAIT_CLOSE);
+ break;
+
+ case SSH_SCP_WAIT_CLOSE:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_wait_closed(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ infof(data, "Channel failed to close: %d\n", rc);
+ }
+ }
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ break;
+
+ case SSH_SCP_CHANNEL_FREE:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_free(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to free libssh2 scp subsystem\n");
+ }
+ sshc->ssh_channel = NULL;
+ }
+ DEBUGF(infof(data, "SCP DONE phase complete\n"));
+#if 0 /* PREV */
+ state(conn, SSH_SESSION_DISCONNECT);
+#endif
+ state(conn, SSH_STOP);
+ result = sshc->actualcode;
+ break;
+
+ case SSH_SESSION_DISCONNECT:
+ /* during weird times when we've been prematurely aborted, the channel
+ is still alive when we reach this state and we MUST kill the channel
+ properly first */
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_free(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to free libssh2 scp subsystem\n");
+ }
+ sshc->ssh_channel = NULL;
+ }
+
+ if(sshc->ssh_session) {
+ rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to disconnect libssh2 session\n");
+ }
+ }
+
+ Curl_safefree(sshc->homedir);
+ conn->data->state.most_recent_ftp_entrypath = NULL;
+
+ state(conn, SSH_SESSION_FREE);
+ break;
+
+ case SSH_SESSION_FREE:
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ if(sshc->kh) {
+ libssh2_knownhost_free(sshc->kh);
+ sshc->kh = NULL;
+ }
+#endif
+
+#ifdef HAVE_LIBSSH2_AGENT_API
+ if(sshc->ssh_agent) {
+ rc = libssh2_agent_disconnect(sshc->ssh_agent);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to disconnect from libssh2 agent\n");
+ }
+ libssh2_agent_free (sshc->ssh_agent);
+ sshc->ssh_agent = NULL;
+
+ /* NB: there is no need to free identities, they are part of internal
+ agent stuff */
+ sshc->sshagent_identity = NULL;
+ sshc->sshagent_prev_identity = NULL;
+ }
+#endif
+
+ if(sshc->ssh_session) {
+ rc = libssh2_session_free(sshc->ssh_session);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to free libssh2 session\n");
+ }
+ sshc->ssh_session = NULL;
+ }
+
+ /* worst-case scenario cleanup */
+
+ DEBUGASSERT(sshc->ssh_session == NULL);
+ DEBUGASSERT(sshc->ssh_channel == NULL);
+ DEBUGASSERT(sshc->sftp_session == NULL);
+ DEBUGASSERT(sshc->sftp_handle == NULL);
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ DEBUGASSERT(sshc->kh == NULL);
+#endif
+#ifdef HAVE_LIBSSH2_AGENT_API
+ DEBUGASSERT(sshc->ssh_agent == NULL);
+#endif
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+
+ Curl_safefree(sshc->homedir);
+
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ Curl_safefree(sshc->readdir_line);
+ Curl_safefree(sshc->readdir_linkPath);
+
+ /* the code we are about to return */
+ result = sshc->actualcode;
+
+ memset(sshc, 0, sizeof(struct ssh_conn));
+
+ connclose(conn, "SSH session free");
+ sshc->state = SSH_SESSION_FREE; /* current */
+ sshc->nextstate = SSH_NO_STATE;
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ sshc->nextstate = SSH_NO_STATE;
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ } while(!rc && (sshc->state != SSH_STOP));
+
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ /* we would block, we need to wait for the socket to be ready (in the
+ right direction too)! */
+ *block = TRUE;
+ }
+
+ return result;
+}
+
+/* called by the multi interface to figure out what socket(s) to wait for and
+ for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
+static int ssh_perform_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks
+ number of sockets */
+ int numsocks)
+{
+#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+ int bitmap = GETSOCK_BLANK;
+ (void)numsocks;
+
+ sock[0] = conn->sock[FIRSTSOCKET];
+
+ if(conn->waitfor & KEEP_RECV)
+ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+
+ if(conn->waitfor & KEEP_SEND)
+ bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
+
+ return bitmap;
+#else
+ /* if we don't know the direction we can use the generic *_getsock()
+ function even for the protocol_connect and doing states */
+ return Curl_single_getsock(conn, sock, numsocks);
+#endif
+}
+
+/* Generic function called by the multi interface to figure out what socket(s)
+ to wait for and for what actions during the DOING and PROTOCONNECT states*/
+static int ssh_getsock(struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks number
+ of sockets */
+ int numsocks)
+{
+#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+ (void)conn;
+ (void)sock;
+ (void)numsocks;
+ /* if we don't know any direction we can just play along as we used to and
+ not provide any sensible info */
+ return GETSOCK_BLANK;
+#else
+ /* if we know the direction we can use the generic *_getsock() function even
+ for the protocol_connect and doing states */
+ return ssh_perform_getsock(conn, sock, numsocks);
+#endif
+}
+
+#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+/*
+ * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
+ * function is used to figure out in what direction and stores this info so
+ * that the multi interface can take advantage of it. Make sure to call this
+ * function in all cases so that when it _doesn't_ return EAGAIN we can
+ * restore the default wait bits.
+ */
+static void ssh_block2waitfor(struct connectdata *conn, bool block)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ int dir;
+ if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
+ /* translate the libssh2 define bits into our own bit defines */
+ conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
+ ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+ }
+ else
+ /* It didn't block or libssh2 didn't reveal in which direction, put back
+ the original set */
+ conn->waitfor = sshc->orig_waitfor;
+}
+#else
+ /* no libssh2 directional support so we simply don't know */
+#define ssh_block2waitfor(x,y) Curl_nop_stmt
+#endif
+
+/* called repeatedly until done from multi.c */
+static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ CURLcode result = CURLE_OK;
+ bool block; /* we store the status and use that to provide a ssh_getsock()
+ implementation */
+
+ result = ssh_statemach_act(conn, &block);
+ *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+ ssh_block2waitfor(conn, block);
+
+ return result;
+}
+
+static CURLcode ssh_block_statemach(struct connectdata *conn,
+ bool duringconnect)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ while((sshc->state != SSH_STOP) && !result) {
+ bool block;
+ long left;
+
+ result = ssh_statemach_act(conn, &block);
+ if(result)
+ break;
+
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ else {
+ struct timeval now = Curl_tvnow();
+ result = Curl_speedcheck(data, now);
+ if(result)
+ break;
+ }
+
+ left = Curl_timeleft(data, NULL, duringconnect);
+ if(left < 0) {
+ failf(data, "Operation timed out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+ if(!result && block) {
+ int dir = libssh2_session_block_directions(sshc->ssh_session);
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ curl_socket_t fd_read = CURL_SOCKET_BAD;
+ curl_socket_t fd_write = CURL_SOCKET_BAD;
+ if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
+ fd_read = sock;
+ if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
+ fd_write = sock;
+ /* wait for the socket to become ready */
+ Curl_socket_ready(fd_read, fd_write,
+ left>1000?1000:left); /* ignore result */
+ }
+#endif
+
+ }
+
+ return result;
+}
+
+/*
+ * SSH setup and connection
+ */
+static CURLcode ssh_setup_connection(struct connectdata *conn)
+{
+ struct SSHPROTO *ssh;
+
+ conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ if(!ssh)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+static Curl_recv scp_recv, sftp_recv;
+static Curl_send scp_send, sftp_send;
+
+/*
+ * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
+ * do protocol-specific actions at connect-time.
+ */
+static CURLcode ssh_connect(struct connectdata *conn, bool *done)
+{
+#ifdef CURL_LIBSSH2_DEBUG
+ curl_socket_t sock;
+#endif
+ struct ssh_conn *ssh;
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+
+ /* initialize per-handle data if not already */
+ if(!data->req.protop)
+ ssh_setup_connection(conn);
+
+ /* We default to persistent connections. We set this already in this connect
+ function to make the re-use checks properly be able to check this bit. */
+ connkeep(conn, "SSH default");
+
+ if(conn->handler->protocol & CURLPROTO_SCP) {
+ conn->recv[FIRSTSOCKET] = scp_recv;
+ conn->send[FIRSTSOCKET] = scp_send;
+ }
+ else {
+ conn->recv[FIRSTSOCKET] = sftp_recv;
+ conn->send[FIRSTSOCKET] = sftp_send;
+ }
+ ssh = &conn->proto.sshc;
+
+#ifdef CURL_LIBSSH2_DEBUG
+ if(conn->user) {
+ infof(data, "User: %s\n", conn->user);
+ }
+ if(conn->passwd) {
+ infof(data, "Password: %s\n", conn->passwd);
+ }
+ sock = conn->sock[FIRSTSOCKET];
+#endif /* CURL_LIBSSH2_DEBUG */
+
+ ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
+ my_libssh2_free,
+ my_libssh2_realloc, conn);
+ if(ssh->ssh_session == NULL) {
+ failf(data, "Failure initialising ssh session");
+ return CURLE_FAILED_INIT;
+ }
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
+ int rc;
+ ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
+ if(!ssh->kh) {
+ /* eeek. TODO: free the ssh_session! */
+ return CURLE_FAILED_INIT;
+ }
+
+ /* read all known hosts from there */
+ rc = libssh2_knownhost_readfile(ssh->kh,
+ data->set.str[STRING_SSH_KNOWNHOSTS],
+ LIBSSH2_KNOWNHOST_FILE_OPENSSH);
+ if(rc < 0)
+ infof(data, "Failed to read known hosts from %s\n",
+ data->set.str[STRING_SSH_KNOWNHOSTS]);
+ }
+#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
+
+#ifdef CURL_LIBSSH2_DEBUG
+ libssh2_trace(ssh->ssh_session, ~0);
+ infof(data, "SSH socket: %d\n", (int)sock);
+#endif /* CURL_LIBSSH2_DEBUG */
+
+ state(conn, SSH_INIT);
+
+ result = ssh_multi_statemach(conn, done);
+
+ return result;
+}
+
+/*
+ ***********************************************************************
+ *
+ * scp_perform()
+ *
+ * This is the actual DO function for SCP. Get a file according to
+ * the options previously setup.
+ */
+
+static
+CURLcode scp_perform(struct connectdata *conn,
+ bool *connected,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* start the first command in the DO phase */
+ state(conn, SSH_SCP_TRANS_INIT);
+
+ /* run the state-machine */
+ result = ssh_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/* called from multi.c while DOing */
+static CURLcode scp_doing(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result;
+ result = ssh_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+ return result;
+}
+
+/*
+ * The DO function is generic for both protocols. There was previously two
+ * separate ones but this way means less duplicated code.
+ */
+
+static CURLcode ssh_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result;
+ bool connected = 0;
+ struct SessionHandle *data = conn->data;
+ struct ssh_conn *sshc = &conn->proto.sshc;
+
+ *done = FALSE; /* default to false */
+
+ data->req.size = -1; /* make sure this is unknown at this point */
+
+ sshc->actualcode = CURLE_OK; /* reset error code */
+ sshc->secondCreateDirs =0; /* reset the create dir attempt state
+ variable */
+
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ if(conn->handler->protocol & CURLPROTO_SCP)
+ result = scp_perform(conn, &connected, done);
+ else
+ result = sftp_perform(conn, &connected, done);
+
+ return result;
+}
+
+/* BLOCKING, but the function is using the state machine so the only reason
+ this is still blocking is that the multi interface code has no support for
+ disconnecting operations that takes a while */
+static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ CURLcode result = CURLE_OK;
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void) dead_connection;
+
+ Curl_safefree(conn->data->req.protop);
+
+ if(ssh->ssh_session) {
+ /* only if there's a session still around to use! */
+
+ state(conn, SSH_SESSION_DISCONNECT);
+
+ result = ssh_block_statemach(conn, FALSE);
+ }
+
+ return result;
+}
+
+/* generic done function for both SCP and SFTP called from their specific
+ done functions */
+static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
+{
+ CURLcode result = CURLE_OK;
+ struct SSHPROTO *sftp_scp = conn->data->req.protop;
+
+ if(!status) {
+ /* run the state-machine
+
+ TODO: when the multi interface is used, this _really_ should be using
+ the ssh_multi_statemach function but we have no general support for
+ non-blocking DONE operations, not in the multi state machine and with
+ Curl_done() invokes on several places in the code!
+ */
+ result = ssh_block_statemach(conn, FALSE);
+ }
+ else
+ result = status;
+
+ if(sftp_scp)
+ Curl_safefree(sftp_scp->path);
+ if(Curl_pgrsDone(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+
+ conn->data->req.keepon = 0; /* clear all bits */
+ return result;
+}
+
+
+static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ (void)premature; /* not used */
+
+ if(!status)
+ state(conn, SSH_SCP_DONE);
+
+ return ssh_done(conn, status);
+
+}
+
+/* return number of received (decrypted) bytes */
+static ssize_t scp_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *err)
+{
+ ssize_t nwrite;
+ (void)sockindex; /* we only support SCP on the fixed known primary socket */
+
+ /* libssh2_channel_write() returns int! */
+ nwrite = (ssize_t)
+ libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
+
+ ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+
+ if(nwrite == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nwrite = 0;
+ }
+ else if(nwrite < LIBSSH2_ERROR_NONE) {
+ *err = libssh2_session_error_to_CURLE((int)nwrite);
+ nwrite = -1;
+ }
+
+ return nwrite;
+}
+
+/*
+ * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
+ * a regular CURLcode value.
+ */
+static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err)
+{
+ ssize_t nread;
+ (void)sockindex; /* we only support SCP on the fixed known primary socket */
+
+ /* libssh2_channel_read() returns int */
+ nread = (ssize_t)
+ libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
+
+ ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ if(nread == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nread = -1;
+ }
+
+ return nread;
+}
+
+/*
+ * =============== SFTP ===============
+ */
+
+/*
+ ***********************************************************************
+ *
+ * sftp_perform()
+ *
+ * This is the actual DO function for SFTP. Get a file/directory according to
+ * the options previously setup.
+ */
+
+static
+CURLcode sftp_perform(struct connectdata *conn,
+ bool *connected,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* start the first command in the DO phase */
+ state(conn, SSH_SFTP_QUOTE_INIT);
+
+ /* run the state-machine */
+ result = ssh_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/* called from multi.c while DOing */
+static CURLcode sftp_doing(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = ssh_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+ return result;
+}
+
+/* BLOCKING, but the function is using the state machine so the only reason
+ this is still blocking is that the multi interface code has no support for
+ disconnecting operations that takes a while */
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ CURLcode result = CURLE_OK;
+ (void) dead_connection;
+
+ DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+
+ Curl_safefree(conn->data->req.protop);
+
+ if(conn->proto.sshc.ssh_session) {
+ /* only if there's a session still around to use! */
+ state(conn, SSH_SFTP_SHUTDOWN);
+ result = ssh_block_statemach(conn, FALSE);
+ }
+
+ DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+
+ return result;
+
+}
+
+static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+
+ if(!status) {
+ /* Post quote commands are executed after the SFTP_CLOSE state to avoid
+ errors that could happen due to open file handles during POSTQUOTE
+ operation */
+ if(!status && !premature && conn->data->set.postquote) {
+ sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
+ state(conn, SSH_SFTP_CLOSE);
+ }
+ else
+ state(conn, SSH_SFTP_CLOSE);
+ }
+ return ssh_done(conn, status);
+}
+
+/* return number of sent bytes */
+static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *err)
+{
+ ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
+ but is changed to ssize_t in 0.15. These days we don't
+ support libssh2 0.15*/
+ (void)sockindex;
+
+ nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
+
+ ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+
+ if(nwrite == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nwrite = 0;
+ }
+ else if(nwrite < LIBSSH2_ERROR_NONE) {
+ *err = libssh2_session_error_to_CURLE((int)nwrite);
+ nwrite = -1;
+ }
+
+ return nwrite;
+}
+
+/*
+ * Return number of received (decrypted) bytes
+ * or <0 on error
+ */
+static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err)
+{
+ ssize_t nread;
+ (void)sockindex;
+
+ nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
+
+ ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+
+ if(nread == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nread = -1;
+
+ }
+ else if(nread < 0) {
+ *err = libssh2_session_error_to_CURLE((int)nread);
+ }
+ return nread;
+}
+
+/* The get_pathname() function is being borrowed from OpenSSH sftp.c
+ version 4.6p1. */
+/*
+ * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+static CURLcode
+get_pathname(const char **cpp, char **path)
+{
+ const char *cp = *cpp, *end;
+ char quot;
+ unsigned int i, j;
+ static const char WHITESPACE[] = " \t\r\n";
+
+ cp += strspn(cp, WHITESPACE);
+ if(!*cp) {
+ *cpp = cp;
+ *path = NULL;
+ return CURLE_QUOTE_ERROR;
+ }
+
+ *path = malloc(strlen(cp) + 1);
+ if(*path == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Check for quoted filenames */
+ if(*cp == '\"' || *cp == '\'') {
+ quot = *cp++;
+
+ /* Search for terminating quote, unescape some chars */
+ for(i = j = 0; i <= strlen(cp); i++) {
+ if(cp[i] == quot) { /* Found quote */
+ i++;
+ (*path)[j] = '\0';
+ break;
+ }
+ if(cp[i] == '\0') { /* End of string */
+ /*error("Unterminated quote");*/
+ goto fail;
+ }
+ if(cp[i] == '\\') { /* Escaped characters */
+ i++;
+ if(cp[i] != '\'' && cp[i] != '\"' &&
+ cp[i] != '\\') {
+ /*error("Bad escaped character '\\%c'",
+ cp[i]);*/
+ goto fail;
+ }
+ }
+ (*path)[j++] = cp[i];
+ }
+
+ if(j == 0) {
+ /*error("Empty quotes");*/
+ goto fail;
+ }
+ *cpp = cp + i + strspn(cp + i, WHITESPACE);
+ }
+ else {
+ /* Read to end of filename */
+ end = strpbrk(cp, WHITESPACE);
+ if(end == NULL)
+ end = strchr(cp, '\0');
+ *cpp = end + strspn(end, WHITESPACE);
+
+ memcpy(*path, cp, end - cp);
+ (*path)[end - cp] = '\0';
+ }
+ return CURLE_OK;
+
+ fail:
+ Curl_safefree(*path);
+ return CURLE_QUOTE_ERROR;
+}
+
+
+static const char *sftp_libssh2_strerror(int err)
+{
+ switch (err) {
+ case LIBSSH2_FX_NO_SUCH_FILE:
+ return "No such file or directory";
+
+ case LIBSSH2_FX_PERMISSION_DENIED:
+ return "Permission denied";
+
+ case LIBSSH2_FX_FAILURE:
+ return "Operation failed";
+
+ case LIBSSH2_FX_BAD_MESSAGE:
+ return "Bad message from SFTP server";
+
+ case LIBSSH2_FX_NO_CONNECTION:
+ return "Not connected to SFTP server";
+
+ case LIBSSH2_FX_CONNECTION_LOST:
+ return "Connection to SFTP server lost";
+
+ case LIBSSH2_FX_OP_UNSUPPORTED:
+ return "Operation not supported by SFTP server";
+
+ case LIBSSH2_FX_INVALID_HANDLE:
+ return "Invalid handle";
+
+ case LIBSSH2_FX_NO_SUCH_PATH:
+ return "No such file or directory";
+
+ case LIBSSH2_FX_FILE_ALREADY_EXISTS:
+ return "File already exists";
+
+ case LIBSSH2_FX_WRITE_PROTECT:
+ return "File is write protected";
+
+ case LIBSSH2_FX_NO_MEDIA:
+ return "No media";
+
+ case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
+ return "Disk full";
+
+ case LIBSSH2_FX_QUOTA_EXCEEDED:
+ return "User quota exceeded";
+
+ case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
+ return "Unknown principle";
+
+ case LIBSSH2_FX_LOCK_CONFlICT:
+ return "File lock conflict";
+
+ case LIBSSH2_FX_DIR_NOT_EMPTY:
+ return "Directory not empty";
+
+ case LIBSSH2_FX_NOT_A_DIRECTORY:
+ return "Not a directory";
+
+ case LIBSSH2_FX_INVALID_FILENAME:
+ return "Invalid filename";
+
+ case LIBSSH2_FX_LINK_LOOP:
+ return "Link points to itself";
+ }
+ return "Unknown error in libssh2";
+}
+
+#endif /* USE_LIBSSH2 */
diff --git a/libcurl/src/lib/ssh.h b/libcurl/src/lib/ssh.h
new file mode 100644
index 0000000..b3cc54c
--- /dev/null
+++ b/libcurl/src/lib/ssh.h
@@ -0,0 +1,195 @@
+#ifndef HEADER_CURL_SSH_H
+#define HEADER_CURL_SSH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIBSSH2_H
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+#endif /* HAVE_LIBSSH2_H */
+
+/****************************************************************************
+ * SSH unique setup
+ ***************************************************************************/
+typedef enum {
+ SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */
+ SSH_STOP = 0, /* do nothing state, stops the state machine */
+
+ SSH_INIT, /* First state in SSH-CONNECT */
+ SSH_S_STARTUP, /* Session startup */
+ SSH_HOSTKEY, /* verify hostkey */
+ SSH_AUTHLIST,
+ SSH_AUTH_PKEY_INIT,
+ SSH_AUTH_PKEY,
+ SSH_AUTH_PASS_INIT,
+ SSH_AUTH_PASS,
+ SSH_AUTH_AGENT_INIT, /* initialize then wait for connection to agent */
+ SSH_AUTH_AGENT_LIST, /* ask for list then wait for entire list to come */
+ SSH_AUTH_AGENT, /* attempt one key at a time */
+ SSH_AUTH_HOST_INIT,
+ SSH_AUTH_HOST,
+ SSH_AUTH_KEY_INIT,
+ SSH_AUTH_KEY,
+ SSH_AUTH_DONE,
+ SSH_SFTP_INIT,
+ SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */
+
+ SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */
+ SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */
+ SSH_SFTP_QUOTE,
+ SSH_SFTP_NEXT_QUOTE,
+ SSH_SFTP_QUOTE_STAT,
+ SSH_SFTP_QUOTE_SETSTAT,
+ SSH_SFTP_QUOTE_SYMLINK,
+ SSH_SFTP_QUOTE_MKDIR,
+ SSH_SFTP_QUOTE_RENAME,
+ SSH_SFTP_QUOTE_RMDIR,
+ SSH_SFTP_QUOTE_UNLINK,
+ SSH_SFTP_TRANS_INIT,
+ SSH_SFTP_UPLOAD_INIT,
+ SSH_SFTP_CREATE_DIRS_INIT,
+ SSH_SFTP_CREATE_DIRS,
+ SSH_SFTP_CREATE_DIRS_MKDIR,
+ SSH_SFTP_READDIR_INIT,
+ SSH_SFTP_READDIR,
+ SSH_SFTP_READDIR_LINK,
+ SSH_SFTP_READDIR_BOTTOM,
+ SSH_SFTP_READDIR_DONE,
+ SSH_SFTP_DOWNLOAD_INIT,
+ SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */
+ SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */
+ SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */
+ SSH_SCP_TRANS_INIT, /* First state in SCP-DO */
+ SSH_SCP_UPLOAD_INIT,
+ SSH_SCP_DOWNLOAD_INIT,
+ SSH_SCP_DONE,
+ SSH_SCP_SEND_EOF,
+ SSH_SCP_WAIT_EOF,
+ SSH_SCP_WAIT_CLOSE,
+ SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */
+ SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */
+ SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */
+ SSH_QUIT,
+ SSH_LAST /* never used */
+} sshstate;
+
+/* this struct is used in the HandleData struct which is part of the
+ SessionHandle, which means this is used on a per-easy handle basis.
+ Everything that is strictly related to a connection is banned from this
+ struct. */
+struct SSHPROTO {
+ char *path; /* the path we operate on */
+};
+
+/* ssh_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct ssh_conn {
+ const char *authlist; /* List of auth. methods, managed by libssh2 */
+#ifdef USE_LIBSSH2
+ const char *passphrase; /* pass-phrase to use */
+ char *rsa_pub; /* path name */
+ char *rsa; /* path name */
+ bool authed; /* the connection has been authenticated fine */
+ sshstate state; /* always use ssh.c:state() to change state! */
+ sshstate nextstate; /* the state to goto after stopping */
+ CURLcode actualcode; /* the actual error code */
+ struct curl_slist *quote_item; /* for the quote option */
+ char *quote_path1; /* two generic pointers for the QUOTE stuff */
+ char *quote_path2;
+ LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
+ bool acceptfail; /* used by the SFTP_QUOTE (continue if
+ quote command fails) */
+ char *homedir; /* when doing SFTP we figure out home dir in the
+ connect phase */
+
+ /* Here's a set of struct members used by the SFTP_READDIR state */
+ LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
+ char *readdir_filename;
+ char *readdir_longentry;
+ int readdir_len, readdir_totalLen, readdir_currLen;
+ char *readdir_line;
+ char *readdir_linkPath;
+ /* end of READDIR stuff */
+
+ int secondCreateDirs; /* counter use by the code to see if the
+ second attempt has been made to change
+ to/create a directory */
+ char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
+ LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
+ LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
+ LIBSSH2_SFTP *sftp_session; /* SFTP handle */
+ LIBSSH2_SFTP_HANDLE *sftp_handle;
+ int orig_waitfor; /* default READ/WRITE bits wait for */
+
+#ifdef HAVE_LIBSSH2_AGENT_API
+ LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */
+ struct libssh2_agent_publickey *sshagent_identity,
+ *sshagent_prev_identity;
+#endif
+
+ /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
+ header */
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ LIBSSH2_KNOWNHOSTS *kh;
+#endif
+#endif /* USE_LIBSSH2 */
+};
+
+#ifdef USE_LIBSSH2
+
+/* Feature detection based on version numbers to better work with
+ non-configure platforms */
+
+#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000)
+# error "SCP/SFTP protocols require libssh2 0.16 or later"
+#endif
+
+#if LIBSSH2_VERSION_NUM >= 0x010000
+#define HAVE_LIBSSH2_SFTP_SEEK64 1
+#endif
+
+#if LIBSSH2_VERSION_NUM >= 0x010100
+#define HAVE_LIBSSH2_VERSION 1
+#endif
+
+#if LIBSSH2_VERSION_NUM >= 0x010205
+#define HAVE_LIBSSH2_INIT 1
+#define HAVE_LIBSSH2_EXIT 1
+#endif
+
+#if LIBSSH2_VERSION_NUM >= 0x010206
+#define HAVE_LIBSSH2_KNOWNHOST_CHECKP 1
+#define HAVE_LIBSSH2_SCP_SEND64 1
+#endif
+
+#if LIBSSH2_VERSION_NUM >= 0x010208
+#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1
+#endif
+
+extern const struct Curl_handler Curl_handler_scp;
+extern const struct Curl_handler Curl_handler_sftp;
+
+#endif /* USE_LIBSSH2 */
+
+#endif /* HEADER_CURL_SSH_H */
diff --git a/libcurl/src/lib/strdup.c b/libcurl/src/lib/strdup.c
new file mode 100644
index 0000000..807ddac
--- /dev/null
+++ b/libcurl/src/lib/strdup.c
@@ -0,0 +1,73 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+#include "strdup.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef HAVE_STRDUP
+CURL_STATIC char *curlx_strdup(const char *str)
+{
+ size_t len;
+ char *newstr;
+
+ if(!str)
+ return (char *)NULL;
+
+ len = strlen(str);
+
+ if(len >= ((size_t)-1) / sizeof(char))
+ return (char *)NULL;
+
+ newstr = malloc((len+1)*sizeof(char));
+ if(!newstr)
+ return (char *)NULL;
+
+ memcpy(newstr, str, (len+1)*sizeof(char));
+
+ return newstr;
+
+}
+#endif
+
+/***************************************************************************
+ *
+ * Curl_memdup(source, length)
+ *
+ * Copies the 'source' data to a newly allocated buffer (that is
+ * returned). Copies 'length' bytes.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+CURL_STATIC char *Curl_memdup(const char *src, size_t length)
+{
+ char *buffer = malloc(length);
+ if(!buffer)
+ return NULL; /* fail */
+
+ memcpy(buffer, src, length);
+
+ return buffer;
+}
diff --git a/libcurl/src/lib/strdup.h b/libcurl/src/lib/strdup.h
new file mode 100644
index 0000000..9058e33
--- /dev/null
+++ b/libcurl/src/lib/strdup.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_STRDUP_H
+#define HEADER_CURL_STRDUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef HAVE_STRDUP
+extern CURL_STATIC char *curlx_strdup(const char *str);
+#endif
+CURL_STATIC char *Curl_memdup(const char *src, size_t buffer_length);
+
+#endif /* HEADER_CURL_STRDUP_H */
diff --git a/libcurl/src/lib/strequal.c b/libcurl/src/lib/strequal.c
new file mode 100644
index 0000000..5f2f508
--- /dev/null
+++ b/libcurl/src/lib/strequal.c
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include "strequal.h"
+
+/*
+ * @unittest: 1301
+ */
+int curl_strequal(const char *first, const char *second)
+{
+#if defined(HAVE_STRCASECMP)
+ return !(strcasecmp)(first, second);
+#elif defined(HAVE_STRCMPI)
+ return !(strcmpi)(first, second);
+#elif defined(HAVE_STRICMP)
+ return !(stricmp)(first, second);
+#else
+ while(*first && *second) {
+ if(toupper(*first) != toupper(*second)) {
+ break;
+ }
+ first++;
+ second++;
+ }
+ return toupper(*first) == toupper(*second);
+#endif
+}
+
+/*
+ * @unittest: 1301
+ */
+int curl_strnequal(const char *first, const char *second, size_t max)
+{
+#if defined(HAVE_STRNCASECMP)
+ return !strncasecmp(first, second, max);
+#elif defined(HAVE_STRNCMPI)
+ return !strncmpi(first, second, max);
+#elif defined(HAVE_STRNICMP)
+ return !strnicmp(first, second, max);
+#else
+ while(*first && *second && max) {
+ if(toupper(*first) != toupper(*second)) {
+ break;
+ }
+ max--;
+ first++;
+ second++;
+ }
+ if(0 == max)
+ return 1; /* they are equal this far */
+
+ return toupper(*first) == toupper(*second);
+#endif
+}
diff --git a/libcurl/src/lib/strequal.h b/libcurl/src/lib/strequal.h
new file mode 100644
index 0000000..117a305
--- /dev/null
+++ b/libcurl/src/lib/strequal.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_STREQUAL_H
+#define HEADER_CURL_STREQUAL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+#define strequal(a,b) curl_strequal(a,b)
+#define strnequal(a,b,c) curl_strnequal(a,b,c)
+
+#endif /* HEADER_CURL_STREQUAL_H */
+
diff --git a/libcurl/src/lib/strerror.c b/libcurl/src/lib/strerror.c
new file mode 100644
index 0000000..b07a534
--- /dev/null
+++ b/libcurl/src/lib/strerror.c
@@ -0,0 +1,1139 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2004 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_STRERROR_R
+# if (!defined(HAVE_POSIX_STRERROR_R) && \
+ !defined(HAVE_GLIBC_STRERROR_R) && \
+ !defined(HAVE_VXWORKS_STRERROR_R)) || \
+ (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
+ (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
+ (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
+# error "strerror_r MUST be either POSIX, glibc or vxworks-style"
+# endif
+#endif
+
+#include <curl/curl.h>
+
+#ifdef USE_LIBIDN
+#include <idna.h>
+#endif
+
+#include "strerror.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+const char *
+curl_easy_strerror(CURLcode error)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (error) {
+ case CURLE_OK:
+ return "No error";
+
+ case CURLE_UNSUPPORTED_PROTOCOL:
+ return "Unsupported protocol";
+
+ case CURLE_FAILED_INIT:
+ return "Failed initialization";
+
+ case CURLE_URL_MALFORMAT:
+ return "URL using bad/illegal format or missing URL";
+
+ case CURLE_NOT_BUILT_IN:
+ return "A requested feature, protocol or option was not found built-in in"
+ " this libcurl due to a build-time decision.";
+
+ case CURLE_COULDNT_RESOLVE_PROXY:
+ return "Couldn't resolve proxy name";
+
+ case CURLE_COULDNT_RESOLVE_HOST:
+ return "Couldn't resolve host name";
+
+ case CURLE_COULDNT_CONNECT:
+ return "Couldn't connect to server";
+
+ case CURLE_FTP_WEIRD_SERVER_REPLY:
+ return "FTP: weird server reply";
+
+ case CURLE_REMOTE_ACCESS_DENIED:
+ return "Access denied to remote resource";
+
+ case CURLE_FTP_ACCEPT_FAILED:
+ return "FTP: The server failed to connect to data port";
+
+ case CURLE_FTP_ACCEPT_TIMEOUT:
+ return "FTP: Accepting server connect has timed out";
+
+ case CURLE_FTP_PRET_FAILED:
+ return "FTP: The server did not accept the PRET command.";
+
+ case CURLE_FTP_WEIRD_PASS_REPLY:
+ return "FTP: unknown PASS reply";
+
+ case CURLE_FTP_WEIRD_PASV_REPLY:
+ return "FTP: unknown PASV reply";
+
+ case CURLE_FTP_WEIRD_227_FORMAT:
+ return "FTP: unknown 227 response format";
+
+ case CURLE_FTP_CANT_GET_HOST:
+ return "FTP: can't figure out the host in the PASV response";
+
+ case CURLE_HTTP2:
+ return "Error in the HTTP2 framing layer";
+
+ case CURLE_FTP_COULDNT_SET_TYPE:
+ return "FTP: couldn't set file type";
+
+ case CURLE_PARTIAL_FILE:
+ return "Transferred a partial file";
+
+ case CURLE_FTP_COULDNT_RETR_FILE:
+ return "FTP: couldn't retrieve (RETR failed) the specified file";
+
+ case CURLE_QUOTE_ERROR:
+ return "Quote command returned error";
+
+ case CURLE_HTTP_RETURNED_ERROR:
+ return "HTTP response code said error";
+
+ case CURLE_WRITE_ERROR:
+ return "Failed writing received data to disk/application";
+
+ case CURLE_UPLOAD_FAILED:
+ return "Upload failed (at start/before it took off)";
+
+ case CURLE_READ_ERROR:
+ return "Failed to open/read local data from file/application";
+
+ case CURLE_OUT_OF_MEMORY:
+ return "Out of memory";
+
+ case CURLE_OPERATION_TIMEDOUT:
+ return "Timeout was reached";
+
+ case CURLE_FTP_PORT_FAILED:
+ return "FTP: command PORT failed";
+
+ case CURLE_FTP_COULDNT_USE_REST:
+ return "FTP: command REST failed";
+
+ case CURLE_RANGE_ERROR:
+ return "Requested range was not delivered by the server";
+
+ case CURLE_HTTP_POST_ERROR:
+ return "Internal problem setting up the POST";
+
+ case CURLE_SSL_CONNECT_ERROR:
+ return "SSL connect error";
+
+ case CURLE_BAD_DOWNLOAD_RESUME:
+ return "Couldn't resume download";
+
+ case CURLE_FILE_COULDNT_READ_FILE:
+ return "Couldn't read a file:// file";
+
+ case CURLE_LDAP_CANNOT_BIND:
+ return "LDAP: cannot bind";
+
+ case CURLE_LDAP_SEARCH_FAILED:
+ return "LDAP: search failed";
+
+ case CURLE_FUNCTION_NOT_FOUND:
+ return "A required function in the library was not found";
+
+ case CURLE_ABORTED_BY_CALLBACK:
+ return "Operation was aborted by an application callback";
+
+ case CURLE_BAD_FUNCTION_ARGUMENT:
+ return "A libcurl function was given a bad argument";
+
+ case CURLE_INTERFACE_FAILED:
+ return "Failed binding local connection end";
+
+ case CURLE_TOO_MANY_REDIRECTS :
+ return "Number of redirects hit maximum amount";
+
+ case CURLE_UNKNOWN_OPTION:
+ return "An unknown option was passed in to libcurl";
+
+ case CURLE_TELNET_OPTION_SYNTAX :
+ return "Malformed telnet option";
+
+ case CURLE_PEER_FAILED_VERIFICATION:
+ return "SSL peer certificate or SSH remote key was not OK";
+
+ case CURLE_GOT_NOTHING:
+ return "Server returned nothing (no headers, no data)";
+
+ case CURLE_SSL_ENGINE_NOTFOUND:
+ return "SSL crypto engine not found";
+
+ case CURLE_SSL_ENGINE_SETFAILED:
+ return "Can not set SSL crypto engine as default";
+
+ case CURLE_SSL_ENGINE_INITFAILED:
+ return "Failed to initialise SSL crypto engine";
+
+ case CURLE_SEND_ERROR:
+ return "Failed sending data to the peer";
+
+ case CURLE_RECV_ERROR:
+ return "Failure when receiving data from the peer";
+
+ case CURLE_SSL_CERTPROBLEM:
+ return "Problem with the local SSL certificate";
+
+ case CURLE_SSL_CIPHER:
+ return "Couldn't use specified SSL cipher";
+
+ case CURLE_SSL_CACERT:
+ return "Peer certificate cannot be authenticated with given CA "
+ "certificates";
+
+ case CURLE_SSL_CACERT_BADFILE:
+ return "Problem with the SSL CA cert (path? access rights?)";
+
+ case CURLE_BAD_CONTENT_ENCODING:
+ return "Unrecognized or bad HTTP Content or Transfer-Encoding";
+
+ case CURLE_LDAP_INVALID_URL:
+ return "Invalid LDAP URL";
+
+ case CURLE_FILESIZE_EXCEEDED:
+ return "Maximum file size exceeded";
+
+ case CURLE_USE_SSL_FAILED:
+ return "Requested SSL level failed";
+
+ case CURLE_SSL_SHUTDOWN_FAILED:
+ return "Failed to shut down the SSL connection";
+
+ case CURLE_SSL_CRL_BADFILE:
+ return "Failed to load CRL file (path? access rights?, format?)";
+
+ case CURLE_SSL_ISSUER_ERROR:
+ return "Issuer check against peer certificate failed";
+
+ case CURLE_SEND_FAIL_REWIND:
+ return "Send failed since rewinding of the data stream failed";
+
+ case CURLE_LOGIN_DENIED:
+ return "Login denied";
+
+ case CURLE_TFTP_NOTFOUND:
+ return "TFTP: File Not Found";
+
+ case CURLE_TFTP_PERM:
+ return "TFTP: Access Violation";
+
+ case CURLE_REMOTE_DISK_FULL:
+ return "Disk full or allocation exceeded";
+
+ case CURLE_TFTP_ILLEGAL:
+ return "TFTP: Illegal operation";
+
+ case CURLE_TFTP_UNKNOWNID:
+ return "TFTP: Unknown transfer ID";
+
+ case CURLE_REMOTE_FILE_EXISTS:
+ return "Remote file already exists";
+
+ case CURLE_TFTP_NOSUCHUSER:
+ return "TFTP: No such user";
+
+ case CURLE_CONV_FAILED:
+ return "Conversion failed";
+
+ case CURLE_CONV_REQD:
+ return "Caller must register CURLOPT_CONV_ callback options";
+
+ case CURLE_REMOTE_FILE_NOT_FOUND:
+ return "Remote file not found";
+
+ case CURLE_SSH:
+ return "Error in the SSH layer";
+
+ case CURLE_AGAIN:
+ return "Socket not ready for send/recv";
+
+ case CURLE_RTSP_CSEQ_ERROR:
+ return "RTSP CSeq mismatch or invalid CSeq";
+
+ case CURLE_RTSP_SESSION_ERROR:
+ return "RTSP session error";
+
+ case CURLE_FTP_BAD_FILE_LIST:
+ return "Unable to parse FTP file list";
+
+ case CURLE_CHUNK_FAILED:
+ return "Chunk callback failed";
+
+ case CURLE_NO_CONNECTION_AVAILABLE:
+ return "The max connection limit is reached";
+
+ case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
+ return "SSL public key does not match pinned public key";
+
+ case CURLE_SSL_INVALIDCERTSTATUS:
+ return "SSL server certificate status verification FAILED";
+
+ /* error codes not used by current libcurl */
+ case CURLE_OBSOLETE20:
+ case CURLE_OBSOLETE24:
+ case CURLE_OBSOLETE29:
+ case CURLE_OBSOLETE32:
+ case CURLE_OBSOLETE40:
+ case CURLE_OBSOLETE44:
+ case CURLE_OBSOLETE46:
+ case CURLE_OBSOLETE50:
+ case CURLE_OBSOLETE57:
+ case CURL_LAST:
+ break;
+ }
+ /*
+ * By using a switch, gcc -Wall will complain about enum values
+ * which do not appear, helping keep this function up-to-date.
+ * By using gcc -Wall -Werror, you can't forget.
+ *
+ * A table would not have the same benefit. Most compilers will
+ * generate code very similar to a table in any case, so there
+ * is little performance gain from a table. And something is broken
+ * for the user's application, anyways, so does it matter how fast
+ * it _doesn't_ work?
+ *
+ * The line number for the error will be near this comment, which
+ * is why it is here, and not at the start of the switch.
+ */
+ return "Unknown error";
+#else
+ if(!error)
+ return "No error";
+ else
+ return "Error";
+#endif
+}
+
+const char *
+curl_multi_strerror(CURLMcode error)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (error) {
+ case CURLM_CALL_MULTI_PERFORM:
+ return "Please call curl_multi_perform() soon";
+
+ case CURLM_OK:
+ return "No error";
+
+ case CURLM_BAD_HANDLE:
+ return "Invalid multi handle";
+
+ case CURLM_BAD_EASY_HANDLE:
+ return "Invalid easy handle";
+
+ case CURLM_OUT_OF_MEMORY:
+ return "Out of memory";
+
+ case CURLM_INTERNAL_ERROR:
+ return "Internal error";
+
+ case CURLM_BAD_SOCKET:
+ return "Invalid socket argument";
+
+ case CURLM_UNKNOWN_OPTION:
+ return "Unknown option";
+
+ case CURLM_ADDED_ALREADY:
+ return "The easy handle is already added to a multi handle";
+
+ case CURLM_LAST:
+ break;
+ }
+
+ return "Unknown error";
+#else
+ if(error == CURLM_OK)
+ return "No error";
+ else
+ return "Error";
+#endif
+}
+
+const char *
+curl_share_strerror(CURLSHcode error)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (error) {
+ case CURLSHE_OK:
+ return "No error";
+
+ case CURLSHE_BAD_OPTION:
+ return "Unknown share option";
+
+ case CURLSHE_IN_USE:
+ return "Share currently in use";
+
+ case CURLSHE_INVALID:
+ return "Invalid share handle";
+
+ case CURLSHE_NOMEM:
+ return "Out of memory";
+
+ case CURLSHE_NOT_BUILT_IN:
+ return "Feature not enabled in this library";
+
+ case CURLSHE_LAST:
+ break;
+ }
+
+ return "CURLSHcode unknown";
+#else
+ if(error == CURLSHE_OK)
+ return "No error";
+ else
+ return "Error";
+#endif
+}
+
+#ifdef USE_WINSOCK
+
+/* This function handles most / all (?) Winsock errors cURL is able to produce.
+ */
+static const char *
+get_winsock_error (int err, char *buf, size_t len)
+{
+ const char *p;
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (err) {
+ case WSAEINTR:
+ p = "Call interrupted";
+ break;
+ case WSAEBADF:
+ p = "Bad file";
+ break;
+ case WSAEACCES:
+ p = "Bad access";
+ break;
+ case WSAEFAULT:
+ p = "Bad argument";
+ break;
+ case WSAEINVAL:
+ p = "Invalid arguments";
+ break;
+ case WSAEMFILE:
+ p = "Out of file descriptors";
+ break;
+ case WSAEWOULDBLOCK:
+ p = "Call would block";
+ break;
+ case WSAEINPROGRESS:
+ case WSAEALREADY:
+ p = "Blocking call in progress";
+ break;
+ case WSAENOTSOCK:
+ p = "Descriptor is not a socket";
+ break;
+ case WSAEDESTADDRREQ:
+ p = "Need destination address";
+ break;
+ case WSAEMSGSIZE:
+ p = "Bad message size";
+ break;
+ case WSAEPROTOTYPE:
+ p = "Bad protocol";
+ break;
+ case WSAENOPROTOOPT:
+ p = "Protocol option is unsupported";
+ break;
+ case WSAEPROTONOSUPPORT:
+ p = "Protocol is unsupported";
+ break;
+ case WSAESOCKTNOSUPPORT:
+ p = "Socket is unsupported";
+ break;
+ case WSAEOPNOTSUPP:
+ p = "Operation not supported";
+ break;
+ case WSAEAFNOSUPPORT:
+ p = "Address family not supported";
+ break;
+ case WSAEPFNOSUPPORT:
+ p = "Protocol family not supported";
+ break;
+ case WSAEADDRINUSE:
+ p = "Address already in use";
+ break;
+ case WSAEADDRNOTAVAIL:
+ p = "Address not available";
+ break;
+ case WSAENETDOWN:
+ p = "Network down";
+ break;
+ case WSAENETUNREACH:
+ p = "Network unreachable";
+ break;
+ case WSAENETRESET:
+ p = "Network has been reset";
+ break;
+ case WSAECONNABORTED:
+ p = "Connection was aborted";
+ break;
+ case WSAECONNRESET:
+ p = "Connection was reset";
+ break;
+ case WSAENOBUFS:
+ p = "No buffer space";
+ break;
+ case WSAEISCONN:
+ p = "Socket is already connected";
+ break;
+ case WSAENOTCONN:
+ p = "Socket is not connected";
+ break;
+ case WSAESHUTDOWN:
+ p = "Socket has been shut down";
+ break;
+ case WSAETOOMANYREFS:
+ p = "Too many references";
+ break;
+ case WSAETIMEDOUT:
+ p = "Timed out";
+ break;
+ case WSAECONNREFUSED:
+ p = "Connection refused";
+ break;
+ case WSAELOOP:
+ p = "Loop??";
+ break;
+ case WSAENAMETOOLONG:
+ p = "Name too long";
+ break;
+ case WSAEHOSTDOWN:
+ p = "Host down";
+ break;
+ case WSAEHOSTUNREACH:
+ p = "Host unreachable";
+ break;
+ case WSAENOTEMPTY:
+ p = "Not empty";
+ break;
+ case WSAEPROCLIM:
+ p = "Process limit reached";
+ break;
+ case WSAEUSERS:
+ p = "Too many users";
+ break;
+ case WSAEDQUOT:
+ p = "Bad quota";
+ break;
+ case WSAESTALE:
+ p = "Something is stale";
+ break;
+ case WSAEREMOTE:
+ p = "Remote error";
+ break;
+#ifdef WSAEDISCON /* missing in SalfordC! */
+ case WSAEDISCON:
+ p = "Disconnected";
+ break;
+#endif
+ /* Extended Winsock errors */
+ case WSASYSNOTREADY:
+ p = "Winsock library is not ready";
+ break;
+ case WSANOTINITIALISED:
+ p = "Winsock library not initialised";
+ break;
+ case WSAVERNOTSUPPORTED:
+ p = "Winsock version not supported";
+ break;
+
+ /* getXbyY() errors (already handled in herrmsg):
+ * Authoritative Answer: Host not found */
+ case WSAHOST_NOT_FOUND:
+ p = "Host not found";
+ break;
+
+ /* Non-Authoritative: Host not found, or SERVERFAIL */
+ case WSATRY_AGAIN:
+ p = "Host not found, try again";
+ break;
+
+ /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+ case WSANO_RECOVERY:
+ p = "Unrecoverable error in call to nameserver";
+ break;
+
+ /* Valid name, no data record of requested type */
+ case WSANO_DATA:
+ p = "No data record of requested type";
+ break;
+
+ default:
+ return NULL;
+ }
+#else
+ if(!err)
+ return NULL;
+ else
+ p = "error";
+#endif
+ strncpy (buf, p, len);
+ buf [len-1] = '\0';
+ return buf;
+}
+#endif /* USE_WINSOCK */
+
+/*
+ * Our thread-safe and smart strerror() replacement.
+ *
+ * The 'err' argument passed in to this function MUST be a true errno number
+ * as reported on this system. We do no range checking on the number before
+ * we pass it to the "number-to-message" conversion function and there might
+ * be systems that don't do proper range checking in there themselves.
+ *
+ * We don't do range checking (on systems other than Windows) since there is
+ * no good reliable and portable way to do it.
+ */
+CURL_STATIC const char *Curl_strerror(struct connectdata *conn, int err)
+{
+ char *buf, *p;
+ size_t max;
+ int old_errno = ERRNO;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(err >= 0);
+
+ buf = conn->syserr_buf;
+ max = sizeof(conn->syserr_buf)-1;
+ *buf = '\0';
+
+#ifdef USE_WINSOCK
+
+#ifdef _WIN32_WCE
+ {
+ wchar_t wbuf[256];
+ wbuf[0] = L'\0';
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL);
+ wcstombs(buf, wbuf, max);
+ }
+#elif defined(CURL_WINRT)
+ {
+ wchar_t wbuf[256];
+ wbuf[0] = L'\0';
+
+ FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ LANG_NEUTRAL, wbuf, sizeof(wbuf) / sizeof(wchar_t), NULL);
+ wcstombs(buf, wbuf, max);
+ }
+#else
+ /* 'sys_nerr' is the maximum errno number, it is not widely portable */
+ if(err >= 0 && err < sys_nerr)
+ strncpy(buf, strerror(err), max);
+ else {
+ if(!get_winsock_error(err, buf, max) &&
+ !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ LANG_NEUTRAL, buf, (DWORD)max, NULL))
+ snprintf(buf, max, "Unknown error %d (%#x)", err, err);
+ }
+#endif
+
+#else /* not USE_WINSOCK coming up */
+
+#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
+ /*
+ * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
+ * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
+ * message string, or EINVAL if 'errnum' is not a valid error number.
+ */
+ if(0 != strerror_r(err, buf, max)) {
+ if('\0' == buf[0])
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
+ /*
+ * The glibc-style strerror_r() only *might* use the buffer we pass to
+ * the function, but it always returns the error message as a pointer,
+ * so we must copy that string unconditionally (if non-NULL).
+ */
+ {
+ char buffer[256];
+ char *msg = strerror_r(err, buffer, sizeof(buffer));
+ if(msg)
+ strncpy(buf, msg, max);
+ else
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
+ /*
+ * The vxworks-style strerror_r() does use the buffer we pass to the function.
+ * The buffer size should be at least NAME_MAX (256)
+ */
+ {
+ char buffer[256];
+ if(OK == strerror_r(err, buffer))
+ strncpy(buf, buffer, max);
+ else
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#else
+ {
+ char *msg = strerror(err);
+ if(msg)
+ strncpy(buf, msg, max);
+ else
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#endif
+
+#endif /* end of ! USE_WINSOCK */
+
+ buf[max] = '\0'; /* make sure the string is zero terminated */
+
+ /* strip trailing '\r\n' or '\n'. */
+ if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2)
+ *p = '\0';
+ if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1)
+ *p = '\0';
+
+ if(old_errno != ERRNO)
+ SET_ERRNO(old_errno);
+
+ return buf;
+}
+
+#ifdef USE_LIBIDN
+/*
+ * Return error-string for libidn status as returned from idna_to_ascii_lz().
+ */
+CURL_STATIC const char *Curl_idn_strerror (struct connectdata *conn, int err)
+{
+#ifdef HAVE_IDNA_STRERROR
+ (void)conn;
+ return idna_strerror((Idna_rc) err);
+#else
+ const char *str;
+ char *buf;
+ size_t max;
+
+ DEBUGASSERT(conn);
+
+ buf = conn->syserr_buf;
+ max = sizeof(conn->syserr_buf)-1;
+ *buf = '\0';
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch ((Idna_rc)err) {
+ case IDNA_SUCCESS:
+ str = "No error";
+ break;
+ case IDNA_STRINGPREP_ERROR:
+ str = "Error in string preparation";
+ break;
+ case IDNA_PUNYCODE_ERROR:
+ str = "Error in Punycode operation";
+ break;
+ case IDNA_CONTAINS_NON_LDH:
+ str = "Illegal ASCII characters";
+ break;
+ case IDNA_CONTAINS_MINUS:
+ str = "Contains minus";
+ break;
+ case IDNA_INVALID_LENGTH:
+ str = "Invalid output length";
+ break;
+ case IDNA_NO_ACE_PREFIX:
+ str = "No ACE prefix (\"xn--\")";
+ break;
+ case IDNA_ROUNDTRIP_VERIFY_ERROR:
+ str = "Round trip verify error";
+ break;
+ case IDNA_CONTAINS_ACE_PREFIX:
+ str = "Already have ACE prefix (\"xn--\")";
+ break;
+ case IDNA_ICONV_ERROR:
+ str = "Locale conversion failed";
+ break;
+ case IDNA_MALLOC_ERROR:
+ str = "Allocation failed";
+ break;
+ case IDNA_DLOPEN_ERROR:
+ str = "dlopen() error";
+ break;
+ default:
+ snprintf(buf, max, "error %d", err);
+ str = NULL;
+ break;
+ }
+#else
+ if((Idna_rc)err == IDNA_SUCCESS)
+ str = "No error";
+ else
+ str = "Error";
+#endif
+ if(str)
+ strncpy(buf, str, max);
+ buf[max] = '\0';
+ return (buf);
+#endif
+}
+#endif /* USE_LIBIDN */
+
+#ifdef USE_WINDOWS_SSPI
+CURL_STATIC const char *Curl_sspi_strerror (struct connectdata *conn, int err)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ char txtbuf[80];
+ char msgbuf[sizeof(conn->syserr_buf)];
+ char *p, *str, *msg = NULL;
+ bool msg_formatted = FALSE;
+ int old_errno;
+#endif
+ const char *txt;
+ char *outbuf;
+ size_t outmax;
+
+ DEBUGASSERT(conn);
+
+ outbuf = conn->syserr_buf;
+ outmax = sizeof(conn->syserr_buf)-1;
+ *outbuf = '\0';
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+
+ old_errno = ERRNO;
+
+ switch (err) {
+ case SEC_E_OK:
+ txt = "No error";
+ break;
+ case SEC_E_ALGORITHM_MISMATCH:
+ txt = "SEC_E_ALGORITHM_MISMATCH";
+ break;
+ case SEC_E_BAD_BINDINGS:
+ txt = "SEC_E_BAD_BINDINGS";
+ break;
+ case SEC_E_BAD_PKGID:
+ txt = "SEC_E_BAD_PKGID";
+ break;
+ case SEC_E_BUFFER_TOO_SMALL:
+ txt = "SEC_E_BUFFER_TOO_SMALL";
+ break;
+ case SEC_E_CANNOT_INSTALL:
+ txt = "SEC_E_CANNOT_INSTALL";
+ break;
+ case SEC_E_CANNOT_PACK:
+ txt = "SEC_E_CANNOT_PACK";
+ break;
+ case SEC_E_CERT_EXPIRED:
+ txt = "SEC_E_CERT_EXPIRED";
+ break;
+ case SEC_E_CERT_UNKNOWN:
+ txt = "SEC_E_CERT_UNKNOWN";
+ break;
+ case SEC_E_CERT_WRONG_USAGE:
+ txt = "SEC_E_CERT_WRONG_USAGE";
+ break;
+ case SEC_E_CONTEXT_EXPIRED:
+ txt = "SEC_E_CONTEXT_EXPIRED";
+ break;
+ case SEC_E_CROSSREALM_DELEGATION_FAILURE:
+ txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE";
+ break;
+ case SEC_E_CRYPTO_SYSTEM_INVALID:
+ txt = "SEC_E_CRYPTO_SYSTEM_INVALID";
+ break;
+ case SEC_E_DECRYPT_FAILURE:
+ txt = "SEC_E_DECRYPT_FAILURE";
+ break;
+ case SEC_E_DELEGATION_POLICY:
+ txt = "SEC_E_DELEGATION_POLICY";
+ break;
+ case SEC_E_DELEGATION_REQUIRED:
+ txt = "SEC_E_DELEGATION_REQUIRED";
+ break;
+ case SEC_E_DOWNGRADE_DETECTED:
+ txt = "SEC_E_DOWNGRADE_DETECTED";
+ break;
+ case SEC_E_ENCRYPT_FAILURE:
+ txt = "SEC_E_ENCRYPT_FAILURE";
+ break;
+ case SEC_E_ILLEGAL_MESSAGE:
+ txt = "SEC_E_ILLEGAL_MESSAGE";
+ break;
+ case SEC_E_INCOMPLETE_CREDENTIALS:
+ txt = "SEC_E_INCOMPLETE_CREDENTIALS";
+ break;
+ case SEC_E_INCOMPLETE_MESSAGE:
+ txt = "SEC_E_INCOMPLETE_MESSAGE";
+ break;
+ case SEC_E_INSUFFICIENT_MEMORY:
+ txt = "SEC_E_INSUFFICIENT_MEMORY";
+ break;
+ case SEC_E_INTERNAL_ERROR:
+ txt = "SEC_E_INTERNAL_ERROR";
+ break;
+ case SEC_E_INVALID_HANDLE:
+ txt = "SEC_E_INVALID_HANDLE";
+ break;
+ case SEC_E_INVALID_PARAMETER:
+ txt = "SEC_E_INVALID_PARAMETER";
+ break;
+ case SEC_E_INVALID_TOKEN:
+ txt = "SEC_E_INVALID_TOKEN";
+ break;
+ case SEC_E_ISSUING_CA_UNTRUSTED:
+ txt = "SEC_E_ISSUING_CA_UNTRUSTED";
+ break;
+ case SEC_E_ISSUING_CA_UNTRUSTED_KDC:
+ txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC";
+ break;
+ case SEC_E_KDC_CERT_EXPIRED:
+ txt = "SEC_E_KDC_CERT_EXPIRED";
+ break;
+ case SEC_E_KDC_CERT_REVOKED:
+ txt = "SEC_E_KDC_CERT_REVOKED";
+ break;
+ case SEC_E_KDC_INVALID_REQUEST:
+ txt = "SEC_E_KDC_INVALID_REQUEST";
+ break;
+ case SEC_E_KDC_UNABLE_TO_REFER:
+ txt = "SEC_E_KDC_UNABLE_TO_REFER";
+ break;
+ case SEC_E_KDC_UNKNOWN_ETYPE:
+ txt = "SEC_E_KDC_UNKNOWN_ETYPE";
+ break;
+ case SEC_E_LOGON_DENIED:
+ txt = "SEC_E_LOGON_DENIED";
+ break;
+ case SEC_E_MAX_REFERRALS_EXCEEDED:
+ txt = "SEC_E_MAX_REFERRALS_EXCEEDED";
+ break;
+ case SEC_E_MESSAGE_ALTERED:
+ txt = "SEC_E_MESSAGE_ALTERED";
+ break;
+ case SEC_E_MULTIPLE_ACCOUNTS:
+ txt = "SEC_E_MULTIPLE_ACCOUNTS";
+ break;
+ case SEC_E_MUST_BE_KDC:
+ txt = "SEC_E_MUST_BE_KDC";
+ break;
+ case SEC_E_NOT_OWNER:
+ txt = "SEC_E_NOT_OWNER";
+ break;
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY";
+ break;
+ case SEC_E_NO_CREDENTIALS:
+ txt = "SEC_E_NO_CREDENTIALS";
+ break;
+ case SEC_E_NO_IMPERSONATION:
+ txt = "SEC_E_NO_IMPERSONATION";
+ break;
+ case SEC_E_NO_IP_ADDRESSES:
+ txt = "SEC_E_NO_IP_ADDRESSES";
+ break;
+ case SEC_E_NO_KERB_KEY:
+ txt = "SEC_E_NO_KERB_KEY";
+ break;
+ case SEC_E_NO_PA_DATA:
+ txt = "SEC_E_NO_PA_DATA";
+ break;
+ case SEC_E_NO_S4U_PROT_SUPPORT:
+ txt = "SEC_E_NO_S4U_PROT_SUPPORT";
+ break;
+ case SEC_E_NO_TGT_REPLY:
+ txt = "SEC_E_NO_TGT_REPLY";
+ break;
+ case SEC_E_OUT_OF_SEQUENCE:
+ txt = "SEC_E_OUT_OF_SEQUENCE";
+ break;
+ case SEC_E_PKINIT_CLIENT_FAILURE:
+ txt = "SEC_E_PKINIT_CLIENT_FAILURE";
+ break;
+ case SEC_E_PKINIT_NAME_MISMATCH:
+ txt = "SEC_E_PKINIT_NAME_MISMATCH";
+ break;
+ case SEC_E_POLICY_NLTM_ONLY:
+ txt = "SEC_E_POLICY_NLTM_ONLY";
+ break;
+ case SEC_E_QOP_NOT_SUPPORTED:
+ txt = "SEC_E_QOP_NOT_SUPPORTED";
+ break;
+ case SEC_E_REVOCATION_OFFLINE_C:
+ txt = "SEC_E_REVOCATION_OFFLINE_C";
+ break;
+ case SEC_E_REVOCATION_OFFLINE_KDC:
+ txt = "SEC_E_REVOCATION_OFFLINE_KDC";
+ break;
+ case SEC_E_SECPKG_NOT_FOUND:
+ txt = "SEC_E_SECPKG_NOT_FOUND";
+ break;
+ case SEC_E_SECURITY_QOS_FAILED:
+ txt = "SEC_E_SECURITY_QOS_FAILED";
+ break;
+ case SEC_E_SHUTDOWN_IN_PROGRESS:
+ txt = "SEC_E_SHUTDOWN_IN_PROGRESS";
+ break;
+ case SEC_E_SMARTCARD_CERT_EXPIRED:
+ txt = "SEC_E_SMARTCARD_CERT_EXPIRED";
+ break;
+ case SEC_E_SMARTCARD_CERT_REVOKED:
+ txt = "SEC_E_SMARTCARD_CERT_REVOKED";
+ break;
+ case SEC_E_SMARTCARD_LOGON_REQUIRED:
+ txt = "SEC_E_SMARTCARD_LOGON_REQUIRED";
+ break;
+ case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
+ txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED";
+ break;
+ case SEC_E_TARGET_UNKNOWN:
+ txt = "SEC_E_TARGET_UNKNOWN";
+ break;
+ case SEC_E_TIME_SKEW:
+ txt = "SEC_E_TIME_SKEW";
+ break;
+ case SEC_E_TOO_MANY_PRINCIPALS:
+ txt = "SEC_E_TOO_MANY_PRINCIPALS";
+ break;
+ case SEC_E_UNFINISHED_CONTEXT_DELETED:
+ txt = "SEC_E_UNFINISHED_CONTEXT_DELETED";
+ break;
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ txt = "SEC_E_UNKNOWN_CREDENTIALS";
+ break;
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ txt = "SEC_E_UNSUPPORTED_FUNCTION";
+ break;
+ case SEC_E_UNSUPPORTED_PREAUTH:
+ txt = "SEC_E_UNSUPPORTED_PREAUTH";
+ break;
+ case SEC_E_UNTRUSTED_ROOT:
+ txt = "SEC_E_UNTRUSTED_ROOT";
+ break;
+ case SEC_E_WRONG_CREDENTIAL_HANDLE:
+ txt = "SEC_E_WRONG_CREDENTIAL_HANDLE";
+ break;
+ case SEC_E_WRONG_PRINCIPAL:
+ txt = "SEC_E_WRONG_PRINCIPAL";
+ break;
+ case SEC_I_COMPLETE_AND_CONTINUE:
+ txt = "SEC_I_COMPLETE_AND_CONTINUE";
+ break;
+ case SEC_I_COMPLETE_NEEDED:
+ txt = "SEC_I_COMPLETE_NEEDED";
+ break;
+ case SEC_I_CONTEXT_EXPIRED:
+ txt = "SEC_I_CONTEXT_EXPIRED";
+ break;
+ case SEC_I_CONTINUE_NEEDED:
+ txt = "SEC_I_CONTINUE_NEEDED";
+ break;
+ case SEC_I_INCOMPLETE_CREDENTIALS:
+ txt = "SEC_I_INCOMPLETE_CREDENTIALS";
+ break;
+ case SEC_I_LOCAL_LOGON:
+ txt = "SEC_I_LOCAL_LOGON";
+ break;
+ case SEC_I_NO_LSA_CONTEXT:
+ txt = "SEC_I_NO_LSA_CONTEXT";
+ break;
+ case SEC_I_RENEGOTIATE:
+ txt = "SEC_I_RENEGOTIATE";
+ break;
+ case SEC_I_SIGNATURE_NEEDED:
+ txt = "SEC_I_SIGNATURE_NEEDED";
+ break;
+ default:
+ txt = "Unknown error";
+ }
+
+ if(err == SEC_E_OK)
+ strncpy(outbuf, txt, outmax);
+ else {
+ str = txtbuf;
+ snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)",
+ txt, (err >> 16) & 0xffff, err & 0xffff);
+ txtbuf[sizeof(txtbuf)-1] = '\0';
+
+#ifdef _WIN32_WCE
+ {
+ wchar_t wbuf[256];
+ wbuf[0] = L'\0';
+
+ if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, LANG_NEUTRAL,
+ wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
+ wcstombs(msgbuf, wbuf, sizeof(msgbuf)-1);
+ msg_formatted = TRUE;
+ }
+ }
+#else
+ if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, LANG_NEUTRAL,
+ msgbuf, sizeof(msgbuf)-1, NULL)) {
+ msg_formatted = TRUE;
+ }
+#endif
+ if(msg_formatted) {
+ msgbuf[sizeof(msgbuf)-1] = '\0';
+ /* strip trailing '\r\n' or '\n' */
+ if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2)
+ *p = '\0';
+ if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1)
+ *p = '\0';
+ msg = msgbuf;
+ }
+ if(msg)
+ snprintf(outbuf, outmax, "%s - %s", str, msg);
+ else
+ strncpy(outbuf, str, outmax);
+ }
+
+ if(old_errno != ERRNO)
+ SET_ERRNO(old_errno);
+
+#else
+
+ if(err == SEC_E_OK)
+ txt = "No error";
+ else
+ txt = "Error";
+
+ strncpy(outbuf, txt, outmax);
+
+#endif
+
+ outbuf[outmax] = '\0';
+
+ return outbuf;
+}
+#endif /* USE_WINDOWS_SSPI */
diff --git a/libcurl/src/lib/strerror.h b/libcurl/src/lib/strerror.h
new file mode 100644
index 0000000..b0f1675
--- /dev/null
+++ b/libcurl/src/lib/strerror.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_STRERROR_H
+#define HEADER_CURL_STRERROR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "urldata.h"
+
+CURL_STATIC const char *Curl_strerror (struct connectdata *conn, int err);
+
+#ifdef USE_LIBIDN
+CURL_STATIC const char *Curl_idn_strerror (struct connectdata *conn, int err);
+#endif
+
+#ifdef USE_WINDOWS_SSPI
+CURL_STATIC const char *Curl_sspi_strerror (struct connectdata *conn, int err);
+#endif
+
+#endif /* HEADER_CURL_STRERROR_H */
diff --git a/libcurl/src/lib/strtok.c b/libcurl/src/lib/strtok.c
new file mode 100644
index 0000000..9a1fdf1
--- /dev/null
+++ b/libcurl/src/lib/strtok.c
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef HAVE_STRTOK_R
+#include <stddef.h>
+
+#include "strtok.h"
+
+CURL_STATIC char *
+Curl_strtok_r(char *ptr, const char *sep, char **end)
+{
+ if(!ptr)
+ /* we got NULL input so then we get our last position instead */
+ ptr = *end;
+
+ /* pass all letters that are including in the separator string */
+ while(*ptr && strchr(sep, *ptr))
+ ++ptr;
+
+ if(*ptr) {
+ /* so this is where the next piece of string starts */
+ char *start = ptr;
+
+ /* set the end pointer to the first byte after the start */
+ *end = start + 1;
+
+ /* scan through the string to find where it ends, it ends on a
+ null byte or a character that exists in the separator string */
+ while(**end && !strchr(sep, **end))
+ ++*end;
+
+ if(**end) {
+ /* the end is not a null byte */
+ **end = '\0'; /* zero terminate it! */
+ ++*end; /* advance the last pointer to beyond the null byte */
+ }
+
+ return start; /* return the position where the string starts */
+ }
+
+ /* we ended up on a null byte, there are no more strings to find! */
+ return NULL;
+}
+
+#endif /* this was only compiled if strtok_r wasn't present */
diff --git a/libcurl/src/lib/strtok.h b/libcurl/src/lib/strtok.h
new file mode 100644
index 0000000..c2fa92d
--- /dev/null
+++ b/libcurl/src/lib/strtok.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_STRTOK_H
+#define HEADER_CURL_STRTOK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+#include <stddef.h>
+
+#ifndef HAVE_STRTOK_R
+CURL_STATIC char *Curl_strtok_r(char *s, const char *delim, char **last);
+#define strtok_r Curl_strtok_r
+#else
+#include <string.h>
+#endif
+
+#endif /* HEADER_CURL_STRTOK_H */
diff --git a/libcurl/src/lib/strtoofft.c b/libcurl/src/lib/strtoofft.c
new file mode 100644
index 0000000..e6da0af
--- /dev/null
+++ b/libcurl/src/lib/strtoofft.c
@@ -0,0 +1,188 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "strtoofft.h"
+
+/*
+ * NOTE:
+ *
+ * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
+ * could use in case strtoll() doesn't exist... See
+ * http://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
+ */
+
+#ifdef NEED_CURL_STRTOLL
+
+/* Range tests can be used for alphanum decoding if characters are consecutive,
+ like in ASCII. Else an array is scanned. Determine this condition now. */
+
+#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
+
+#define NO_RANGE_TEST
+
+static const char valchars[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+#endif
+
+static int get_char(char c, int base);
+
+/**
+ * Emulated version of the strtoll function. This extracts a long long
+ * value from the given input string and returns it.
+ */
+CURL_STATIC curl_off_t
+curlx_strtoll(const char *nptr, char **endptr, int base)
+{
+ char *end;
+ int is_negative = 0;
+ int overflow;
+ int i;
+ curl_off_t value = 0;
+ curl_off_t newval;
+
+ /* Skip leading whitespace. */
+ end = (char *)nptr;
+ while(ISSPACE(end[0])) {
+ end++;
+ }
+
+ /* Handle the sign, if any. */
+ if(end[0] == '-') {
+ is_negative = 1;
+ end++;
+ }
+ else if(end[0] == '+') {
+ end++;
+ }
+ else if(end[0] == '\0') {
+ /* We had nothing but perhaps some whitespace -- there was no number. */
+ if(endptr) {
+ *endptr = end;
+ }
+ return 0;
+ }
+
+ /* Handle special beginnings, if present and allowed. */
+ if(end[0] == '0' && end[1] == 'x') {
+ if(base == 16 || base == 0) {
+ end += 2;
+ base = 16;
+ }
+ }
+ else if(end[0] == '0') {
+ if(base == 8 || base == 0) {
+ end++;
+ base = 8;
+ }
+ }
+
+ /* Matching strtol, if the base is 0 and it doesn't look like
+ * the number is octal or hex, we assume it's base 10.
+ */
+ if(base == 0) {
+ base = 10;
+ }
+
+ /* Loop handling digits. */
+ value = 0;
+ overflow = 0;
+ for(i = get_char(end[0], base);
+ i != -1;
+ end++, i = get_char(end[0], base)) {
+ newval = base * value + i;
+ if(newval < value) {
+ /* We've overflowed. */
+ overflow = 1;
+ break;
+ }
+ else
+ value = newval;
+ }
+
+ if(!overflow) {
+ if(is_negative) {
+ /* Fix the sign. */
+ value *= -1;
+ }
+ }
+ else {
+ if(is_negative)
+ value = CURL_OFF_T_MIN;
+ else
+ value = CURL_OFF_T_MAX;
+
+ SET_ERRNO(ERANGE);
+ }
+
+ if(endptr)
+ *endptr = end;
+
+ return value;
+}
+
+/**
+ * Returns the value of c in the given base, or -1 if c cannot
+ * be interpreted properly in that base (i.e., is out of range,
+ * is a null, etc.).
+ *
+ * @param c the character to interpret according to base
+ * @param base the base in which to interpret c
+ *
+ * @return the value of c in base, or -1 if c isn't in range
+ */
+static int get_char(char c, int base)
+{
+#ifndef NO_RANGE_TEST
+ int value = -1;
+ if(c <= '9' && c >= '0') {
+ value = c - '0';
+ }
+ else if(c <= 'Z' && c >= 'A') {
+ value = c - 'A' + 10;
+ }
+ else if(c <= 'z' && c >= 'a') {
+ value = c - 'a' + 10;
+ }
+#else
+ const char * cp;
+ int value;
+
+ cp = memchr(valchars, c, 10 + 26 + 26);
+
+ if(!cp)
+ return -1;
+
+ value = cp - valchars;
+
+ if(value >= 10 + 26)
+ value -= 26; /* Lowercase. */
+#endif
+
+ if(value >= base) {
+ value = -1;
+ }
+
+ return value;
+}
+#endif /* Only present if we need strtoll, but don't have it. */
diff --git a/libcurl/src/lib/strtoofft.h b/libcurl/src/lib/strtoofft.h
new file mode 100644
index 0000000..e1c3bda
--- /dev/null
+++ b/libcurl/src/lib/strtoofft.h
@@ -0,0 +1,75 @@
+#ifndef HEADER_CURL_STRTOOFFT_H
+#define HEADER_CURL_STRTOOFFT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/*
+ * Determine which string to integral data type conversion function we use
+ * to implement string conversion to our curl_off_t integral data type.
+ *
+ * Notice that curl_off_t might be 64 or 32 bit wide, and that it might use
+ * an underlying data type which might be 'long', 'int64_t', 'long long' or
+ * '__int64' and more remotely other data types.
+ *
+ * On systems where the size of curl_off_t is greater than the size of 'long'
+ * the conversion function to use is strtoll() if it is available, otherwise,
+ * we emulate its functionality with our own clone.
+ *
+ * On systems where the size of curl_off_t is smaller or equal than the size
+ * of 'long' the conversion function to use is strtol().
+ */
+
+#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+# ifdef HAVE_STRTOLL
+# define curlx_strtoofft strtoll
+# else
+# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
+# if defined(_SAL_VERSION)
+ _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
+ _In_z_ const char *_String,
+ _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
+# else
+ _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
+ char **_EndPtr, int _Radix);
+# endif
+# define curlx_strtoofft _strtoi64
+# else
+ CURL_STATIC curl_off_t curlx_strtoll(const char *nptr, char **endptr, int base);
+# define curlx_strtoofft curlx_strtoll
+# define NEED_CURL_STRTOLL 1
+# endif
+# endif
+#else
+# define curlx_strtoofft strtol
+#endif
+
+#if (CURL_SIZEOF_CURL_OFF_T == 4)
+# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
+#else
+ /* assume CURL_SIZEOF_CURL_OFF_T == 8 */
+# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
+#endif
+#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
+
+#endif /* HEADER_CURL_STRTOOFFT_H */
diff --git a/libcurl/src/lib/telnet.c b/libcurl/src/lib/telnet.c
new file mode 100644
index 0000000..91863c0
--- /dev/null
+++ b/libcurl/src/lib/telnet.c
@@ -0,0 +1,1674 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_TELNET
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "telnet.h"
+#include "connect.h"
+#include "progress.h"
+#include "curl_printf.h"
+
+#define TELOPTS
+#define TELCMDS
+
+#include "arpa_telnet.h"
+#include "select.h"
+#include "strequal.h"
+#include "rawstr.h"
+#include "warnless.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define SUBBUFSIZE 512
+
+#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer
+#define CURL_SB_TERM(x) \
+ do { \
+ x->subend = x->subpointer; \
+ CURL_SB_CLEAR(x); \
+ } WHILE_FALSE
+#define CURL_SB_ACCUM(x,c) \
+ do { \
+ if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) \
+ *x->subpointer++ = (c); \
+ } WHILE_FALSE
+
+#define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
+#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
+#define CURL_SB_EOF(x) (x->subpointer >= x->subend)
+#define CURL_SB_LEN(x) (x->subend - x->subpointer)
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+#define printoption(a,b,c,d) Curl_nop_stmt
+#endif
+
+#ifdef USE_WINSOCK
+typedef FARPROC WSOCK2_FUNC;
+static CURLcode check_wsock2 ( struct SessionHandle *data );
+#endif
+
+static
+CURLcode telrcv(struct connectdata *,
+ const unsigned char *inbuf, /* Data received from socket */
+ ssize_t count); /* Number of bytes received */
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void printoption(struct SessionHandle *data,
+ const char *direction,
+ int cmd, int option);
+#endif
+
+static void negotiate(struct connectdata *);
+static void send_negotiation(struct connectdata *, int cmd, int option);
+static void set_local_option(struct connectdata *, int cmd, int option);
+static void set_remote_option(struct connectdata *, int cmd, int option);
+
+static void printsub(struct SessionHandle *data,
+ int direction, unsigned char *pointer,
+ size_t length);
+static void suboption(struct connectdata *);
+static void sendsuboption(struct connectdata *conn, int option);
+
+static CURLcode telnet_do(struct connectdata *conn, bool *done);
+static CURLcode telnet_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode send_telnet_data(struct connectdata *conn,
+ char *buffer, ssize_t nread);
+
+/* For negotiation compliant to RFC 1143 */
+#define CURL_NO 0
+#define CURL_YES 1
+#define CURL_WANTYES 2
+#define CURL_WANTNO 3
+
+#define CURL_EMPTY 0
+#define CURL_OPPOSITE 1
+
+/*
+ * Telnet receiver states for fsm
+ */
+typedef enum
+{
+ CURL_TS_DATA = 0,
+ CURL_TS_IAC,
+ CURL_TS_WILL,
+ CURL_TS_WONT,
+ CURL_TS_DO,
+ CURL_TS_DONT,
+ CURL_TS_CR,
+ CURL_TS_SB, /* sub-option collection */
+ CURL_TS_SE /* looking for sub-option end */
+} TelnetReceive;
+
+struct TELNET {
+ int please_negotiate;
+ int already_negotiated;
+ int us[256];
+ int usq[256];
+ int us_preferred[256];
+ int him[256];
+ int himq[256];
+ int him_preferred[256];
+ int subnegotiation[256];
+ char subopt_ttype[32]; /* Set with suboption TTYPE */
+ char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */
+ unsigned short subopt_wsx; /* Set with suboption NAWS */
+ unsigned short subopt_wsy; /* Set with suboption NAWS */
+ struct curl_slist *telnet_vars; /* Environment variables */
+
+ /* suboptions */
+ unsigned char subbuffer[SUBBUFSIZE];
+ unsigned char *subpointer, *subend; /* buffer for sub-options */
+
+ TelnetReceive telrcv_state;
+};
+
+
+/*
+ * TELNET protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_telnet = {
+ "TELNET", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ telnet_do, /* do_it */
+ telnet_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_TELNET, /* defport */
+ CURLPROTO_TELNET, /* protocol */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+#ifdef USE_WINSOCK
+static CURLcode
+check_wsock2 ( struct SessionHandle *data )
+{
+ int err;
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ DEBUGASSERT(data);
+
+ /* telnet requires at least WinSock 2.0 so ask for it. */
+ wVersionRequested = MAKEWORD(2, 0);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+
+ /* We must've called this once already, so this call */
+ /* should always succeed. But, just in case... */
+ if(err != 0) {
+ failf(data,"WSAStartup failed (%d)",err);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* We have to have a WSACleanup call for every successful */
+ /* WSAStartup call. */
+ WSACleanup();
+
+ /* Check that our version is supported */
+ if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
+ HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
+ /* Our version isn't supported */
+ failf(data, "insufficient winsock version to support "
+ "telnet");
+ return CURLE_FAILED_INIT;
+ }
+
+ /* Our version is supported */
+ return CURLE_OK;
+}
+#endif
+
+static
+CURLcode init_telnet(struct connectdata *conn)
+{
+ struct TELNET *tn;
+
+ tn = calloc(1, sizeof(struct TELNET));
+ if(!tn)
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->data->req.protop = tn; /* make us known */
+
+ tn->telrcv_state = CURL_TS_DATA;
+
+ /* Init suboptions */
+ CURL_SB_CLEAR(tn);
+
+ /* Set the options we want by default */
+ tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES;
+ tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES;
+
+ /* To be compliant with previous releases of libcurl
+ we enable this option by default. This behaviour
+ can be changed thanks to the "BINARY" option in
+ CURLOPT_TELNETOPTIONS
+ */
+ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES;
+ tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES;
+
+ /* We must allow the server to echo what we sent
+ but it is not necessary to request the server
+ to do so (it might forces the server to close
+ the connection). Hence, we ignore ECHO in the
+ negotiate function
+ */
+ tn->him_preferred[CURL_TELOPT_ECHO] = CURL_YES;
+
+ /* Set the subnegotiation fields to send information
+ just after negotiation passed (do/will)
+
+ Default values are (0,0) initialized by calloc.
+ According to the RFC1013 it is valid:
+ A value equal to zero is acceptable for the width (or height),
+ and means that no character width (or height) is being sent.
+ In this case, the width (or height) that will be assumed by the
+ Telnet server is operating system specific (it will probably be
+ based upon the terminal type information that may have been sent
+ using the TERMINAL TYPE Telnet option). */
+ tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES;
+ return CURLE_OK;
+}
+
+static void negotiate(struct connectdata *conn)
+{
+ int i;
+ struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
+
+ for(i = 0;i < CURL_NTELOPTS;i++) {
+ if(i==CURL_TELOPT_ECHO)
+ continue;
+
+ if(tn->us_preferred[i] == CURL_YES)
+ set_local_option(conn, i, CURL_YES);
+
+ if(tn->him_preferred[i] == CURL_YES)
+ set_remote_option(conn, i, CURL_YES);
+ }
+}
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void printoption(struct SessionHandle *data,
+ const char *direction, int cmd, int option)
+{
+ const char *fmt;
+ const char *opt;
+
+ if(data->set.verbose) {
+ if(cmd == CURL_IAC) {
+ if(CURL_TELCMD_OK(option))
+ infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
+ else
+ infof(data, "%s IAC %d\n", direction, option);
+ }
+ else {
+ fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
+ (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
+ if(fmt) {
+ if(CURL_TELOPT_OK(option))
+ opt = CURL_TELOPT(option);
+ else if(option == CURL_TELOPT_EXOPL)
+ opt = "EXOPL";
+ else
+ opt = NULL;
+
+ if(opt)
+ infof(data, "%s %s %s\n", direction, fmt, opt);
+ else
+ infof(data, "%s %s %d\n", direction, fmt, option);
+ }
+ else
+ infof(data, "%s %d %d\n", direction, cmd, option);
+ }
+ }
+}
+#endif
+
+static void send_negotiation(struct connectdata *conn, int cmd, int option)
+{
+ unsigned char buf[3];
+ ssize_t bytes_written;
+ int err;
+ struct SessionHandle *data = conn->data;
+
+ buf[0] = CURL_IAC;
+ buf[1] = (unsigned char)cmd;
+ buf[2] = (unsigned char)option;
+
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+
+ printoption(conn->data, "SENT", cmd, option);
+}
+
+static
+void set_remote_option(struct connectdata *conn, int option, int newstate)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ if(newstate == CURL_YES) {
+ switch(tn->him[option]) {
+ case CURL_NO:
+ tn->him[option] = CURL_WANTYES;
+ send_negotiation(conn, CURL_DO, option);
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for CURL_YES, queue the request */
+ tn->himq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: already queued an enable request */
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Error: already negotiating for enable */
+ break;
+ case CURL_OPPOSITE:
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+ }
+ else { /* NO */
+ switch(tn->him[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->him[option] = CURL_WANTNO;
+ send_negotiation(conn, CURL_DONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for NO */
+ break;
+ case CURL_OPPOSITE:
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->himq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static
+void rec_will(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->him[option]) {
+ case CURL_NO:
+ if(tn->him_preferred[option] == CURL_YES) {
+ tn->him[option] = CURL_YES;
+ send_negotiation(conn, CURL_DO, option);
+ }
+ else
+ send_negotiation(conn, CURL_DONT, option);
+
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Error: DONT answered by WILL */
+ tn->him[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: DONT answered by WILL */
+ tn->him[option] = CURL_YES;
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->him[option] = CURL_YES;
+ break;
+ case CURL_OPPOSITE:
+ tn->him[option] = CURL_WANTNO;
+ tn->himq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_DONT, option);
+ break;
+ }
+ break;
+ }
+}
+
+static
+void rec_wont(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->him[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->him[option] = CURL_NO;
+ send_negotiation(conn, CURL_DONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->him[option] = CURL_NO;
+ break;
+
+ case CURL_OPPOSITE:
+ tn->him[option] = CURL_WANTYES;
+ tn->himq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_DO, option);
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->him[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ tn->him[option] = CURL_NO;
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+}
+
+static void
+set_local_option(struct connectdata *conn, int option, int newstate)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ if(newstate == CURL_YES) {
+ switch(tn->us[option]) {
+ case CURL_NO:
+ tn->us[option] = CURL_WANTYES;
+ send_negotiation(conn, CURL_WILL, option);
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for CURL_YES, queue the request */
+ tn->usq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: already queued an enable request */
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Error: already negotiating for enable */
+ break;
+ case CURL_OPPOSITE:
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+ }
+ else { /* NO */
+ switch(tn->us[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->us[option] = CURL_WANTNO;
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for NO */
+ break;
+ case CURL_OPPOSITE:
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->usq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static
+void rec_do(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->us[option]) {
+ case CURL_NO:
+ if(tn->us_preferred[option] == CURL_YES) {
+ tn->us[option] = CURL_YES;
+ send_negotiation(conn, CURL_WILL, option);
+ if(tn->subnegotiation[option] == CURL_YES)
+ /* transmission of data option */
+ sendsuboption(conn, option);
+ }
+ else if(tn->subnegotiation[option] == CURL_YES) {
+ /* send information to achieve this option*/
+ tn->us[option] = CURL_YES;
+ send_negotiation(conn, CURL_WILL, option);
+ sendsuboption(conn, option);
+ }
+ else
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Error: DONT answered by WILL */
+ tn->us[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: DONT answered by WILL */
+ tn->us[option] = CURL_YES;
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->us[option] = CURL_YES;
+ if(tn->subnegotiation[option] == CURL_YES) {
+ /* transmission of data option */
+ sendsuboption(conn, option);
+ }
+ break;
+ case CURL_OPPOSITE:
+ tn->us[option] = CURL_WANTNO;
+ tn->himq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+ }
+ break;
+ }
+}
+
+static
+void rec_dont(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->us[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->us[option] = CURL_NO;
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->us[option] = CURL_NO;
+ break;
+
+ case CURL_OPPOSITE:
+ tn->us[option] = CURL_WANTYES;
+ tn->usq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_WILL, option);
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->us[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ tn->us[option] = CURL_NO;
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+}
+
+
+static void printsub(struct SessionHandle *data,
+ int direction, /* '<' or '>' */
+ unsigned char *pointer, /* where suboption data is */
+ size_t length) /* length of suboption data */
+{
+ unsigned int i = 0;
+
+ if(data->set.verbose) {
+ if(direction) {
+ infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
+ if(length >= 3) {
+ int j;
+
+ i = pointer[length-2];
+ j = pointer[length-1];
+
+ if(i != CURL_IAC || j != CURL_SE) {
+ infof(data, "(terminated by ");
+ if(CURL_TELOPT_OK(i))
+ infof(data, "%s ", CURL_TELOPT(i));
+ else if(CURL_TELCMD_OK(i))
+ infof(data, "%s ", CURL_TELCMD(i));
+ else
+ infof(data, "%u ", i);
+ if(CURL_TELOPT_OK(j))
+ infof(data, "%s", CURL_TELOPT(j));
+ else if(CURL_TELCMD_OK(j))
+ infof(data, "%s", CURL_TELCMD(j));
+ else
+ infof(data, "%d", j);
+ infof(data, ", not IAC SE!) ");
+ }
+ }
+ length -= 2;
+ }
+ if(length < 1) {
+ infof(data, "(Empty suboption?)");
+ return;
+ }
+
+ if(CURL_TELOPT_OK(pointer[0])) {
+ switch(pointer[0]) {
+ case CURL_TELOPT_TTYPE:
+ case CURL_TELOPT_XDISPLOC:
+ case CURL_TELOPT_NEW_ENVIRON:
+ case CURL_TELOPT_NAWS:
+ infof(data, "%s", CURL_TELOPT(pointer[0]));
+ break;
+ default:
+ infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0]));
+ break;
+ }
+ }
+ else
+ infof(data, "%d (unknown)", pointer[i]);
+
+ switch(pointer[0]) {
+ case CURL_TELOPT_NAWS:
+ if(length > 4)
+ infof(data, "Width: %hu ; Height: %hu", (pointer[1]<<8) | pointer[2],
+ (pointer[3]<<8) | pointer[4]);
+ break;
+ default:
+ switch(pointer[1]) {
+ case CURL_TELQUAL_IS:
+ infof(data, " IS");
+ break;
+ case CURL_TELQUAL_SEND:
+ infof(data, " SEND");
+ break;
+ case CURL_TELQUAL_INFO:
+ infof(data, " INFO/REPLY");
+ break;
+ case CURL_TELQUAL_NAME:
+ infof(data, " NAME");
+ break;
+ }
+
+ switch(pointer[0]) {
+ case CURL_TELOPT_TTYPE:
+ case CURL_TELOPT_XDISPLOC:
+ pointer[length] = 0;
+ infof(data, " \"%s\"", &pointer[2]);
+ break;
+ case CURL_TELOPT_NEW_ENVIRON:
+ if(pointer[1] == CURL_TELQUAL_IS) {
+ infof(data, " ");
+ for(i = 3;i < length;i++) {
+ switch(pointer[i]) {
+ case CURL_NEW_ENV_VAR:
+ infof(data, ", ");
+ break;
+ case CURL_NEW_ENV_VALUE:
+ infof(data, " = ");
+ break;
+ default:
+ infof(data, "%c", pointer[i]);
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ for(i = 2; i < length; i++)
+ infof(data, " %.2x", pointer[i]);
+ break;
+ }
+ }
+ if(direction)
+ infof(data, "\n");
+ }
+}
+
+static CURLcode check_telnet_options(struct connectdata *conn)
+{
+ struct curl_slist *head;
+ struct curl_slist *beg;
+ char option_keyword[128] = "";
+ char option_arg[256] = "";
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ CURLcode result = CURLE_OK;
+ int binary_option;
+
+ /* Add the user name as an environment variable if it
+ was given on the command line */
+ if(conn->bits.user_passwd) {
+ snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
+ beg = curl_slist_append(tn->telnet_vars, option_arg);
+ if(!beg) {
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ tn->telnet_vars = beg;
+ tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
+ }
+
+ for(head = data->set.telnet_options; head; head=head->next) {
+ if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
+ option_keyword, option_arg) == 2) {
+
+ /* Terminal type */
+ if(Curl_raw_equal(option_keyword, "TTYPE")) {
+ strncpy(tn->subopt_ttype, option_arg, 31);
+ tn->subopt_ttype[31] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
+ continue;
+ }
+
+ /* Display variable */
+ if(Curl_raw_equal(option_keyword, "XDISPLOC")) {
+ strncpy(tn->subopt_xdisploc, option_arg, 127);
+ tn->subopt_xdisploc[127] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
+ continue;
+ }
+
+ /* Environment variable */
+ if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
+ beg = curl_slist_append(tn->telnet_vars, option_arg);
+ if(!beg) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ tn->telnet_vars = beg;
+ tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
+ continue;
+ }
+
+ /* Window Size */
+ if(Curl_raw_equal(option_keyword, "WS")) {
+ if(sscanf(option_arg, "%hu%*[xX]%hu",
+ &tn->subopt_wsx, &tn->subopt_wsy) == 2)
+ tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
+ else {
+ failf(data, "Syntax error in telnet option: %s", head->data);
+ result = CURLE_TELNET_OPTION_SYNTAX;
+ break;
+ }
+ continue;
+ }
+
+ /* To take care or not of the 8th bit in data exchange */
+ if(Curl_raw_equal(option_keyword, "BINARY")) {
+ binary_option=atoi(option_arg);
+ if(binary_option!=1) {
+ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+ tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+ }
+ continue;
+ }
+
+ failf(data, "Unknown telnet option %s", head->data);
+ result = CURLE_UNKNOWN_TELNET_OPTION;
+ break;
+ }
+ else {
+ failf(data, "Syntax error in telnet option: %s", head->data);
+ result = CURLE_TELNET_OPTION_SYNTAX;
+ break;
+ }
+ }
+
+ if(result) {
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+ }
+
+ return result;
+}
+
+/*
+ * suboption()
+ *
+ * Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ */
+
+static void suboption(struct connectdata *conn)
+{
+ struct curl_slist *v;
+ unsigned char temp[2048];
+ ssize_t bytes_written;
+ size_t len;
+ size_t tmplen;
+ int err;
+ char varname[128] = "";
+ char varval[128] = "";
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)data->req.protop;
+
+ printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
+ switch (CURL_SB_GET(tn)) {
+ case CURL_TELOPT_TTYPE:
+ len = strlen(tn->subopt_ttype) + 4 + 2;
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
+ CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+ printsub(data, '>', &temp[2], len-2);
+ break;
+ case CURL_TELOPT_XDISPLOC:
+ len = strlen(tn->subopt_xdisploc) + 4 + 2;
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
+ CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+ printsub(data, '>', &temp[2], len-2);
+ break;
+ case CURL_TELOPT_NEW_ENVIRON:
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
+ CURL_TELQUAL_IS);
+ len = 4;
+
+ for(v = tn->telnet_vars;v;v = v->next) {
+ tmplen = (strlen(v->data) + 1);
+ /* Add the variable only if it fits */
+ if(len + tmplen < (int)sizeof(temp)-6) {
+ if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
+ snprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+ CURL_NEW_ENV_VALUE, varval);
+ len += tmplen;
+ }
+ }
+ }
+ snprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%c", CURL_IAC, CURL_SE);
+ len += 2;
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+ printsub(data, '>', &temp[2], len-2);
+ break;
+ }
+ return;
+}
+
+
+/*
+ * sendsuboption()
+ *
+ * Send suboption information to the server side.
+ */
+
+static void sendsuboption(struct connectdata *conn, int option)
+{
+ ssize_t bytes_written;
+ int err;
+ unsigned short x, y;
+ unsigned char*uc1, *uc2;
+
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)data->req.protop;
+
+ switch (option) {
+ case CURL_TELOPT_NAWS:
+ /* We prepare data to be sent */
+ CURL_SB_CLEAR(tn);
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, CURL_SB);
+ CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
+ /* We must deal either with litte or big endien processors */
+ /* Window size must be sent according to the 'network order' */
+ x=htons(tn->subopt_wsx);
+ y=htons(tn->subopt_wsy);
+ uc1 = (unsigned char*)&x;
+ uc2 = (unsigned char*)&y;
+ CURL_SB_ACCUM(tn, uc1[0]);
+ CURL_SB_ACCUM(tn, uc1[1]);
+ CURL_SB_ACCUM(tn, uc2[0]);
+ CURL_SB_ACCUM(tn, uc2[1]);
+
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, CURL_SE);
+ CURL_SB_TERM(tn);
+ /* data suboption is now ready */
+
+ printsub(data, '>', (unsigned char *)tn->subbuffer+2,
+ CURL_SB_LEN(tn)-2);
+
+ /* we send the header of the suboption... */
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data, "Sending data failed (%d)", err);
+ }
+ /* ... then the window size with the send_telnet_data() function
+ to deal with 0xFF cases ... */
+ send_telnet_data(conn, (char *)tn->subbuffer+3, 4);
+ /* ... and the footer */
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer+7, 2);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data, "Sending data failed (%d)", err);
+ }
+ break;
+ }
+}
+
+
+static
+CURLcode telrcv(struct connectdata *conn,
+ const unsigned char *inbuf, /* Data received from socket */
+ ssize_t count) /* Number of bytes received */
+{
+ unsigned char c;
+ CURLcode result;
+ int in = 0;
+ int startwrite=-1;
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)data->req.protop;
+
+#define startskipping() \
+ if(startwrite >= 0) { \
+ result = Curl_client_write(conn, \
+ CLIENTWRITE_BODY, \
+ (char *)&inbuf[startwrite], \
+ in-startwrite); \
+ if(result) \
+ return result; \
+ } \
+ startwrite = -1
+
+#define writebyte() \
+ if(startwrite < 0) \
+ startwrite = in
+
+#define bufferflush() startskipping()
+
+ while(count--) {
+ c = inbuf[in];
+
+ switch (tn->telrcv_state) {
+ case CURL_TS_CR:
+ tn->telrcv_state = CURL_TS_DATA;
+ if(c == '\0') {
+ startskipping();
+ break; /* Ignore \0 after CR */
+ }
+ writebyte();
+ break;
+
+ case CURL_TS_DATA:
+ if(c == CURL_IAC) {
+ tn->telrcv_state = CURL_TS_IAC;
+ startskipping();
+ break;
+ }
+ else if(c == '\r')
+ tn->telrcv_state = CURL_TS_CR;
+ writebyte();
+ break;
+
+ case CURL_TS_IAC:
+ process_iac:
+ DEBUGASSERT(startwrite < 0);
+ switch (c) {
+ case CURL_WILL:
+ tn->telrcv_state = CURL_TS_WILL;
+ break;
+ case CURL_WONT:
+ tn->telrcv_state = CURL_TS_WONT;
+ break;
+ case CURL_DO:
+ tn->telrcv_state = CURL_TS_DO;
+ break;
+ case CURL_DONT:
+ tn->telrcv_state = CURL_TS_DONT;
+ break;
+ case CURL_SB:
+ CURL_SB_CLEAR(tn);
+ tn->telrcv_state = CURL_TS_SB;
+ break;
+ case CURL_IAC:
+ tn->telrcv_state = CURL_TS_DATA;
+ writebyte();
+ break;
+ case CURL_DM:
+ case CURL_NOP:
+ case CURL_GA:
+ default:
+ tn->telrcv_state = CURL_TS_DATA;
+ printoption(data, "RCVD", CURL_IAC, c);
+ break;
+ }
+ break;
+
+ case CURL_TS_WILL:
+ printoption(data, "RCVD", CURL_WILL, c);
+ tn->please_negotiate = 1;
+ rec_will(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_WONT:
+ printoption(data, "RCVD", CURL_WONT, c);
+ tn->please_negotiate = 1;
+ rec_wont(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_DO:
+ printoption(data, "RCVD", CURL_DO, c);
+ tn->please_negotiate = 1;
+ rec_do(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_DONT:
+ printoption(data, "RCVD", CURL_DONT, c);
+ tn->please_negotiate = 1;
+ rec_dont(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_SB:
+ if(c == CURL_IAC)
+ tn->telrcv_state = CURL_TS_SE;
+ else
+ CURL_SB_ACCUM(tn, c);
+ break;
+
+ case CURL_TS_SE:
+ if(c != CURL_SE) {
+ if(c != CURL_IAC) {
+ /*
+ * This is an error. We only expect to get "IAC IAC" or "IAC SE".
+ * Several things may have happened. An IAC was not doubled, the
+ * IAC SE was left off, or another option got inserted into the
+ * suboption are all possibilities. If we assume that the IAC was
+ * not doubled, and really the IAC SE was left off, we could get
+ * into an infinate loop here. So, instead, we terminate the
+ * suboption, and process the partial suboption if we can.
+ */
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, c);
+ tn->subpointer -= 2;
+ CURL_SB_TERM(tn);
+
+ printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
+ suboption(conn); /* handle sub-option */
+ tn->telrcv_state = CURL_TS_IAC;
+ goto process_iac;
+ }
+ CURL_SB_ACCUM(tn, c);
+ tn->telrcv_state = CURL_TS_SB;
+ }
+ else
+ {
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, CURL_SE);
+ tn->subpointer -= 2;
+ CURL_SB_TERM(tn);
+ suboption(conn); /* handle sub-option */
+ tn->telrcv_state = CURL_TS_DATA;
+ }
+ break;
+ }
+ ++in;
+ }
+ bufferflush();
+ return CURLE_OK;
+}
+
+/* Escape and send a telnet data block */
+/* TODO: write large chunks of data instead of one byte at a time */
+static CURLcode send_telnet_data(struct connectdata *conn,
+ char *buffer, ssize_t nread)
+{
+ unsigned char outbuf[2];
+ ssize_t bytes_written, total_written;
+ int out_count;
+ CURLcode result = CURLE_OK;
+
+ while(!result && nread--) {
+ outbuf[0] = *buffer++;
+ out_count = 1;
+ if(outbuf[0] == CURL_IAC)
+ outbuf[out_count++] = CURL_IAC;
+
+ total_written = 0;
+ do {
+ /* Make sure socket is writable to avoid EWOULDBLOCK condition */
+ struct pollfd pfd[1];
+ pfd[0].fd = conn->sock[FIRSTSOCKET];
+ pfd[0].events = POLLOUT;
+ switch (Curl_poll(pfd, 1, -1)) {
+ case -1: /* error, abort writing */
+ case 0: /* timeout (will never happen) */
+ result = CURLE_SEND_ERROR;
+ break;
+ default: /* write! */
+ bytes_written = 0;
+ result = Curl_write(conn, conn->sock[FIRSTSOCKET],
+ outbuf+total_written, out_count-total_written,
+ &bytes_written);
+ total_written += bytes_written;
+ break;
+ }
+ /* handle partial write */
+ } while(!result && total_written < out_count);
+ }
+ return result;
+}
+
+static CURLcode telnet_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ (void)status; /* unused */
+ (void)premature; /* not used */
+
+ if(!tn)
+ return CURLE_OK;
+
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+
+ Curl_safefree(conn->data->req.protop);
+
+ return CURLE_OK;
+}
+
+static CURLcode telnet_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+#ifdef USE_WINSOCK
+ HMODULE wsock2;
+ WSOCK2_FUNC close_event_func;
+ WSOCK2_FUNC create_event_func;
+ WSOCK2_FUNC event_select_func;
+ WSOCK2_FUNC enum_netevents_func;
+ WSAEVENT event_handle;
+ WSANETWORKEVENTS events;
+ HANDLE stdin_handle;
+ HANDLE objs[2];
+ DWORD obj_count;
+ DWORD wait_timeout;
+ DWORD waitret;
+ DWORD readfile_read;
+ int err;
+#else
+ int interval_ms;
+ struct pollfd pfd[2];
+ int poll_cnt;
+ curl_off_t total_dl = 0;
+ curl_off_t total_ul = 0;
+#endif
+ ssize_t nread;
+ struct timeval now;
+ bool keepon = TRUE;
+ char *buf = data->state.buffer;
+ struct TELNET *tn;
+
+ *done = TRUE; /* unconditionally */
+
+ result = init_telnet(conn);
+ if(result)
+ return result;
+
+ tn = (struct TELNET *)data->req.protop;
+
+ result = check_telnet_options(conn);
+ if(result)
+ return result;
+
+#ifdef USE_WINSOCK
+ /*
+ ** This functionality only works with WinSock >= 2.0. So,
+ ** make sure have it.
+ */
+ result = check_wsock2(data);
+ if(result)
+ return result;
+
+ /* OK, so we have WinSock 2.0. We need to dynamically */
+ /* load ws2_32.dll and get the function pointers we need. */
+ wsock2 = LoadLibrary(TEXT("WS2_32.DLL"));
+ if(wsock2 == NULL) {
+ failf(data, "failed to load WS2_32.DLL (%d)", ERRNO);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* Grab a pointer to WSACreateEvent */
+ create_event_func = GetProcAddress(wsock2, "WSACreateEvent");
+ if(create_event_func == NULL) {
+ failf(data, "failed to find WSACreateEvent function (%d)", ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* And WSACloseEvent */
+ close_event_func = GetProcAddress(wsock2, "WSACloseEvent");
+ if(close_event_func == NULL) {
+ failf(data, "failed to find WSACloseEvent function (%d)", ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* And WSAEventSelect */
+ event_select_func = GetProcAddress(wsock2, "WSAEventSelect");
+ if(event_select_func == NULL) {
+ failf(data, "failed to find WSAEventSelect function (%d)", ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* And WSAEnumNetworkEvents */
+ enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents");
+ if(enum_netevents_func == NULL) {
+ failf(data, "failed to find WSAEnumNetworkEvents function (%d)", ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* We want to wait for both stdin and the socket. Since
+ ** the select() function in winsock only works on sockets
+ ** we have to use the WaitForMultipleObjects() call.
+ */
+
+ /* First, create a sockets event object */
+ event_handle = (WSAEVENT)create_event_func();
+ if(event_handle == WSA_INVALID_EVENT) {
+ failf(data, "WSACreateEvent failed (%d)", SOCKERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* Tell winsock what events we want to listen to */
+ if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) ==
+ SOCKET_ERROR) {
+ close_event_func(event_handle);
+ FreeLibrary(wsock2);
+ return CURLE_OK;
+ }
+
+ /* The get the Windows file handle for stdin */
+ stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
+
+ /* Create the list of objects to wait for */
+ objs[0] = event_handle;
+ objs[1] = stdin_handle;
+
+ /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
+ else use the old WaitForMultipleObjects() way */
+ if(GetFileType(stdin_handle) == FILE_TYPE_PIPE ||
+ data->set.is_fread_set) {
+ /* Don't wait for stdin_handle, just wait for event_handle */
+ obj_count = 1;
+ /* Check stdin_handle per 100 milliseconds */
+ wait_timeout = 100;
+ }
+ else {
+ obj_count = 2;
+ wait_timeout = 1000;
+ }
+
+ /* Keep on listening and act on events */
+ while(keepon) {
+ waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
+ switch(waitret) {
+ case WAIT_TIMEOUT:
+ {
+ for(;;) {
+ if(data->set.is_fread_set) {
+ /* read from user-supplied method */
+ result = (int) conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
+ if(result == CURL_READFUNC_ABORT) {
+ keepon = FALSE;
+ result = CURLE_READ_ERROR;
+ break;
+ }
+
+ if(result == CURL_READFUNC_PAUSE)
+ break;
+
+ if(result == 0) /* no bytes */
+ break;
+
+ readfile_read = result; /* fall thru with number of bytes read */
+ }
+ else {
+ /* read from stdin */
+ if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL,
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ result = CURLE_READ_ERROR;
+ break;
+ }
+
+ if(!readfile_read)
+ break;
+
+ if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ result = CURLE_READ_ERROR;
+ break;
+ }
+ }
+
+ result = send_telnet_data(conn, buf, readfile_read);
+ if(result) {
+ keepon = FALSE;
+ break;
+ }
+ }
+ }
+ break;
+
+ case WAIT_OBJECT_0 + 1:
+ {
+ if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ result = CURLE_READ_ERROR;
+ break;
+ }
+
+ result = send_telnet_data(conn, buf, readfile_read);
+ if(result) {
+ keepon = FALSE;
+ break;
+ }
+ }
+ break;
+
+ case WAIT_OBJECT_0:
+
+ events.lNetworkEvents = 0;
+ if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
+ if((err = SOCKERRNO) != EINPROGRESS) {
+ infof(data, "WSAEnumNetworkEvents failed (%d)", err);
+ keepon = FALSE;
+ result = CURLE_READ_ERROR;
+ }
+ break;
+ }
+ if(events.lNetworkEvents & FD_READ) {
+ /* read data from network */
+ result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+ /* read would've blocked. Loop again */
+ if(result == CURLE_AGAIN)
+ break;
+ /* returned not-zero, this an error */
+ else if(result) {
+ keepon = FALSE;
+ break;
+ }
+ /* returned zero but actually received 0 or less here,
+ the server closed the connection and we bail out */
+ else if(nread <= 0) {
+ keepon = FALSE;
+ break;
+ }
+
+ result = telrcv(conn, (unsigned char *) buf, nread);
+ if(result) {
+ keepon = FALSE;
+ break;
+ }
+
+ /* Negotiate if the peer has started negotiating,
+ otherwise don't. We don't want to speak telnet with
+ non-telnet servers, like POP or SMTP. */
+ if(tn->please_negotiate && !tn->already_negotiated) {
+ negotiate(conn);
+ tn->already_negotiated = 1;
+ }
+ }
+ if(events.lNetworkEvents & FD_CLOSE) {
+ keepon = FALSE;
+ }
+ break;
+
+ }
+
+ if(data->set.timeout) {
+ now = Curl_tvnow();
+ if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
+ failf(data, "Time-out");
+ result = CURLE_OPERATION_TIMEDOUT;
+ keepon = FALSE;
+ }
+ }
+ }
+
+ /* We called WSACreateEvent, so call WSACloseEvent */
+ if(!close_event_func(event_handle)) {
+ infof(data, "WSACloseEvent failed (%d)", SOCKERRNO);
+ }
+
+ /* "Forget" pointers into the library we're about to free */
+ create_event_func = NULL;
+ close_event_func = NULL;
+ event_select_func = NULL;
+ enum_netevents_func = NULL;
+
+ /* We called LoadLibrary, so call FreeLibrary */
+ if(!FreeLibrary(wsock2))
+ infof(data, "FreeLibrary(wsock2) failed (%d)", ERRNO);
+#else
+ pfd[0].fd = sockfd;
+ pfd[0].events = POLLIN;
+
+ if(conn->fread_func != (curl_read_callback)fread) {
+ poll_cnt = 1;
+ interval_ms = 100; /* poll user-supplied read function */
+ }
+ else {
+ /* really using fread, so infile is a FILE* */
+ pfd[1].fd = fileno((FILE *)conn->fread_in);
+ pfd[1].events = POLLIN;
+ poll_cnt = 2;
+ interval_ms = 1 * 1000;
+ }
+
+ while(keepon) {
+ switch (Curl_poll(pfd, poll_cnt, interval_ms)) {
+ case -1: /* error, stop reading */
+ keepon = FALSE;
+ continue;
+ case 0: /* timeout */
+ pfd[0].revents = 0;
+ pfd[1].revents = 0;
+ /* fall through */
+ default: /* read! */
+ if(pfd[0].revents & POLLIN) {
+ /* read data from network */
+ result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+ /* read would've blocked. Loop again */
+ if(result == CURLE_AGAIN)
+ break;
+ /* returned not-zero, this an error */
+ else if(result) {
+ keepon = FALSE;
+ break;
+ }
+ /* returned zero but actually received 0 or less here,
+ the server closed the connection and we bail out */
+ else if(nread <= 0) {
+ keepon = FALSE;
+ break;
+ }
+
+ total_dl += nread;
+ Curl_pgrsSetDownloadCounter(data, total_dl);
+ result = telrcv(conn, (unsigned char *)buf, nread);
+ if(result) {
+ keepon = FALSE;
+ break;
+ }
+
+ /* Negotiate if the peer has started negotiating,
+ otherwise don't. We don't want to speak telnet with
+ non-telnet servers, like POP or SMTP. */
+ if(tn->please_negotiate && !tn->already_negotiated) {
+ negotiate(conn);
+ tn->already_negotiated = 1;
+ }
+ }
+
+ nread = 0;
+ if(poll_cnt == 2) {
+ if(pfd[1].revents & POLLIN) { /* read from in file */
+ nread = read(pfd[1].fd, buf, BUFSIZE - 1);
+ }
+ }
+ else {
+ /* read from user-supplied method */
+ nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
+ if(nread == CURL_READFUNC_ABORT) {
+ keepon = FALSE;
+ break;
+ }
+ if(nread == CURL_READFUNC_PAUSE)
+ break;
+ }
+
+ if(nread > 0) {
+ result = send_telnet_data(conn, buf, nread);
+ if(result) {
+ keepon = FALSE;
+ break;
+ }
+ total_ul += nread;
+ Curl_pgrsSetUploadCounter(data, total_ul);
+ }
+ else if(nread < 0)
+ keepon = FALSE;
+
+ break;
+ } /* poll switch statement */
+
+ if(data->set.timeout) {
+ now = Curl_tvnow();
+ if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
+ failf(data, "Time-out");
+ result = CURLE_OPERATION_TIMEDOUT;
+ keepon = FALSE;
+ }
+ }
+
+ if(Curl_pgrsUpdate(conn)) {
+ result = CURLE_ABORTED_BY_CALLBACK;
+ break;
+ }
+ }
+#endif
+ /* mark this as "no further transfer wanted" */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ return result;
+}
+#endif
diff --git a/libcurl/src/lib/telnet.h b/libcurl/src/lib/telnet.h
new file mode 100644
index 0000000..ddb9e54
--- /dev/null
+++ b/libcurl/src/lib/telnet.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TELNET_H
+#define HEADER_CURL_TELNET_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_TELNET
+extern const struct Curl_handler Curl_handler_telnet;
+#endif
+
+#endif /* HEADER_CURL_TELNET_H */
+
diff --git a/libcurl/src/lib/tftp.c b/libcurl/src/lib/tftp.c
new file mode 100644
index 0000000..4c5796f
--- /dev/null
+++ b/libcurl/src/lib/tftp.c
@@ -0,0 +1,1376 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_TFTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "tftp.h"
+#include "progress.h"
+#include "connect.h"
+#include "strerror.h"
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "speedcheck.h"
+#include "curl_printf.h"
+#include "select.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* RFC2348 allows the block size to be negotiated */
+#define TFTP_BLKSIZE_DEFAULT 512
+#define TFTP_BLKSIZE_MIN 8
+#define TFTP_BLKSIZE_MAX 65464
+#define TFTP_OPTION_BLKSIZE "blksize"
+
+/* from RFC2349: */
+#define TFTP_OPTION_TSIZE "tsize"
+#define TFTP_OPTION_INTERVAL "timeout"
+
+typedef enum {
+ TFTP_MODE_NETASCII=0,
+ TFTP_MODE_OCTET
+} tftp_mode_t;
+
+typedef enum {
+ TFTP_STATE_START=0,
+ TFTP_STATE_RX,
+ TFTP_STATE_TX,
+ TFTP_STATE_FIN
+} tftp_state_t;
+
+typedef enum {
+ TFTP_EVENT_NONE = -1,
+ TFTP_EVENT_INIT = 0,
+ TFTP_EVENT_RRQ = 1,
+ TFTP_EVENT_WRQ = 2,
+ TFTP_EVENT_DATA = 3,
+ TFTP_EVENT_ACK = 4,
+ TFTP_EVENT_ERROR = 5,
+ TFTP_EVENT_OACK = 6,
+ TFTP_EVENT_TIMEOUT
+} tftp_event_t;
+
+typedef enum {
+ TFTP_ERR_UNDEF=0,
+ TFTP_ERR_NOTFOUND,
+ TFTP_ERR_PERM,
+ TFTP_ERR_DISKFULL,
+ TFTP_ERR_ILLEGAL,
+ TFTP_ERR_UNKNOWNID,
+ TFTP_ERR_EXISTS,
+ TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */
+
+ /* The remaining error codes are internal to curl */
+ TFTP_ERR_NONE = -100,
+ TFTP_ERR_TIMEOUT,
+ TFTP_ERR_NORESPONSE
+} tftp_error_t;
+
+typedef struct tftp_packet {
+ unsigned char *data;
+} tftp_packet_t;
+
+typedef struct tftp_state_data {
+ tftp_state_t state;
+ tftp_mode_t mode;
+ tftp_error_t error;
+ tftp_event_t event;
+ struct connectdata *conn;
+ curl_socket_t sockfd;
+ int retries;
+ int retry_time;
+ int retry_max;
+ time_t start_time;
+ time_t max_time;
+ time_t rx_time;
+ unsigned short block;
+ struct Curl_sockaddr_storage local_addr;
+ struct Curl_sockaddr_storage remote_addr;
+ curl_socklen_t remote_addrlen;
+ int rbytes;
+ int sbytes;
+ int blksize;
+ int requested_blksize;
+ tftp_packet_t rpacket;
+ tftp_packet_t spacket;
+} tftp_state_data_t;
+
+
+/* Forward declarations */
+static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event);
+static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event);
+static CURLcode tftp_connect(struct connectdata *conn, bool *done);
+static CURLcode tftp_disconnect(struct connectdata *conn,
+ bool dead_connection);
+static CURLcode tftp_do(struct connectdata *conn, bool *done);
+static CURLcode tftp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode tftp_setup_connection(struct connectdata * conn);
+static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done);
+static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done);
+static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode tftp_translate_code(tftp_error_t error);
+
+
+/*
+ * TFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_tftp = {
+ "TFTP", /* scheme */
+ tftp_setup_connection, /* setup_connection */
+ tftp_do, /* do_it */
+ tftp_done, /* done */
+ ZERO_NULL, /* do_more */
+ tftp_connect, /* connect_it */
+ tftp_multi_statemach, /* connecting */
+ tftp_doing, /* doing */
+ tftp_getsock, /* proto_getsock */
+ tftp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ tftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_TFTP, /* defport */
+ CURLPROTO_TFTP, /* protocol */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+};
+
+/**********************************************************
+ *
+ * tftp_set_timeouts -
+ *
+ * Set timeouts based on state machine state.
+ * Use user provided connect timeouts until DATA or ACK
+ * packet is received, then use user-provided transfer timeouts
+ *
+ *
+ **********************************************************/
+static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
+{
+ time_t maxtime, timeout;
+ long timeout_ms;
+ bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
+
+ time(&state->start_time);
+
+ /* Compute drop-dead time */
+ timeout_ms = Curl_timeleft(state->conn->data, NULL, start);
+
+ if(timeout_ms < 0) {
+ /* time-out, bail out, go home */
+ failf(state->conn->data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ if(start) {
+
+ maxtime = (time_t)(timeout_ms + 500) / 1000;
+ state->max_time = state->start_time+maxtime;
+
+ /* Set per-block timeout to total */
+ timeout = maxtime;
+
+ /* Average restart after 5 seconds */
+ state->retry_max = (int)timeout/5;
+
+ if(state->retry_max < 1)
+ /* avoid division by zero below */
+ state->retry_max = 1;
+
+ /* Compute the re-start interval to suit the timeout */
+ state->retry_time = (int)timeout/state->retry_max;
+ if(state->retry_time<1)
+ state->retry_time=1;
+
+ }
+ else {
+ if(timeout_ms > 0)
+ maxtime = (time_t)(timeout_ms + 500) / 1000;
+ else
+ maxtime = 3600;
+
+ state->max_time = state->start_time+maxtime;
+
+ /* Set per-block timeout to total */
+ timeout = maxtime;
+
+ /* Average reposting an ACK after 5 seconds */
+ state->retry_max = (int)timeout/5;
+ }
+ /* But bound the total number */
+ if(state->retry_max<3)
+ state->retry_max=3;
+
+ if(state->retry_max>50)
+ state->retry_max=50;
+
+ /* Compute the re-ACK interval to suit the timeout */
+ state->retry_time = (int)(timeout/state->retry_max);
+ if(state->retry_time<1)
+ state->retry_time=1;
+
+ infof(state->conn->data,
+ "set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
+ (int)state->state, (long)(state->max_time-state->start_time),
+ state->retry_time, state->retry_max);
+
+ /* init RX time */
+ time(&state->rx_time);
+
+ return CURLE_OK;
+}
+
+/**********************************************************
+ *
+ * tftp_set_send_first
+ *
+ * Event handler for the START state
+ *
+ **********************************************************/
+
+static void setpacketevent(tftp_packet_t *packet, unsigned short num)
+{
+ packet->data[0] = (unsigned char)(num >> 8);
+ packet->data[1] = (unsigned char)(num & 0xff);
+}
+
+
+static void setpacketblock(tftp_packet_t *packet, unsigned short num)
+{
+ packet->data[2] = (unsigned char)(num >> 8);
+ packet->data[3] = (unsigned char)(num & 0xff);
+}
+
+static unsigned short getrpacketevent(const tftp_packet_t *packet)
+{
+ return (unsigned short)((packet->data[0] << 8) | packet->data[1]);
+}
+
+static unsigned short getrpacketblock(const tftp_packet_t *packet)
+{
+ return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
+}
+
+static size_t Curl_strnlen(const char *string, size_t maxlen)
+{
+ const char *end = memchr (string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+
+static const char *tftp_option_get(const char *buf, size_t len,
+ const char **option, const char **value)
+{
+ size_t loc;
+
+ loc = Curl_strnlen( buf, len );
+ loc++; /* NULL term */
+
+ if(loc >= len)
+ return NULL;
+ *option = buf;
+
+ loc += Curl_strnlen( buf+loc, len-loc );
+ loc++; /* NULL term */
+
+ if(loc > len)
+ return NULL;
+ *value = &buf[strlen(*option) + 1];
+
+ return &buf[loc];
+}
+
+static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
+ const char *ptr, int len)
+{
+ const char *tmp = ptr;
+ struct SessionHandle *data = state->conn->data;
+
+ /* if OACK doesn't contain blksize option, the default (512) must be used */
+ state->blksize = TFTP_BLKSIZE_DEFAULT;
+
+ while(tmp < ptr + len) {
+ const char *option, *value;
+
+ tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value);
+ if(tmp == NULL) {
+ failf(data, "Malformed ACK packet, rejecting");
+ return CURLE_TFTP_ILLEGAL;
+ }
+
+ infof(data, "got option=(%s) value=(%s)\n", option, value);
+
+ if(checkprefix(option, TFTP_OPTION_BLKSIZE)) {
+ long blksize;
+
+ blksize = strtol( value, NULL, 10 );
+
+ if(!blksize) {
+ failf(data, "invalid blocksize value in OACK packet");
+ return CURLE_TFTP_ILLEGAL;
+ }
+ else if(blksize > TFTP_BLKSIZE_MAX) {
+ failf(data, "%s (%d)", "blksize is larger than max supported",
+ TFTP_BLKSIZE_MAX);
+ return CURLE_TFTP_ILLEGAL;
+ }
+ else if(blksize < TFTP_BLKSIZE_MIN) {
+ failf(data, "%s (%d)", "blksize is smaller than min supported",
+ TFTP_BLKSIZE_MIN);
+ return CURLE_TFTP_ILLEGAL;
+ }
+ else if(blksize > state->requested_blksize) {
+ /* could realloc pkt buffers here, but the spec doesn't call out
+ * support for the server requesting a bigger blksize than the client
+ * requests */
+ failf(data, "%s (%ld)",
+ "server requested blksize larger than allocated", blksize);
+ return CURLE_TFTP_ILLEGAL;
+ }
+
+ state->blksize = (int)blksize;
+ infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK",
+ state->blksize, "requested", state->requested_blksize);
+ }
+ else if(checkprefix(option, TFTP_OPTION_TSIZE)) {
+ long tsize = 0;
+
+ tsize = strtol( value, NULL, 10 );
+ infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize);
+
+ /* tsize should be ignored on upload: Who cares about the size of the
+ remote file? */
+ if(!data->set.upload) {
+ if(!tsize) {
+ failf(data, "invalid tsize -:%s:- value in OACK packet", value);
+ return CURLE_TFTP_ILLEGAL;
+ }
+ Curl_pgrsSetDownloadSize(data, tsize);
+ }
+ }
+ }
+
+ return CURLE_OK;
+}
+
+static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
+ char *buf, const char *option)
+{
+ if(( strlen(option) + csize + 1 ) > (size_t)state->blksize)
+ return 0;
+ strcpy(buf, option);
+ return strlen(option) + 1;
+}
+
+static CURLcode tftp_connect_for_tx(tftp_state_data_t *state,
+ tftp_event_t event)
+{
+ CURLcode result;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ struct SessionHandle *data = state->conn->data;
+
+ infof(data, "%s\n", "Connected for transmit");
+#endif
+ state->state = TFTP_STATE_TX;
+ result = tftp_set_timeouts(state);
+ if(result)
+ return result;
+ return tftp_tx(state, event);
+}
+
+static CURLcode tftp_connect_for_rx(tftp_state_data_t *state,
+ tftp_event_t event)
+{
+ CURLcode result;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ struct SessionHandle *data = state->conn->data;
+
+ infof(data, "%s\n", "Connected for receive");
+#endif
+ state->state = TFTP_STATE_RX;
+ result = tftp_set_timeouts(state);
+ if(result)
+ return result;
+ return tftp_rx(state, event);
+}
+
+static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
+{
+ size_t sbytes;
+ ssize_t senddata;
+ const char *mode = "octet";
+ char *filename;
+ char buf[64];
+ struct SessionHandle *data = state->conn->data;
+ CURLcode result = CURLE_OK;
+
+ /* Set ascii mode if -B flag was used */
+ if(data->set.prefer_ascii)
+ mode = "netascii";
+
+ switch(event) {
+
+ case TFTP_EVENT_INIT: /* Send the first packet out */
+ case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */
+ /* Increment the retry counter, quit if over the limit */
+ state->retries++;
+ if(state->retries>state->retry_max) {
+ state->error = TFTP_ERR_NORESPONSE;
+ state->state = TFTP_STATE_FIN;
+ return result;
+ }
+
+ if(data->set.upload) {
+ /* If we are uploading, send an WRQ */
+ setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
+ state->conn->data->req.upload_fromhere =
+ (char *)state->spacket.data+4;
+ if(data->state.infilesize != -1)
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+ else {
+ /* If we are downloading, send an RRQ */
+ setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
+ }
+ /* As RFC3617 describes the separator slash is not actually part of the
+ file name so we skip the always-present first letter of the path
+ string. */
+ filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
+ NULL);
+ if(!filename)
+ return CURLE_OUT_OF_MEMORY;
+
+ snprintf((char *)state->spacket.data+2,
+ state->blksize,
+ "%s%c%s%c", filename, '\0', mode, '\0');
+ sbytes = 4 + strlen(filename) + strlen(mode);
+
+ /* add tsize option */
+ if(data->set.upload && (data->state.infilesize != -1))
+ snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
+ data->state.infilesize);
+ else
+ strcpy(buf, "0"); /* the destination is large enough */
+
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes,
+ TFTP_OPTION_TSIZE);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes, buf);
+ /* add blksize option */
+ snprintf( buf, sizeof(buf), "%d", state->requested_blksize );
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes,
+ TFTP_OPTION_BLKSIZE);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes, buf );
+
+ /* add timeout option */
+ snprintf( buf, sizeof(buf), "%d", state->retry_time);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes,
+ TFTP_OPTION_INTERVAL);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes, buf );
+
+ /* the typecase for the 3rd argument is mostly for systems that do
+ not have a size_t argument, like older unixes that want an 'int' */
+ senddata = sendto(state->sockfd, (void *)state->spacket.data,
+ (SEND_TYPE_ARG3)sbytes, 0,
+ state->conn->ip_addr->ai_addr,
+ state->conn->ip_addr->ai_addrlen);
+ if(senddata != (ssize_t)sbytes) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ }
+ free(filename);
+ break;
+
+ case TFTP_EVENT_OACK:
+ if(data->set.upload) {
+ result = tftp_connect_for_tx(state, event);
+ }
+ else {
+ result = tftp_connect_for_rx(state, event);
+ }
+ break;
+
+ case TFTP_EVENT_ACK: /* Connected for transmit */
+ result = tftp_connect_for_tx(state, event);
+ break;
+
+ case TFTP_EVENT_DATA: /* Connected for receive */
+ result = tftp_connect_for_rx(state, event);
+ break;
+
+ case TFTP_EVENT_ERROR:
+ state->state = TFTP_STATE_FIN;
+ break;
+
+ default:
+ failf(state->conn->data, "tftp_send_first: internal error");
+ break;
+ }
+
+ return result;
+}
+
+/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
+ boundary */
+#define NEXT_BLOCKNUM(x) (((x)+1)&0xffff)
+
+/**********************************************************
+ *
+ * tftp_rx
+ *
+ * Event handler for the RX state
+ *
+ **********************************************************/
+static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
+{
+ ssize_t sbytes;
+ int rblock;
+ struct SessionHandle *data = state->conn->data;
+
+ switch(event) {
+
+ case TFTP_EVENT_DATA:
+ /* Is this the block we expect? */
+ rblock = getrpacketblock(&state->rpacket);
+ if(NEXT_BLOCKNUM(state->block) == rblock) {
+ /* This is the expected block. Reset counters and ACK it. */
+ state->retries = 0;
+ }
+ else if(state->block == rblock) {
+ /* This is the last recently received block again. Log it and ACK it
+ again. */
+ infof(data, "Received last DATA packet block %d again.\n", rblock);
+ }
+ else {
+ /* totally unexpected, just log it */
+ infof(data,
+ "Received unexpected DATA packet block %d, expecting block %d\n",
+ rblock, NEXT_BLOCKNUM(state->block));
+ break;
+ }
+
+ /* ACK this block. */
+ state->block = (unsigned short)rblock;
+ setpacketevent(&state->spacket, TFTP_EVENT_ACK);
+ setpacketblock(&state->spacket, state->block);
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ if(sbytes < 0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+
+ /* Check if completed (That is, a less than full packet is received) */
+ if(state->rbytes < (ssize_t)state->blksize+4) {
+ state->state = TFTP_STATE_FIN;
+ }
+ else {
+ state->state = TFTP_STATE_RX;
+ }
+ time(&state->rx_time);
+ break;
+
+ case TFTP_EVENT_OACK:
+ /* ACK option acknowledgement so we can move on to data */
+ state->block = 0;
+ state->retries = 0;
+ setpacketevent(&state->spacket, TFTP_EVENT_ACK);
+ setpacketblock(&state->spacket, state->block);
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ if(sbytes < 0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+
+ /* we're ready to RX data */
+ state->state = TFTP_STATE_RX;
+ time(&state->rx_time);
+ break;
+
+ case TFTP_EVENT_TIMEOUT:
+ /* Increment the retry count and fail if over the limit */
+ state->retries++;
+ infof(data,
+ "Timeout waiting for block %d ACK. Retries = %d\n",
+ NEXT_BLOCKNUM(state->block), state->retries);
+ if(state->retries > state->retry_max) {
+ state->error = TFTP_ERR_TIMEOUT;
+ state->state = TFTP_STATE_FIN;
+ }
+ else {
+ /* Resend the previous ACK */
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+ }
+ break;
+
+ case TFTP_EVENT_ERROR:
+ setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
+ setpacketblock(&state->spacket, state->block);
+ (void)sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* don't bother with the return code, but if the socket is still up we
+ * should be a good TFTP client and let the server know we're done */
+ state->state = TFTP_STATE_FIN;
+ break;
+
+ default:
+ failf(data, "%s", "tftp_rx: internal error");
+ return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for
+ this */
+ }
+ return CURLE_OK;
+}
+
+/**********************************************************
+ *
+ * tftp_tx
+ *
+ * Event handler for the TX state
+ *
+ **********************************************************/
+static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
+{
+ struct SessionHandle *data = state->conn->data;
+ ssize_t sbytes;
+ int rblock;
+ CURLcode result = CURLE_OK;
+ struct SingleRequest *k = &data->req;
+
+ switch(event) {
+
+ case TFTP_EVENT_ACK:
+ case TFTP_EVENT_OACK:
+ if(event == TFTP_EVENT_ACK) {
+ /* Ack the packet */
+ rblock = getrpacketblock(&state->rpacket);
+
+ if(rblock != state->block &&
+ /* There's a bug in tftpd-hpa that causes it to send us an ack for
+ * 65535 when the block number wraps to 0. So when we're expecting
+ * 0, also accept 65535. See
+ * http://syslinux.zytor.com/archives/2010-September/015253.html
+ * */
+ !(state->block == 0 && rblock == 65535)) {
+ /* This isn't the expected block. Log it and up the retry counter */
+ infof(data, "Received ACK for block %d, expecting %d\n",
+ rblock, state->block);
+ state->retries++;
+ /* Bail out if over the maximum */
+ if(state->retries>state->retry_max) {
+ failf(data, "tftp_tx: giving up waiting for block %d ack",
+ state->block);
+ result = CURLE_SEND_ERROR;
+ }
+ else {
+ /* Re-send the data packet */
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4+state->sbytes, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* Check all sbytes were sent */
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ result = CURLE_SEND_ERROR;
+ }
+ }
+
+ return result;
+ }
+ /* This is the expected packet. Reset the counters and send the next
+ block */
+ time(&state->rx_time);
+ state->block++;
+ }
+ else
+ state->block = 1; /* first data block is 1 when using OACK */
+
+ state->retries = 0;
+ setpacketevent(&state->spacket, TFTP_EVENT_DATA);
+ setpacketblock(&state->spacket, state->block);
+ if(state->block > 1 && state->sbytes < (int)state->blksize) {
+ state->state = TFTP_STATE_FIN;
+ return CURLE_OK;
+ }
+
+ result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes);
+ if(result)
+ return result;
+
+ sbytes = sendto(state->sockfd, (void *) state->spacket.data,
+ 4 + state->sbytes, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* Check all sbytes were sent */
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+ /* Update the progress meter */
+ k->writebytecount += state->sbytes;
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ break;
+
+ case TFTP_EVENT_TIMEOUT:
+ /* Increment the retry counter and log the timeout */
+ state->retries++;
+ infof(data, "Timeout waiting for block %d ACK. "
+ " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries);
+ /* Decide if we've had enough */
+ if(state->retries > state->retry_max) {
+ state->error = TFTP_ERR_TIMEOUT;
+ state->state = TFTP_STATE_FIN;
+ }
+ else {
+ /* Re-send the data packet */
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4+state->sbytes, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* Check all sbytes were sent */
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+ /* since this was a re-send, we remain at the still byte position */
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ }
+ break;
+
+ case TFTP_EVENT_ERROR:
+ state->state = TFTP_STATE_FIN;
+ setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
+ setpacketblock(&state->spacket, state->block);
+ (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* don't bother with the return code, but if the socket is still up we
+ * should be a good TFTP client and let the server know we're done */
+ state->state = TFTP_STATE_FIN;
+ break;
+
+ default:
+ failf(data, "tftp_tx: internal error, event: %i", (int)(event));
+ break;
+ }
+
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_translate_code
+ *
+ * Translate internal error codes to CURL error codes
+ *
+ **********************************************************/
+static CURLcode tftp_translate_code(tftp_error_t error)
+{
+ CURLcode result = CURLE_OK;
+
+ if(error != TFTP_ERR_NONE) {
+ switch(error) {
+ case TFTP_ERR_NOTFOUND:
+ result = CURLE_TFTP_NOTFOUND;
+ break;
+ case TFTP_ERR_PERM:
+ result = CURLE_TFTP_PERM;
+ break;
+ case TFTP_ERR_DISKFULL:
+ result = CURLE_REMOTE_DISK_FULL;
+ break;
+ case TFTP_ERR_UNDEF:
+ case TFTP_ERR_ILLEGAL:
+ result = CURLE_TFTP_ILLEGAL;
+ break;
+ case TFTP_ERR_UNKNOWNID:
+ result = CURLE_TFTP_UNKNOWNID;
+ break;
+ case TFTP_ERR_EXISTS:
+ result = CURLE_REMOTE_FILE_EXISTS;
+ break;
+ case TFTP_ERR_NOSUCHUSER:
+ result = CURLE_TFTP_NOSUCHUSER;
+ break;
+ case TFTP_ERR_TIMEOUT:
+ result = CURLE_OPERATION_TIMEDOUT;
+ break;
+ case TFTP_ERR_NORESPONSE:
+ result = CURLE_COULDNT_CONNECT;
+ break;
+ default:
+ result = CURLE_ABORTED_BY_CALLBACK;
+ break;
+ }
+ }
+ else
+ result = CURLE_OK;
+
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_state_machine
+ *
+ * The tftp state machine event dispatcher
+ *
+ **********************************************************/
+static CURLcode tftp_state_machine(tftp_state_data_t *state,
+ tftp_event_t event)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = state->conn->data;
+
+ switch(state->state) {
+ case TFTP_STATE_START:
+ DEBUGF(infof(data, "TFTP_STATE_START\n"));
+ result = tftp_send_first(state, event);
+ break;
+ case TFTP_STATE_RX:
+ DEBUGF(infof(data, "TFTP_STATE_RX\n"));
+ result = tftp_rx(state, event);
+ break;
+ case TFTP_STATE_TX:
+ DEBUGF(infof(data, "TFTP_STATE_TX\n"));
+ result = tftp_tx(state, event);
+ break;
+ case TFTP_STATE_FIN:
+ infof(data, "%s\n", "TFTP finished");
+ break;
+ default:
+ DEBUGF(infof(data, "STATE: %d\n", state->state));
+ failf(data, "%s", "Internal state machine error");
+ result = CURLE_TFTP_ILLEGAL;
+ break;
+ }
+
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_disconnect
+ *
+ * The disconnect callback
+ *
+ **********************************************************/
+static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ tftp_state_data_t *state = conn->proto.tftpc;
+ (void) dead_connection;
+
+ /* done, free dynamically allocated pkt buffers */
+ if(state) {
+ Curl_safefree(state->rpacket.data);
+ Curl_safefree(state->spacket.data);
+ free(state);
+ }
+
+ return CURLE_OK;
+}
+
+/**********************************************************
+ *
+ * tftp_connect
+ *
+ * The connect callback
+ *
+ **********************************************************/
+static CURLcode tftp_connect(struct connectdata *conn, bool *done)
+{
+ tftp_state_data_t *state;
+ int blksize, rc;
+
+ blksize = TFTP_BLKSIZE_DEFAULT;
+
+ state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
+ if(!state)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* alloc pkt buffers based on specified blksize */
+ if(conn->data->set.tftp_blksize) {
+ blksize = (int)conn->data->set.tftp_blksize;
+ if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN )
+ return CURLE_TFTP_ILLEGAL;
+ }
+
+ if(!state->rpacket.data) {
+ state->rpacket.data = calloc(1, blksize + 2 + 2);
+
+ if(!state->rpacket.data)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!state->spacket.data) {
+ state->spacket.data = calloc(1, blksize + 2 + 2);
+
+ if(!state->spacket.data)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* we don't keep TFTP connections up bascially because there's none or very
+ * little gain for UDP */
+ connclose(conn, "TFTP");
+
+ state->conn = conn;
+ state->sockfd = state->conn->sock[FIRSTSOCKET];
+ state->state = TFTP_STATE_START;
+ state->error = TFTP_ERR_NONE;
+ state->blksize = TFTP_BLKSIZE_DEFAULT;
+ state->requested_blksize = blksize;
+
+ ((struct sockaddr *)&state->local_addr)->sa_family =
+ (unsigned short)(conn->ip_addr->ai_family);
+
+ tftp_set_timeouts(state);
+
+ if(!conn->bits.bound) {
+ /* If not already bound, bind to any interface, random UDP port. If it is
+ * reused or a custom local port was desired, this has already been done!
+ *
+ * We once used the size of the local_addr struct as the third argument
+ * for bind() to better work with IPv6 or whatever size the struct could
+ * have, but we learned that at least Tru64, AIX and IRIX *requires* the
+ * size of that argument to match the exact size of a 'sockaddr_in' struct
+ * when running IPv4-only.
+ *
+ * Therefore we use the size from the address we connected to, which we
+ * assume uses the same IP version and thus hopefully this works for both
+ * IPv4 and IPv6...
+ */
+ rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
+ conn->ip_addr->ai_addrlen);
+ if(rc) {
+ failf(conn->data, "bind() failed; %s",
+ Curl_strerror(conn, SOCKERRNO));
+ return CURLE_COULDNT_CONNECT;
+ }
+ conn->bits.bound = TRUE;
+ }
+
+ Curl_pgrsStartNow(conn->data);
+
+ *done = TRUE;
+
+ return CURLE_OK;
+}
+
+/**********************************************************
+ *
+ * tftp_done
+ *
+ * The done callback
+ *
+ **********************************************************/
+static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode result = CURLE_OK;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+
+ (void)status; /* unused */
+ (void)premature; /* not used */
+
+ if(Curl_pgrsDone(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+
+ /* If we have encountered an error */
+ if(state)
+ result = tftp_translate_code(state->error);
+
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_getsock
+ *
+ * The getsock callback
+ *
+ **********************************************************/
+static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ socks[0] = conn->sock[FIRSTSOCKET];
+
+ return GETSOCK_READSOCK(0);
+}
+
+/**********************************************************
+ *
+ * tftp_receive_packet
+ *
+ * Called once select fires and data is ready on the socket
+ *
+ **********************************************************/
+static CURLcode tftp_receive_packet(struct connectdata *conn)
+{
+ struct Curl_sockaddr_storage fromaddr;
+ curl_socklen_t fromlen;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ struct SingleRequest *k = &data->req;
+
+ /* Receive the packet */
+ fromlen = sizeof(fromaddr);
+ state->rbytes = (int)recvfrom(state->sockfd,
+ (void *)state->rpacket.data,
+ state->blksize+4,
+ 0,
+ (struct sockaddr *)&fromaddr,
+ &fromlen);
+ if(state->remote_addrlen==0) {
+ memcpy(&state->remote_addr, &fromaddr, fromlen);
+ state->remote_addrlen = fromlen;
+ }
+
+ /* Sanity check packet length */
+ if(state->rbytes < 4) {
+ failf(data, "Received too short packet");
+ /* Not a timeout, but how best to handle it? */
+ state->event = TFTP_EVENT_TIMEOUT;
+ }
+ else {
+ /* The event is given by the TFTP packet time */
+ state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
+
+ switch(state->event) {
+ case TFTP_EVENT_DATA:
+ /* Don't pass to the client empty or retransmitted packets */
+ if(state->rbytes > 4 &&
+ (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ (char *)state->rpacket.data+4,
+ state->rbytes-4);
+ if(result) {
+ tftp_state_machine(state, TFTP_EVENT_ERROR);
+ return result;
+ }
+ k->bytecount += state->rbytes-4;
+ Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
+ }
+ break;
+ case TFTP_EVENT_ERROR:
+ state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
+ infof(data, "%s\n", (const char *)state->rpacket.data+4);
+ break;
+ case TFTP_EVENT_ACK:
+ break;
+ case TFTP_EVENT_OACK:
+ result = tftp_parse_option_ack(state,
+ (const char *)state->rpacket.data+2,
+ state->rbytes-2);
+ if(result)
+ return result;
+ break;
+ case TFTP_EVENT_RRQ:
+ case TFTP_EVENT_WRQ:
+ default:
+ failf(data, "%s", "Internal error: Unexpected packet");
+ break;
+ }
+
+ /* Update the progress meter */
+ if(Curl_pgrsUpdate(conn)) {
+ tftp_state_machine(state, TFTP_EVENT_ERROR);
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ }
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_state_timeout
+ *
+ * Check if timeouts have been reached
+ *
+ **********************************************************/
+static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
+{
+ time_t current;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+
+ if(event)
+ *event = TFTP_EVENT_NONE;
+
+ time(&current);
+ if(current > state->max_time) {
+ DEBUGF(infof(conn->data, "timeout: %ld > %ld\n",
+ (long)current, (long)state->max_time));
+ state->error = TFTP_ERR_TIMEOUT;
+ state->state = TFTP_STATE_FIN;
+ return 0;
+ }
+ else if(current > state->rx_time+state->retry_time) {
+ if(event)
+ *event = TFTP_EVENT_TIMEOUT;
+ time(&state->rx_time); /* update even though we received nothing */
+ }
+
+ /* there's a typecast below here since 'time_t' may in fact be larger than
+ 'long', but we estimate that a 'long' will still be able to hold number
+ of seconds even if "only" 32 bit */
+ return (long)(state->max_time - current);
+}
+
+/**********************************************************
+ *
+ * tftp_multi_statemach
+ *
+ * Handle single RX socket event and return
+ *
+ **********************************************************/
+static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
+{
+ int rc;
+ tftp_event_t event;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ long timeout_ms = tftp_state_timeout(conn, &event);
+
+ *done = FALSE;
+
+ if(timeout_ms <= 0) {
+ failf(data, "TFTP response timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ else if(event != TFTP_EVENT_NONE) {
+ result = tftp_state_machine(state, event);
+ if(result)
+ return result;
+ *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
+ if(*done)
+ /* Tell curl we're done */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ }
+ else {
+ /* no timeouts to handle, check our socket */
+ rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0);
+
+ if(rc == -1) {
+ /* bail out */
+ int error = SOCKERRNO;
+ failf(data, "%s", Curl_strerror(conn, error));
+ state->event = TFTP_EVENT_ERROR;
+ }
+ else if(rc != 0) {
+ result = tftp_receive_packet(conn);
+ if(result)
+ return result;
+ result = tftp_state_machine(state, state->event);
+ if(result)
+ return result;
+ *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
+ if(*done)
+ /* Tell curl we're done */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ }
+ /* if rc == 0, then select() timed out */
+ }
+
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_doing
+ *
+ * Called from multi.c while DOing
+ *
+ **********************************************************/
+static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result;
+ result = tftp_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+ else if(!result) {
+ /* The multi code doesn't have this logic for the DOING state so we
+ provide it for TFTP since it may do the entire transfer in this
+ state. */
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(conn->data, Curl_tvnow());
+ }
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_peform
+ *
+ * Entry point for transfer from tftp_do, sarts state mach
+ *
+ **********************************************************/
+static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+
+ *dophase_done = FALSE;
+
+ result = tftp_state_machine(state, TFTP_EVENT_INIT);
+
+ if((state->state == TFTP_STATE_FIN) || result)
+ return result;
+
+ tftp_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+
+/**********************************************************
+ *
+ * tftp_do
+ *
+ * The do callback
+ *
+ * This callback initiates the TFTP transfer
+ *
+ **********************************************************/
+
+static CURLcode tftp_do(struct connectdata *conn, bool *done)
+{
+ tftp_state_data_t *state;
+ CURLcode result;
+
+ *done = FALSE;
+
+ if(!conn->proto.tftpc) {
+ result = tftp_connect(conn, done);
+ if(result)
+ return result;
+ }
+
+ state = (tftp_state_data_t *)conn->proto.tftpc;
+ if(!state)
+ return CURLE_BAD_CALLING_ORDER;
+
+ result = tftp_perform(conn, done);
+
+ /* If tftp_perform() returned an error, use that for return code. If it
+ was OK, see if tftp_translate_code() has an error. */
+ if(!result)
+ /* If we have encountered an internal tftp error, translate it. */
+ result = tftp_translate_code(state->error);
+
+ return result;
+}
+
+static CURLcode tftp_setup_connection(struct connectdata * conn)
+{
+ struct SessionHandle *data = conn->data;
+ char * type;
+ char command;
+
+ conn->socktype = SOCK_DGRAM; /* UDP datagram based */
+
+ /* TFTP URLs support an extension like ";mode=<typecode>" that
+ * we'll try to get now! */
+ type = strstr(data->state.path, ";mode=");
+
+ if(!type)
+ type = strstr(conn->host.rawalloc, ";mode=");
+
+ if(type) {
+ *type = 0; /* it was in the middle of the hostname */
+ command = Curl_raw_toupper(type[6]);
+
+ switch (command) {
+ case 'A': /* ASCII mode */
+ case 'N': /* NETASCII mode */
+ data->set.prefer_ascii = TRUE;
+ break;
+
+ case 'O': /* octet mode */
+ case 'I': /* binary mode */
+ default:
+ /* switch off ASCII */
+ data->set.prefer_ascii = FALSE;
+ break;
+ }
+ }
+
+ return CURLE_OK;
+}
+#endif
diff --git a/libcurl/src/lib/tftp.h b/libcurl/src/lib/tftp.h
new file mode 100644
index 0000000..117b40f
--- /dev/null
+++ b/libcurl/src/lib/tftp.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TFTP_H
+#define HEADER_CURL_TFTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_TFTP
+extern const struct Curl_handler Curl_handler_tftp;
+#endif
+
+#endif /* HEADER_CURL_TFTP_H */
+
diff --git a/libcurl/src/lib/timeval.c b/libcurl/src/lib/timeval.c
new file mode 100644
index 0000000..b6f398d
--- /dev/null
+++ b/libcurl/src/lib/timeval.c
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "timeval.h"
+
+#if defined(WIN32) && !defined(MSDOS)
+
+CURL_STATIC struct timeval curlx_tvnow(void)
+{
+ /*
+ ** GetTickCount() is available on _all_ Windows versions from W95 up
+ ** to nowadays. Returns milliseconds elapsed since last system boot,
+ ** increases monotonically and wraps once 49.7 days have elapsed.
+ */
+ struct timeval now;
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+ DWORD milliseconds = GetTickCount();
+ now.tv_sec = milliseconds / 1000;
+ now.tv_usec = (milliseconds % 1000) * 1000;
+#else
+ ULONGLONG milliseconds = GetTickCount64();
+ now.tv_sec = (long) (milliseconds / 1000);
+ now.tv_usec = (long) (milliseconds % 1000) * 1000;
+#endif
+
+ return now;
+}
+
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+CURL_STATIC struct timeval curlx_tvnow(void)
+{
+ /*
+ ** clock_gettime() is granted to be increased monotonically when the
+ ** monotonic clock is queried. Time starting point is unspecified, it
+ ** could be the system start-up time, the Epoch, or something else,
+ ** in any case the time starting point does not change once that the
+ ** system has started up.
+ */
+ struct timeval now;
+ struct timespec tsnow;
+ if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
+ now.tv_sec = tsnow.tv_sec;
+ now.tv_usec = tsnow.tv_nsec / 1000;
+ }
+ /*
+ ** Even when the configure process has truly detected monotonic clock
+ ** availability, it might happen that it is not actually available at
+ ** run-time. When this occurs simply fallback to other time source.
+ */
+#ifdef HAVE_GETTIMEOFDAY
+ else
+ (void)gettimeofday(&now, NULL);
+#else
+ else {
+ now.tv_sec = (long)time(NULL);
+ now.tv_usec = 0;
+ }
+#endif
+ return now;
+}
+
+#elif defined(HAVE_GETTIMEOFDAY)
+
+CURL_STATIC struct timeval curlx_tvnow(void)
+{
+ /*
+ ** gettimeofday() is not granted to be increased monotonically, due to
+ ** clock drifting and external source time synchronization it can jump
+ ** forward or backward in time.
+ */
+ struct timeval now;
+ (void)gettimeofday(&now, NULL);
+ return now;
+}
+
+#else
+
+CURL_STATIC struct timeval curlx_tvnow(void)
+{
+ /*
+ ** time() returns the value of time in seconds since the Epoch.
+ */
+ struct timeval now;
+ now.tv_sec = (long)time(NULL);
+ now.tv_usec = 0;
+ return now;
+}
+
+#endif
+
+/*
+ * Make sure that the first argument is the more recent time, as otherwise
+ * we'll get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+CURL_STATIC long curlx_tvdiff(struct timeval newer, struct timeval older)
+{
+ return (newer.tv_sec-older.tv_sec)*1000+
+ (long)(newer.tv_usec-older.tv_usec)/1000;
+}
+
+/*
+ * Same as curlx_tvdiff but with full usec resolution.
+ *
+ * Returns: the time difference in seconds with subsecond resolution.
+ */
+CURL_STATIC double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
+{
+ if(newer.tv_sec != older.tv_sec)
+ return (double)(newer.tv_sec-older.tv_sec)+
+ (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+ else
+ return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+}
+
+/* return the number of seconds in the given input timeval struct */
+CURL_STATIC long Curl_tvlong(struct timeval t1)
+{
+ return t1.tv_sec;
+}
diff --git a/libcurl/src/lib/timeval.h b/libcurl/src/lib/timeval.h
new file mode 100644
index 0000000..2562012
--- /dev/null
+++ b/libcurl/src/lib/timeval.h
@@ -0,0 +1,58 @@
+#ifndef HEADER_CURL_TIMEVAL_H
+#define HEADER_CURL_TIMEVAL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * CAUTION: this header is designed to work when included by the app-side
+ * as well as the library. Do not mix with library internals!
+ */
+
+#include "curl_setup.h"
+
+CURL_STATIC struct timeval curlx_tvnow(void);
+
+/*
+ * Make sure that the first argument (t1) is the more recent time and t2 is
+ * the older time, as otherwise you get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+CURL_STATIC long curlx_tvdiff(struct timeval t1, struct timeval t2);
+
+/*
+ * Same as curlx_tvdiff but with full usec resolution.
+ *
+ * Returns: the time difference in seconds with subsecond resolution.
+ */
+CURL_STATIC double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
+
+CURL_STATIC long Curl_tvlong(struct timeval t1);
+
+/* These two defines below exist to provide the older API for library
+ internals only. */
+#define Curl_tvnow() curlx_tvnow()
+#define Curl_tvdiff(x,y) curlx_tvdiff(x,y)
+#define Curl_tvdiff_secs(x,y) curlx_tvdiff_secs(x,y)
+
+#endif /* HEADER_CURL_TIMEVAL_H */
+
diff --git a/libcurl/src/lib/transfer.c b/libcurl/src/lib/transfer.c
new file mode 100644
index 0000000..227dc83
--- /dev/null
+++ b/libcurl/src/lib/transfer.c
@@ -0,0 +1,2004 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "rawstr.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef HAVE_SOCKET
+#error "We can't compile without socket() support!"
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "netrc.h"
+
+#include "content_encoding.h"
+#include "hostip.h"
+#include "transfer.h"
+#include "sendf.h"
+#include "speedcheck.h"
+#include "progress.h"
+#include "http.h"
+#include "url.h"
+#include "getinfo.h"
+#include "vtls/vtls.h"
+#include "http_digest.h"
+#include "curl_ntlm.h"
+#include "http_negotiate.h"
+#include "share.h"
+#include "select.h"
+#include "multiif.h"
+#include "connect.h"
+#include "non-ascii.h"
+#include "curl_printf.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * This function will call the read callback to fill our buffer with data
+ * to upload.
+ */
+CURL_STATIC CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
+{
+ struct SessionHandle *data = conn->data;
+ size_t buffersize = (size_t)bytes;
+ int nread;
+#ifdef CURL_DOES_CONVERSIONS
+ bool sending_http_headers = FALSE;
+
+ if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
+ const struct HTTP *http = data->req.protop;
+
+ if(http->sending == HTTPSEND_REQUEST)
+ /* We're sending the HTTP request headers, not the data.
+ Remember that so we don't re-translate them into garbage. */
+ sending_http_headers = TRUE;
+ }
+#endif
+
+ if(data->req.upload_chunky) {
+ /* if chunked Transfer-Encoding */
+ buffersize -= (8 + 2 + 2); /* 32bit hex + CRLF + CRLF */
+ data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
+ }
+
+ /* this function returns a size_t, so we typecast to int to prevent warnings
+ with picky compilers */
+ nread = (int)conn->fread_func(data->req.upload_fromhere, 1,
+ buffersize, conn->fread_in);
+
+ if(nread == CURL_READFUNC_ABORT) {
+ failf(data, "operation aborted by callback");
+ *nreadp = 0;
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ else if(nread == CURL_READFUNC_PAUSE) {
+
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ /* protocols that work without network cannot be paused. This is
+ actually only FILE:// just now, and it can't pause since the transfer
+ isn't done using the "normal" procedure. */
+ failf(data, "Read callback asked for PAUSE when not supported!");
+ return CURLE_READ_ERROR;
+ }
+ else {
+ struct SingleRequest *k = &data->req;
+ /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
+ k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
+ if(data->req.upload_chunky) {
+ /* Back out the preallocation done above */
+ data->req.upload_fromhere -= (8 + 2);
+ }
+ *nreadp = 0;
+ }
+ return CURLE_OK; /* nothing was read */
+ }
+ else if((size_t)nread > buffersize) {
+ /* the read function returned a too large value */
+ *nreadp = 0;
+ failf(data, "read function returned funny value");
+ return CURLE_READ_ERROR;
+ }
+
+ if(!data->req.forbidchunk && data->req.upload_chunky) {
+ /* if chunked Transfer-Encoding
+ * build chunk:
+ *
+ * <HEX SIZE> CRLF
+ * <DATA> CRLF
+ */
+ /* On non-ASCII platforms the <DATA> may or may not be
+ translated based on set.prefer_ascii while the protocol
+ portion must always be translated to the network encoding.
+ To further complicate matters, line end conversion might be
+ done later on, so we need to prevent CRLFs from becoming
+ CRCRLFs if that's the case. To do this we use bare LFs
+ here, knowing they'll become CRLFs later on.
+ */
+
+ char hexbuffer[11];
+ const char *endofline_native;
+ const char *endofline_network;
+ int hexlen;
+
+ if(
+#ifdef CURL_DO_LINEEND_CONV
+ (data->set.prefer_ascii) ||
+#endif
+ (data->set.crlf)) {
+ /* \n will become \r\n later on */
+ endofline_native = "\n";
+ endofline_network = "\x0a";
+ }
+ else {
+ endofline_native = "\r\n";
+ endofline_network = "\x0d\x0a";
+ }
+ hexlen = snprintf(hexbuffer, sizeof(hexbuffer),
+ "%x%s", nread, endofline_native);
+
+ /* move buffer pointer */
+ data->req.upload_fromhere -= hexlen;
+ nread += hexlen;
+
+ /* copy the prefix to the buffer, leaving out the NUL */
+ memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
+
+ /* always append ASCII CRLF to the data */
+ memcpy(data->req.upload_fromhere + nread,
+ endofline_network,
+ strlen(endofline_network));
+
+#ifdef CURL_DOES_CONVERSIONS
+ CURLcode result;
+ int length;
+ if(data->set.prefer_ascii) {
+ /* translate the protocol and data */
+ length = nread;
+ }
+ else {
+ /* just translate the protocol portion */
+ length = strlen(hexbuffer);
+ }
+ result = Curl_convert_to_network(data, data->req.upload_fromhere, length);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result)
+ return result;
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if((nread - hexlen) == 0)
+ /* mark this as done once this chunk is transferred */
+ data->req.upload_done = TRUE;
+
+ nread+=(int)strlen(endofline_native); /* for the added end of line */
+ }
+#ifdef CURL_DOES_CONVERSIONS
+ else if((data->set.prefer_ascii) && (!sending_http_headers)) {
+ CURLcode result;
+ result = Curl_convert_to_network(data, data->req.upload_fromhere, nread);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result)
+ return result;
+ }
+#endif /* CURL_DOES_CONVERSIONS */
+
+ *nreadp = nread;
+
+ return CURLE_OK;
+}
+
+
+/*
+ * Curl_readrewind() rewinds the read stream. This is typically used for HTTP
+ * POST/PUT with multi-pass authentication when a sending was denied and a
+ * resend is necessary.
+ */
+CURL_STATIC CURLcode Curl_readrewind(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+
+ conn->bits.rewindaftersend = FALSE; /* we rewind now */
+
+ /* explicitly switch off sending data on this connection now since we are
+ about to restart a new transfer and thus we want to avoid inadvertently
+ sending more data on the existing connection until the next transfer
+ starts */
+ data->req.keepon &= ~KEEP_SEND;
+
+ /* We have sent away data. If not using CURLOPT_POSTFIELDS or
+ CURLOPT_HTTPPOST, call app to rewind
+ */
+ if(data->set.postfields ||
+ (data->set.httpreq == HTTPREQ_POST_FORM))
+ ; /* do nothing */
+ else {
+ if(data->set.seek_func) {
+ int err;
+
+ err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
+ if(err) {
+ failf(data, "seek callback returned error %d", (int)err);
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ else if(data->set.ioctl_func) {
+ curlioerr err;
+
+ err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
+ data->set.ioctl_client);
+ infof(data, "the ioctl callback returned %d\n", (int)err);
+
+ if(err) {
+ /* FIXME: convert to a human readable error message */
+ failf(data, "ioctl callback returned error %d", (int)err);
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ else {
+ /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
+ given FILE * stream and we can actually attempt to rewind that
+ ourselves with fseek() */
+ if(data->set.fread_func == (curl_read_callback)fread) {
+ if(-1 != fseek(data->set.in, 0, SEEK_SET))
+ /* successful rewind */
+ return CURLE_OK;
+ }
+
+ /* no callback set or failure above, makes us fail at once */
+ failf(data, "necessary data rewind wasn't possible");
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ return CURLE_OK;
+}
+
+static int data_pending(const struct connectdata *conn)
+{
+ /* in the case of libssh2, we can never be really sure that we have emptied
+ its internal buffers so we MUST always try until we get EAGAIN back */
+ return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
+#if defined(USE_NGHTTP2)
+ Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
+ /* For HTTP/2, we may read up everything including responde body
+ with header fields in Curl_http_readwrite_headers. If no
+ content-length is provided, curl waits for the connection
+ close, which we emulate it using conn->proto.httpc.closed =
+ TRUE. The thing is if we read everything, then http2_recv won't
+ be called and we cannot signal the HTTP/2 stream has closed. As
+ a workaround, we return nonzero here to call http2_recv. */
+ ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20 &&
+ conn->proto.httpc.closed);
+#else
+ Curl_ssl_data_pending(conn, FIRSTSOCKET);
+#endif
+}
+
+static void read_rewind(struct connectdata *conn,
+ size_t thismuch)
+{
+ DEBUGASSERT(conn->read_pos >= thismuch);
+
+ conn->read_pos -= thismuch;
+ conn->bits.stream_was_rewound = TRUE;
+
+#ifdef DEBUGBUILD
+ {
+ char buf[512 + 1];
+ size_t show;
+
+ show = CURLMIN(conn->buf_len - conn->read_pos, sizeof(buf)-1);
+ if(conn->master_buffer) {
+ memcpy(buf, conn->master_buffer + conn->read_pos, show);
+ buf[show] = '\0';
+ }
+ else {
+ buf[0] = '\0';
+ }
+
+ DEBUGF(infof(conn->data,
+ "Buffer after stream rewind (read_pos = %zu): [%s]\n",
+ conn->read_pos, buf));
+ }
+#endif
+}
+
+/*
+ * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the
+ * remote document with the time provided by CURLOPT_TIMEVAL
+ */
+CURL_STATIC bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc)
+{
+ if((timeofdoc == 0) || (data->set.timevalue == 0))
+ return TRUE;
+
+ switch(data->set.timecondition) {
+ case CURL_TIMECOND_IFMODSINCE:
+ default:
+ if(timeofdoc <= data->set.timevalue) {
+ infof(data,
+ "The requested document is not new enough\n");
+ data->info.timecond = TRUE;
+ return FALSE;
+ }
+ break;
+ case CURL_TIMECOND_IFUNMODSINCE:
+ if(timeofdoc >= data->set.timevalue) {
+ infof(data,
+ "The requested document is not old enough\n");
+ data->info.timecond = TRUE;
+ return FALSE;
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Go ahead and do a read if we have a readable socket or if
+ * the stream was rewound (in which case we have data in a
+ * buffer)
+ */
+static CURLcode readwrite_data(struct SessionHandle *data,
+ struct connectdata *conn,
+ struct SingleRequest *k,
+ int *didwhat, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ ssize_t nread; /* number of bytes read */
+ size_t excess = 0; /* excess bytes read */
+ bool is_empty_data = FALSE;
+ bool readmore = FALSE; /* used by RTP to signal for more data */
+
+ *done = FALSE;
+
+ /* This is where we loop until we have read everything there is to
+ read or we get a CURLE_AGAIN */
+ do {
+ size_t buffersize = data->set.buffer_size?
+ data->set.buffer_size : BUFSIZE;
+ size_t bytestoread = buffersize;
+
+ if(k->size != -1 && !k->header) {
+ /* make sure we don't read "too much" if we can help it since we
+ might be pipelining and then someone else might want to read what
+ follows! */
+ curl_off_t totalleft = k->size - k->bytecount;
+ if(totalleft < (curl_off_t)bytestoread)
+ bytestoread = (size_t)totalleft;
+ }
+
+ if(bytestoread) {
+ /* receive data from the network! */
+ result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread);
+
+ /* read would've blocked */
+ if(CURLE_AGAIN == result)
+ break; /* get out of loop */
+
+ if(result>0)
+ return result;
+ }
+ else {
+ /* read nothing but since we wanted nothing we consider this an OK
+ situation to proceed from */
+ nread = 0;
+ }
+
+ if((k->bytecount == 0) && (k->writebytecount == 0)) {
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+ if(k->exp100 > EXP100_SEND_DATA)
+ /* set time stamp to compare with when waiting for the 100 */
+ k->start100 = Curl_tvnow();
+ }
+
+ *didwhat |= KEEP_RECV;
+ /* indicates data of zero size, i.e. empty file */
+ is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
+
+ /* NUL terminate, allowing string ops to be used */
+ if(0 < nread || is_empty_data) {
+ k->buf[nread] = 0;
+ }
+ else if(0 >= nread) {
+ /* if we receive 0 or less here, the server closed the connection
+ and we bail out from this! */
+ DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n"));
+ k->keepon &= ~KEEP_RECV;
+ break;
+ }
+
+ /* Default buffer to use when we write the buffer, it may be changed
+ in the flow below before the actual storing is done. */
+ k->str = k->buf;
+
+ if(conn->handler->readwrite) {
+ result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ if(result)
+ return result;
+ if(readmore)
+ break;
+ }
+
+#ifndef CURL_DISABLE_HTTP
+ /* Since this is a two-state thing, we check if we are parsing
+ headers at the moment or not. */
+ if(k->header) {
+ /* we are in parse-the-header-mode */
+ bool stop_reading = FALSE;
+ result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
+ if(result)
+ return result;
+
+ if(conn->handler->readwrite &&
+ (k->maxdownload <= 0 && nread > 0)) {
+ result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ if(result)
+ return result;
+ if(readmore)
+ break;
+ }
+
+ if(stop_reading) {
+ /* We've stopped dealing with input, get out of the do-while loop */
+
+ if(nread > 0) {
+ if(Curl_multi_pipeline_enabled(conn->data->multi)) {
+ infof(data,
+ "Rewinding stream by : %zd"
+ " bytes on url %s (zero-length body)\n",
+ nread, data->state.path);
+ read_rewind(conn, (size_t)nread);
+ }
+ else {
+ infof(data,
+ "Excess found in a non pipelined read:"
+ " excess = %zd"
+ " url = %s (zero-length body)\n",
+ nread, data->state.path);
+ }
+ }
+
+ break;
+ }
+ }
+#endif /* CURL_DISABLE_HTTP */
+
+
+ /* This is not an 'else if' since it may be a rest from the header
+ parsing, where the beginning of the buffer is headers and the end
+ is non-headers. */
+ if(k->str && !k->header && (nread > 0 || is_empty_data)) {
+
+#ifndef CURL_DISABLE_HTTP
+ if(0 == k->bodywrites && !is_empty_data) {
+ /* These checks are only made the first time we are about to
+ write a piece of the body */
+ if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
+ /* HTTP-only checks */
+
+ if(data->req.newurl) {
+ if(conn->bits.close) {
+ /* Abort after the headers if "follow Location" is set
+ and we're set to close anyway. */
+ k->keepon &= ~KEEP_RECV;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ /* We have a new url to load, but since we want to be able
+ to re-use this connection properly, we read the full
+ response in "ignore more" */
+ k->ignorebody = TRUE;
+ infof(data, "Ignoring the response-body\n");
+ }
+ if(data->state.resume_from && !k->content_range &&
+ (data->set.httpreq==HTTPREQ_GET) &&
+ !k->ignorebody) {
+
+ if(k->size == data->state.resume_from) {
+ /* The resume point is at the end of file, consider this fine
+ even if it doesn't allow resume from here. */
+ infof(data, "The entire document is already downloaded");
+ connclose(conn, "already downloaded");
+ /* Abort download */
+ k->keepon &= ~KEEP_RECV;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* we wanted to resume a download, although the server doesn't
+ * seem to support this and we did this with a GET (if it
+ * wasn't a GET we did a POST or PUT resume) */
+ failf(data, "HTTP server doesn't seem to support "
+ "byte ranges. Cannot resume.");
+ return CURLE_RANGE_ERROR;
+ }
+
+ if(data->set.timecondition && !data->state.range) {
+ /* A time condition has been set AND no ranges have been
+ requested. This seems to be what chapter 13.3.4 of
+ RFC 2616 defines to be the correct action for a
+ HTTP/1.1 client */
+
+ if(!Curl_meets_timecondition(data, k->timeofdoc)) {
+ *done = TRUE;
+ /* We're simulating a http 304 from server so we return
+ what should have been returned from the server */
+ data->info.httpcode = 304;
+ infof(data, "Simulate a HTTP 304 response!\n");
+ /* we abort the transfer before it is completed == we ruin the
+ re-use ability. Close the connection */
+ connclose(conn, "Simulated 304 handling");
+ return CURLE_OK;
+ }
+ } /* we have a time condition */
+
+ } /* this is HTTP or RTSP */
+ } /* this is the first time we write a body part */
+#endif /* CURL_DISABLE_HTTP */
+
+ k->bodywrites++;
+
+ /* pass data to the debug function before it gets "dechunked" */
+ if(data->set.verbose) {
+ if(k->badheader) {
+ Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
+ (size_t)k->hbuflen, conn);
+ if(k->badheader == HEADER_PARTHEADER)
+ Curl_debug(data, CURLINFO_DATA_IN,
+ k->str, (size_t)nread, conn);
+ }
+ else
+ Curl_debug(data, CURLINFO_DATA_IN,
+ k->str, (size_t)nread, conn);
+ }
+
+#ifndef CURL_DISABLE_HTTP
+ if(k->chunk) {
+ /*
+ * Here comes a chunked transfer flying and we need to decode this
+ * properly. While the name says read, this function both reads
+ * and writes away the data. The returned 'nread' holds the number
+ * of actual data it wrote to the client.
+ */
+
+ CHUNKcode res =
+ Curl_httpchunk_read(conn, k->str, nread, &nread);
+
+ if(CHUNKE_OK < res) {
+ if(CHUNKE_WRITE_ERROR == res) {
+ failf(data, "Failed writing data");
+ return CURLE_WRITE_ERROR;
+ }
+ failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
+ return CURLE_RECV_ERROR;
+ }
+ else if(CHUNKE_STOP == res) {
+ size_t dataleft;
+ /* we're done reading chunks! */
+ k->keepon &= ~KEEP_RECV; /* read no more */
+
+ /* There are now possibly N number of bytes at the end of the
+ str buffer that weren't written to the client.
+
+ We DO care about this data if we are pipelining.
+ Push it back to be read on the next pass. */
+
+ dataleft = conn->chunk.dataleft;
+ if(dataleft != 0) {
+ infof(conn->data, "Leftovers after chunking: %zu bytes\n",
+ dataleft);
+ if(Curl_multi_pipeline_enabled(conn->data->multi)) {
+ /* only attempt the rewind if we truly are pipelining */
+ infof(conn->data, "Rewinding %zu bytes\n",dataleft);
+ read_rewind(conn, dataleft);
+ }
+ }
+ }
+ /* If it returned OK, we just keep going */
+ }
+#endif /* CURL_DISABLE_HTTP */
+
+ /* Account for body content stored in the header buffer */
+ if(k->badheader && !k->ignorebody) {
+ DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n",
+ k->hbuflen));
+ k->bytecount += k->hbuflen;
+ }
+
+ if((-1 != k->maxdownload) &&
+ (k->bytecount + nread >= k->maxdownload)) {
+
+ excess = (size_t)(k->bytecount + nread - k->maxdownload);
+ if(excess > 0 && !k->ignorebody) {
+ if(Curl_multi_pipeline_enabled(conn->data->multi)) {
+ /* The 'excess' amount below can't be more than BUFSIZE which
+ always will fit in a size_t */
+ infof(data,
+ "Rewinding stream by : %zu"
+ " bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
+ ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+ ", bytecount = %" CURL_FORMAT_CURL_OFF_T ", nread = %zd)\n",
+ excess, data->state.path,
+ k->size, k->maxdownload, k->bytecount, nread);
+ read_rewind(conn, excess);
+ }
+ else {
+ infof(data,
+ "Excess found in a non pipelined read:"
+ " excess = %zu"
+ ", size = %" CURL_FORMAT_CURL_OFF_T
+ ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+ ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n",
+ excess, k->size, k->maxdownload, k->bytecount);
+ }
+ }
+
+ nread = (ssize_t) (k->maxdownload - k->bytecount);
+ if(nread < 0 ) /* this should be unusual */
+ nread = 0;
+
+ k->keepon &= ~KEEP_RECV; /* we're done reading */
+ }
+
+ k->bytecount += nread;
+
+ Curl_pgrsSetDownloadCounter(data, k->bytecount);
+
+ if(!k->chunk && (nread || k->badheader || is_empty_data)) {
+ /* If this is chunky transfer, it was already written */
+
+ if(k->badheader && !k->ignorebody) {
+ /* we parsed a piece of data wrongly assuming it was a header
+ and now we output it as body instead */
+
+ /* Don't let excess data pollute body writes */
+ if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload)
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ data->state.headerbuff,
+ k->hbuflen);
+ else
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ data->state.headerbuff,
+ (size_t)k->maxdownload);
+
+ if(result)
+ return result;
+ }
+ if(k->badheader < HEADER_ALLBAD) {
+ /* This switch handles various content encodings. If there's an
+ error here, be sure to check over the almost identical code
+ in http_chunks.c.
+ Make sure that ALL_CONTENT_ENCODINGS contains all the
+ encodings handled here. */
+#ifdef HAVE_LIBZ
+ switch (conn->data->set.http_ce_skip ?
+ IDENTITY : k->auto_decoding) {
+ case IDENTITY:
+#endif
+ /* This is the default when the server sends no
+ Content-Encoding header. See Curl_readwrite_init; the
+ memset() call initializes k->auto_decoding to zero. */
+ if(!k->ignorebody) {
+
+#ifndef CURL_DISABLE_POP3
+ if(conn->handler->protocol&PROTO_FAMILY_POP3)
+ result = Curl_pop3_write(conn, k->str, nread);
+ else
+#endif /* CURL_DISABLE_POP3 */
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
+ nread);
+ }
+#ifdef HAVE_LIBZ
+ break;
+
+ case DEFLATE:
+ /* Assume CLIENTWRITE_BODY; headers are not encoded. */
+ if(!k->ignorebody)
+ result = Curl_unencode_deflate_write(conn, k, nread);
+ break;
+
+ case GZIP:
+ /* Assume CLIENTWRITE_BODY; headers are not encoded. */
+ if(!k->ignorebody)
+ result = Curl_unencode_gzip_write(conn, k, nread);
+ break;
+
+ case COMPRESS:
+ default:
+ failf (data, "Unrecognized content encoding type. "
+ "libcurl understands `identity', `deflate' and `gzip' "
+ "content encodings.");
+ result = CURLE_BAD_CONTENT_ENCODING;
+ break;
+ }
+#endif
+ }
+ k->badheader = HEADER_NORMAL; /* taken care of now */
+
+ if(result)
+ return result;
+ }
+
+ } /* if(! header and data to read ) */
+
+ if(conn->handler->readwrite &&
+ (excess > 0 && !conn->bits.stream_was_rewound)) {
+ /* Parse the excess data */
+ k->str += nread;
+ nread = (ssize_t)excess;
+
+ result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ if(result)
+ return result;
+
+ if(readmore)
+ k->keepon |= KEEP_RECV; /* we're not done reading */
+ break;
+ }
+
+ if(is_empty_data) {
+ /* if we received nothing, the server closed the connection and we
+ are done */
+ k->keepon &= ~KEEP_RECV;
+ }
+
+ } while(data_pending(conn));
+
+ if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
+ conn->bits.close ) {
+ /* When we've read the entire thing and the close bit is set, the server
+ may now close the connection. If there's now any kind of sending going
+ on from our side, we need to stop that immediately. */
+ infof(data, "we are done reading and this is set to close, stop send\n");
+ k->keepon &= ~KEEP_SEND; /* no writing anymore either */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Send data to upload to the server, when the socket is writable.
+ */
+static CURLcode readwrite_upload(struct SessionHandle *data,
+ struct connectdata *conn,
+ struct SingleRequest *k,
+ int *didwhat)
+{
+ ssize_t i, si;
+ ssize_t bytes_written;
+ CURLcode result;
+ ssize_t nread; /* number of bytes read */
+ bool sending_http_headers = FALSE;
+
+ if((k->bytecount == 0) && (k->writebytecount == 0))
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+
+ *didwhat |= KEEP_SEND;
+
+ /*
+ * We loop here to do the READ and SEND loop until we run out of
+ * data to send or until we get EWOULDBLOCK back
+ *
+ * FIXME: above comment is misleading. Currently no looping is
+ * actually done in do-while loop below.
+ */
+ do {
+
+ /* only read more data if there's no upload data already
+ present in the upload buffer */
+ if(0 == data->req.upload_present) {
+ /* init the "upload from here" pointer */
+ data->req.upload_fromhere = k->uploadbuf;
+
+ if(!k->upload_done) {
+ /* HTTP pollution, this should be written nicer to become more
+ protocol agnostic. */
+ int fillcount;
+ struct HTTP *http = data->req.protop;
+
+ if((k->exp100 == EXP100_SENDING_REQUEST) &&
+ (http->sending == HTTPSEND_BODY)) {
+ /* If this call is to send body data, we must take some action:
+ We have sent off the full HTTP 1.1 request, and we shall now
+ go into the Expect: 100 state and await such a header */
+ k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */
+ k->keepon &= ~KEEP_SEND; /* disable writing */
+ k->start100 = Curl_tvnow(); /* timeout count starts now */
+ *didwhat &= ~KEEP_SEND; /* we didn't write anything actually */
+
+ /* set a timeout for the multi interface */
+ Curl_expire(data, data->set.expect_100_timeout);
+ break;
+ }
+
+ if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
+ if(http->sending == HTTPSEND_REQUEST)
+ /* We're sending the HTTP request headers, not the data.
+ Remember that so we don't change the line endings. */
+ sending_http_headers = TRUE;
+ else
+ sending_http_headers = FALSE;
+ }
+
+ result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
+ if(result)
+ return result;
+
+ nread = (ssize_t)fillcount;
+ }
+ else
+ nread = 0; /* we're done uploading/reading */
+
+ if(!nread && (k->keepon & KEEP_SEND_PAUSE)) {
+ /* this is a paused transfer */
+ break;
+ }
+ else if(nread<=0) {
+ /* done */
+ k->keepon &= ~KEEP_SEND; /* we're done writing */
+
+ if(conn->bits.rewindaftersend) {
+ result = Curl_readrewind(conn);
+ if(result)
+ return result;
+ }
+ break;
+ }
+
+ /* store number of bytes available for upload */
+ data->req.upload_present = nread;
+
+ /* convert LF to CRLF if so asked */
+ if((!sending_http_headers) && (
+#ifdef CURL_DO_LINEEND_CONV
+ /* always convert if we're FTPing in ASCII mode */
+ (data->set.prefer_ascii) ||
+#endif
+ (data->set.crlf))) {
+ /* Do we need to allocate a scratch buffer? */
+ if(!data->state.scratch) {
+ data->state.scratch = malloc(2 * BUFSIZE);
+ if(!data->state.scratch) {
+ failf(data, "Failed to alloc scratch buffer!");
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /*
+ * ASCII/EBCDIC Note: This is presumably a text (not binary)
+ * transfer so the data should already be in ASCII.
+ * That means the hex values for ASCII CR (0x0d) & LF (0x0a)
+ * must be used instead of the escape sequences \r & \n.
+ */
+ for(i = 0, si = 0; i < nread; i++, si++) {
+ if(data->req.upload_fromhere[i] == 0x0a) {
+ data->state.scratch[si++] = 0x0d;
+ data->state.scratch[si] = 0x0a;
+ if(!data->set.crlf) {
+ /* we're here only because FTP is in ASCII mode...
+ bump infilesize for the LF we just added */
+ data->state.infilesize++;
+ }
+ }
+ else
+ data->state.scratch[si] = data->req.upload_fromhere[i];
+ }
+
+ if(si != nread) {
+ /* only perform the special operation if we really did replace
+ anything */
+ nread = si;
+
+ /* upload from the new (replaced) buffer instead */
+ data->req.upload_fromhere = data->state.scratch;
+
+ /* set the new amount too */
+ data->req.upload_present = nread;
+ }
+ }
+
+#ifndef CURL_DISABLE_SMTP
+ if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
+ result = Curl_smtp_escape_eob(conn, nread);
+ if(result)
+ return result;
+ }
+#endif /* CURL_DISABLE_SMTP */
+ } /* if 0 == data->req.upload_present */
+ else {
+ /* We have a partial buffer left from a previous "round". Use
+ that instead of reading more data */
+ }
+
+ /* write to socket (send away data) */
+ result = Curl_write(conn,
+ conn->writesockfd, /* socket to send to */
+ data->req.upload_fromhere, /* buffer pointer */
+ data->req.upload_present, /* buffer size */
+ &bytes_written); /* actually sent */
+
+ if(result)
+ return result;
+
+ if(data->set.verbose)
+ /* show the data before we change the pointer upload_fromhere */
+ Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere,
+ (size_t)bytes_written, conn);
+
+ k->writebytecount += bytes_written;
+
+ if(k->writebytecount == data->state.infilesize) {
+ /* we have sent all data we were supposed to */
+ k->upload_done = TRUE;
+ infof(data, "We are completely uploaded and fine\n");
+ }
+
+ if(data->req.upload_present != bytes_written) {
+ /* we only wrote a part of the buffer (if anything), deal with it! */
+
+ /* store the amount of bytes left in the buffer to write */
+ data->req.upload_present -= bytes_written;
+
+ /* advance the pointer where to find the buffer when the next send
+ is to happen */
+ data->req.upload_fromhere += bytes_written;
+ }
+ else {
+ /* we've uploaded that buffer now */
+ data->req.upload_fromhere = k->uploadbuf;
+ data->req.upload_present = 0; /* no more bytes left */
+
+ if(k->upload_done) {
+ /* switch off writing, we're done! */
+ k->keepon &= ~KEEP_SEND; /* we're done writing */
+ }
+ }
+
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+
+ } WHILE_FALSE; /* just to break out from! */
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_readwrite() is the low-level function to be called when data is to
+ * be read and written to/from the connection.
+ */
+CURL_STATIC CURLcode Curl_readwrite(struct connectdata *conn,
+ bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+ CURLcode result;
+ int didwhat=0;
+
+ curl_socket_t fd_read;
+ curl_socket_t fd_write;
+ int select_res = conn->cselect_bits;
+
+ conn->cselect_bits = 0;
+
+ /* only use the proper socket if the *_HOLD bit is not set simultaneously as
+ then we are in rate limiting state in that transfer direction */
+
+ if((k->keepon & KEEP_RECVBITS) == KEEP_RECV)
+ fd_read = conn->sockfd;
+ else
+ fd_read = CURL_SOCKET_BAD;
+
+ if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
+ fd_write = conn->writesockfd;
+ else
+ fd_write = CURL_SOCKET_BAD;
+
+ if(!select_res) /* Call for select()/poll() only, if read/write/error
+ status is not known. */
+ select_res = Curl_socket_ready(fd_read, fd_write, 0);
+
+ if(select_res == CURL_CSELECT_ERR) {
+ failf(data, "select/poll returned error");
+ return CURLE_SEND_ERROR;
+ }
+
+ /* We go ahead and do a read if we have a readable socket or if
+ the stream was rewound (in which case we have data in a
+ buffer) */
+ if((k->keepon & KEEP_RECV) &&
+ ((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
+
+ result = readwrite_data(data, conn, k, &didwhat, done);
+ if(result || *done)
+ return result;
+ }
+
+ /* If we still have writing to do, we check if we have a writable socket. */
+ if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
+ /* write */
+
+ result = readwrite_upload(data, conn, k, &didwhat);
+ if(result)
+ return result;
+ }
+
+ k->now = Curl_tvnow();
+ if(didwhat) {
+ /* Update read/write counters */
+ if(k->bytecountp)
+ *k->bytecountp = k->bytecount; /* read count */
+ if(k->writebytecountp)
+ *k->writebytecountp = k->writebytecount; /* write count */
+ }
+ else {
+ /* no read no write, this is a timeout? */
+ if(k->exp100 == EXP100_AWAITING_CONTINUE) {
+ /* This should allow some time for the header to arrive, but only a
+ very short time as otherwise it'll be too much wasted time too
+ often. */
+
+ /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status":
+
+ Therefore, when a client sends this header field to an origin server
+ (possibly via a proxy) from which it has never seen a 100 (Continue)
+ status, the client SHOULD NOT wait for an indefinite period before
+ sending the request body.
+
+ */
+
+ long ms = Curl_tvdiff(k->now, k->start100);
+ if(ms >= data->set.expect_100_timeout) {
+ /* we've waited long enough, continue anyway */
+ k->exp100 = EXP100_SEND_DATA;
+ k->keepon |= KEEP_SEND;
+ infof(data, "Done waiting for 100-continue\n");
+ }
+ }
+ }
+
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(data, k->now);
+ if(result)
+ return result;
+
+ if(k->keepon) {
+ if(0 > Curl_timeleft(data, &k->now, FALSE)) {
+ if(k->size != -1) {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " out of %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount,
+ k->size);
+ }
+ else {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount);
+ }
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ else {
+ /*
+ * The transfer has been performed. Just make some general checks before
+ * returning.
+ */
+
+ if(!(data->set.opt_no_body) && (k->size != -1) &&
+ (k->bytecount != k->size) &&
+#ifdef CURL_DO_LINEEND_CONV
+ /* Most FTP servers don't adjust their file SIZE response for CRLFs,
+ so we'll check to see if the discrepancy can be explained
+ by the number of CRLFs we've changed to LFs.
+ */
+ (k->bytecount != (k->size + data->state.crlf_conversions)) &&
+#endif /* CURL_DO_LINEEND_CONV */
+ !data->req.newurl) {
+ failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
+ " bytes remaining to read",
+ k->size - k->bytecount);
+ return CURLE_PARTIAL_FILE;
+ }
+ else if(!(data->set.opt_no_body) &&
+ k->chunk &&
+ (conn->chunk.state != CHUNK_STOP)) {
+ /*
+ * In chunked mode, return an error if the connection is closed prior to
+ * the empty (terminating) chunk is read.
+ *
+ * The condition above used to check for
+ * conn->proto.http->chunk.datasize != 0 which is true after reading
+ * *any* chunk, not just the empty chunk.
+ *
+ */
+ failf(data, "transfer closed with outstanding read data remaining");
+ return CURLE_PARTIAL_FILE;
+ }
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+
+ /* Now update the "done" boolean we return */
+ *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
+ KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE;
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_single_getsock() gets called by the multi interface code when the app
+ * has requested to get the sockets for the current connection. This function
+ * will then be called once for every connection that the multi interface
+ * keeps track of. This function will only be called for connections that are
+ * in the proper state to have this information available.
+ */
+CURL_STATIC int Curl_single_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks number
+ of sockets */
+ int numsocks)
+{
+ const struct SessionHandle *data = conn->data;
+ int bitmap = GETSOCK_BLANK;
+ unsigned sockindex = 0;
+
+ if(conn->handler->perform_getsock)
+ return conn->handler->perform_getsock(conn, sock, numsocks);
+
+ if(numsocks < 2)
+ /* simple check but we might need two slots */
+ return GETSOCK_BLANK;
+
+ /* don't include HOLD and PAUSE connections */
+ if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
+
+ DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
+
+ bitmap |= GETSOCK_READSOCK(sockindex);
+ sock[sockindex] = conn->sockfd;
+ }
+
+ /* don't include HOLD and PAUSE connections */
+ if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
+
+ if((conn->sockfd != conn->writesockfd) ||
+ bitmap == GETSOCK_BLANK) {
+ /* only if they are not the same socket and we have a readable
+ one, we increase index */
+ if(bitmap != GETSOCK_BLANK)
+ sockindex++; /* increase index if we need two entries */
+
+ DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
+
+ sock[sockindex] = conn->writesockfd;
+ }
+
+ bitmap |= GETSOCK_WRITESOCK(sockindex);
+ }
+
+ return bitmap;
+}
+
+/*
+ * Determine optimum sleep time based on configured rate, current rate,
+ * and packet size.
+ * Returns value in milliseconds.
+ *
+ * The basic idea is to adjust the desired rate up/down in this method
+ * based on whether we are running too slow or too fast. Then, calculate
+ * how many milliseconds to wait for the next packet to achieve this new
+ * rate.
+ */
+CURL_STATIC long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
+ int pkt_size)
+{
+ curl_off_t min_sleep = 0;
+ curl_off_t rv = 0;
+
+ if(rate_bps == 0)
+ return 0;
+
+ /* If running faster than about .1% of the desired speed, slow
+ * us down a bit. Use shift instead of division as the 0.1%
+ * cutoff is arbitrary anyway.
+ */
+ if(cur_rate_bps > (rate_bps + (rate_bps >> 10))) {
+ /* running too fast, decrease target rate by 1/64th of rate */
+ rate_bps -= rate_bps >> 6;
+ min_sleep = 1;
+ }
+ else if(cur_rate_bps < (rate_bps - (rate_bps >> 10))) {
+ /* running too slow, increase target rate by 1/64th of rate */
+ rate_bps += rate_bps >> 6;
+ }
+
+ /* Determine number of milliseconds to wait until we do
+ * the next packet at the adjusted rate. We should wait
+ * longer when using larger packets, for instance.
+ */
+ rv = ((curl_off_t)(pkt_size * 1000) / rate_bps);
+
+ /* Catch rounding errors and always slow down at least 1ms if
+ * we are running too fast.
+ */
+ if(rv < min_sleep)
+ rv = min_sleep;
+
+ /* Bound value to fit in 'long' on 32-bit platform. That's
+ * plenty long enough anyway!
+ */
+ if(rv > 0x7fffffff)
+ rv = 0x7fffffff;
+
+ return (long)rv;
+}
+
+/*
+ * Curl_pretransfer() is called immediately before a transfer starts.
+ */
+CURL_STATIC CURLcode Curl_pretransfer(struct SessionHandle *data)
+{
+ CURLcode result;
+ if(!data->change.url) {
+ /* we can't do anything without URL */
+ failf(data, "No URL set!");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Init the SSL session ID cache here. We do it here since we want to do it
+ after the *_setopt() calls (that could specify the size of the cache) but
+ before any transfer takes place. */
+ result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions);
+ if(result)
+ return result;
+
+ data->set.followlocation=0; /* reset the location-follow counter */
+ data->state.this_is_a_follow = FALSE; /* reset this */
+ data->state.errorbuf = FALSE; /* no error has occurred */
+ data->state.httpversion = 0; /* don't assume any particular server version */
+
+ data->state.authproblem = FALSE;
+ data->state.authhost.want = data->set.httpauth;
+ data->state.authproxy.want = data->set.proxyauth;
+ Curl_safefree(data->info.wouldredirect);
+ data->info.wouldredirect = NULL;
+
+ /* If there is a list of cookie files to read, do it now! */
+ if(data->change.cookielist)
+ Curl_cookie_loadfiles(data);
+
+ /* If there is a list of host pairs to deal with */
+ if(data->change.resolve)
+ result = Curl_loadhostpairs(data);
+
+ if(!result) {
+ /* Allow data->set.use_port to set which port to use. This needs to be
+ * disabled for example when we follow Location: headers to URLs using
+ * different ports! */
+ data->state.allow_port = TRUE;
+
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
+ /*************************************************************
+ * Tell signal handler to ignore SIGPIPE
+ *************************************************************/
+ if(!data->set.no_signal)
+ data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
+#endif
+
+ Curl_initinfo(data); /* reset session-specific information "variables" */
+ Curl_pgrsResetTimesSizes(data);
+ Curl_pgrsStartNow(data);
+
+ if(data->set.timeout)
+ Curl_expire(data, data->set.timeout);
+
+ if(data->set.connecttimeout)
+ Curl_expire(data, data->set.connecttimeout);
+
+ /* In case the handle is re-used and an authentication method was picked
+ in the session we need to make sure we only use the one(s) we now
+ consider to be fine */
+ data->state.authhost.picked &= data->state.authhost.want;
+ data->state.authproxy.picked &= data->state.authproxy.want;
+ }
+
+ return result;
+}
+
+/*
+ * Curl_posttransfer() is called immediately after a transfer ends
+ */
+CURL_STATIC CURLcode Curl_posttransfer(struct SessionHandle *data)
+{
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
+ /* restore the signal handler for SIGPIPE before we get back */
+ if(!data->set.no_signal)
+ signal(SIGPIPE, data->state.prev_signal);
+#else
+ (void)data; /* unused parameter */
+#endif
+
+ return CURLE_OK;
+}
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * strlen_url() returns the length of the given URL if the spaces within the
+ * URL were properly URL encoded.
+ */
+static size_t strlen_url(const char *url)
+{
+ const char *ptr;
+ size_t newlen=0;
+ bool left=TRUE; /* left side of the ? */
+
+ for(ptr=url; *ptr; ptr++) {
+ switch(*ptr) {
+ case '?':
+ left=FALSE;
+ /* fall through */
+ default:
+ newlen++;
+ break;
+ case ' ':
+ if(left)
+ newlen+=3;
+ else
+ newlen++;
+ break;
+ }
+ }
+ return newlen;
+}
+
+/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
+ * the source URL accordingly.
+ */
+static void strcpy_url(char *output, const char *url)
+{
+ /* we must add this with whitespace-replacing */
+ bool left=TRUE;
+ const char *iptr;
+ char *optr = output;
+ for(iptr = url; /* read from here */
+ *iptr; /* until zero byte */
+ iptr++) {
+ switch(*iptr) {
+ case '?':
+ left=FALSE;
+ /* fall through */
+ default:
+ *optr++=*iptr;
+ break;
+ case ' ':
+ if(left) {
+ *optr++='%'; /* add a '%' */
+ *optr++='2'; /* add a '2' */
+ *optr++='0'; /* add a '0' */
+ }
+ else
+ *optr++='+'; /* add a '+' here */
+ break;
+ }
+ }
+ *optr=0; /* zero terminate output buffer */
+
+}
+
+/*
+ * Returns true if the given URL is absolute (as opposed to relative)
+ */
+static bool is_absolute_url(const char *url)
+{
+ char prot[16]; /* URL protocol string storage */
+ char letter; /* used for a silly sscanf */
+
+ return (2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter)) ? TRUE : FALSE;
+}
+
+/*
+ * Concatenate a relative URL to a base URL making it absolute.
+ * URL-encodes any spaces.
+ * The returned pointer must be freed by the caller unless NULL
+ * (returns NULL on out of memory).
+ */
+static char *concat_url(const char *base, const char *relurl)
+{
+ /***
+ TRY to append this new path to the old URL
+ to the right of the host part. Oh crap, this is doomed to cause
+ problems in the future...
+ */
+ char *newest;
+ char *protsep;
+ char *pathsep;
+ size_t newlen;
+
+ const char *useurl = relurl;
+ size_t urllen;
+
+ /* we must make our own copy of the URL to play with, as it may
+ point to read-only data */
+ char *url_clone=strdup(base);
+
+ if(!url_clone)
+ return NULL; /* skip out of this NOW */
+
+ /* protsep points to the start of the host name */
+ protsep=strstr(url_clone, "//");
+ if(!protsep)
+ protsep=url_clone;
+ else
+ protsep+=2; /* pass the slashes */
+
+ if('/' != relurl[0]) {
+ int level=0;
+
+ /* First we need to find out if there's a ?-letter in the URL,
+ and cut it and the right-side of that off */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep=0;
+
+ /* we have a relative path to append to the last slash if there's one
+ available, or if the new URL is just a query string (starts with a
+ '?') we append the new one at the end of the entire currently worked
+ out URL */
+ if(useurl[0] != '?') {
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep=0;
+ }
+
+ /* Check if there's any slash after the host name, and if so, remember
+ that position instead */
+ pathsep = strchr(protsep, '/');
+ if(pathsep)
+ protsep = pathsep+1;
+ else
+ protsep = NULL;
+
+ /* now deal with one "./" or any amount of "../" in the newurl
+ and act accordingly */
+
+ if((useurl[0] == '.') && (useurl[1] == '/'))
+ useurl+=2; /* just skip the "./" */
+
+ while((useurl[0] == '.') &&
+ (useurl[1] == '.') &&
+ (useurl[2] == '/')) {
+ level++;
+ useurl+=3; /* pass the "../" */
+ }
+
+ if(protsep) {
+ while(level--) {
+ /* cut off one more level from the right of the original URL */
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep=0;
+ else {
+ *protsep=0;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* We got a new absolute path for this server */
+
+ if((relurl[0] == '/') && (relurl[1] == '/')) {
+ /* the new URL starts with //, just keep the protocol part from the
+ original one */
+ *protsep=0;
+ useurl = &relurl[2]; /* we keep the slashes from the original, so we
+ skip the new ones */
+ }
+ else {
+ /* cut off the original URL from the first slash, or deal with URLs
+ without slash */
+ pathsep = strchr(protsep, '/');
+ if(pathsep) {
+ /* When people use badly formatted URLs, such as
+ "http://www.url.com?dir=/home/daniel" we must not use the first
+ slash, if there's a ?-letter before it! */
+ char *sep = strchr(protsep, '?');
+ if(sep && (sep < pathsep))
+ pathsep = sep;
+ *pathsep=0;
+ }
+ else {
+ /* There was no slash. Now, since we might be operating on a badly
+ formatted URL, such as "http://www.url.com?id=2380" which doesn't
+ use a slash separator as it is supposed to, we need to check for a
+ ?-letter as well! */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep=0;
+ }
+ }
+ }
+
+ /* If the new part contains a space, this is a mighty stupid redirect
+ but we still make an effort to do "right". To the left of a '?'
+ letter we replace each space with %20 while it is replaced with '+'
+ on the right side of the '?' letter.
+ */
+ newlen = strlen_url(useurl);
+
+ urllen = strlen(url_clone);
+
+ newest = malloc(urllen + 1 + /* possible slash */
+ newlen + 1 /* zero byte */);
+
+ if(!newest) {
+ free(url_clone); /* don't leak this */
+ return NULL;
+ }
+
+ /* copy over the root url part */
+ memcpy(newest, url_clone, urllen);
+
+ /* check if we need to append a slash */
+ if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
+ ;
+ else
+ newest[urllen++]='/';
+
+ /* then append the new piece on the right side */
+ strcpy_url(&newest[urllen], useurl);
+
+ free(url_clone);
+
+ return newest;
+}
+#endif /* CURL_DISABLE_HTTP */
+
+/*
+ * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
+ * as given by the remote server and set up the new URL to request.
+ */
+CURLcode Curl_follow(struct SessionHandle *data,
+ char *newurl, /* this 'newurl' is the Location: string,
+ and it must be malloc()ed before passed
+ here */
+ followtype type) /* see transfer.h */
+{
+#ifdef CURL_DISABLE_HTTP
+ (void)data;
+ (void)newurl;
+ (void)type;
+ /* Location: following will not happen when HTTP is disabled */
+ return CURLE_TOO_MANY_REDIRECTS;
+#else
+
+ /* Location: redirect */
+ bool disallowport = FALSE;
+
+ if(type == FOLLOW_REDIR) {
+ if((data->set.maxredirs != -1) &&
+ (data->set.followlocation >= data->set.maxredirs)) {
+ failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
+ return CURLE_TOO_MANY_REDIRECTS;
+ }
+
+ /* mark the next request as a followed location: */
+ data->state.this_is_a_follow = TRUE;
+
+ data->set.followlocation++; /* count location-followers */
+
+ if(data->set.http_auto_referer) {
+ /* We are asked to automatically set the previous URL as the referer
+ when we get the next URL. We pick the ->url field, which may or may
+ not be 100% correct */
+
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+
+ data->change.referer = strdup(data->change.url);
+ if(!data->change.referer)
+ return CURLE_OUT_OF_MEMORY;
+ data->change.referer_alloc = TRUE; /* yes, free this later */
+ }
+ }
+
+ if(!is_absolute_url(newurl)) {
+ /***
+ *DANG* this is an RFC 2068 violation. The URL is supposed
+ to be absolute and this doesn't seem to be that!
+ */
+ char *absolute = concat_url(data->change.url, newurl);
+ if(!absolute)
+ return CURLE_OUT_OF_MEMORY;
+ free(newurl);
+ newurl = absolute;
+ }
+ else {
+ /* This is an absolute URL, don't allow the custom port number */
+ disallowport = TRUE;
+
+ if(strchr(newurl, ' ')) {
+ /* This new URL contains at least one space, this is a mighty stupid
+ redirect but we still make an effort to do "right". */
+ char *newest;
+ size_t newlen = strlen_url(newurl);
+
+ newest = malloc(newlen+1); /* get memory for this */
+ if(!newest)
+ return CURLE_OUT_OF_MEMORY;
+ strcpy_url(newest, newurl); /* create a space-free URL */
+
+ free(newurl); /* that was no good */
+ newurl = newest; /* use this instead now */
+ }
+
+ }
+
+ if(type == FOLLOW_FAKE) {
+ /* we're only figuring out the new url if we would've followed locations
+ but now we're done so we can get out! */
+ data->info.wouldredirect = newurl;
+ return CURLE_OK;
+ }
+
+ if(disallowport)
+ data->state.allow_port = FALSE;
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ data->change.url = newurl;
+ data->change.url_alloc = TRUE;
+ newurl = NULL; /* don't free! */
+
+ infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
+
+ /*
+ * We get here when the HTTP code is 300-399 (and 401). We need to perform
+ * differently based on exactly what return code there was.
+ *
+ * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
+ * a HTTP (proxy-) authentication scheme other than Basic.
+ */
+ switch(data->info.httpcode) {
+ /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
+ Authorization: XXXX header in the HTTP request code snippet */
+ /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
+ Proxy-Authorization: XXXX header in the HTTP request code snippet */
+ /* 300 - Multiple Choices */
+ /* 306 - Not used */
+ /* 307 - Temporary Redirect */
+ default: /* for all above (and the unknown ones) */
+ /* Some codes are explicitly mentioned since I've checked RFC2616 and they
+ * seem to be OK to POST to.
+ */
+ break;
+ case 301: /* Moved Permanently */
+ /* (quote from RFC7231, section 6.4.2)
+ *
+ * Note: For historical reasons, a user agent MAY change the request
+ * method from POST to GET for the subsequent request. If this
+ * behavior is undesired, the 307 (Temporary Redirect) status code
+ * can be used instead.
+ *
+ * ----
+ *
+ * Many webservers expect this, so these servers often answers to a POST
+ * request with an error page. To be sure that libcurl gets the page that
+ * most user agents would get, libcurl has to force GET.
+ *
+ * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * can be overridden with CURLOPT_POSTREDIR.
+ */
+ if((data->set.httpreq == HTTPREQ_POST
+ || data->set.httpreq == HTTPREQ_POST_FORM)
+ && !(data->set.keep_post & CURL_REDIR_POST_301)) {
+ infof(data, "Switch from POST to GET\n");
+ data->set.httpreq = HTTPREQ_GET;
+ }
+ break;
+ case 302: /* Found */
+ /* (quote from RFC7231, section 6.4.3)
+ *
+ * Note: For historical reasons, a user agent MAY change the request
+ * method from POST to GET for the subsequent request. If this
+ * behavior is undesired, the 307 (Temporary Redirect) status code
+ * can be used instead.
+ *
+ * ----
+ *
+ * Many webservers expect this, so these servers often answers to a POST
+ * request with an error page. To be sure that libcurl gets the page that
+ * most user agents would get, libcurl has to force GET.
+ *
+ * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * can be overridden with CURLOPT_POSTREDIR.
+ */
+ if((data->set.httpreq == HTTPREQ_POST
+ || data->set.httpreq == HTTPREQ_POST_FORM)
+ && !(data->set.keep_post & CURL_REDIR_POST_302)) {
+ infof(data, "Switch from POST to GET\n");
+ data->set.httpreq = HTTPREQ_GET;
+ }
+ break;
+
+ case 303: /* See Other */
+ /* Disable both types of POSTs, unless the user explicitely
+ asks for POST after POST */
+ if(data->set.httpreq != HTTPREQ_GET
+ && !(data->set.keep_post & CURL_REDIR_POST_303)) {
+ data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
+ infof(data, "Disables POST, goes with %s\n",
+ data->set.opt_no_body?"HEAD":"GET");
+ }
+ break;
+ case 304: /* Not Modified */
+ /* 304 means we did a conditional request and it was "Not modified".
+ * We shouldn't get any Location: header in this response!
+ */
+ break;
+ case 305: /* Use Proxy */
+ /* (quote from RFC2616, section 10.3.6):
+ * "The requested resource MUST be accessed through the proxy given
+ * by the Location field. The Location field gives the URI of the
+ * proxy. The recipient is expected to repeat this single request
+ * via the proxy. 305 responses MUST only be generated by origin
+ * servers."
+ */
+ break;
+ }
+ Curl_pgrsTime(data, TIMER_REDIRECT);
+ Curl_pgrsResetTimesSizes(data);
+
+ return CURLE_OK;
+#endif /* CURL_DISABLE_HTTP */
+}
+
+CURL_STATIC CURLcode
+Curl_reconnect_request(struct connectdata **connp)
+{
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = *connp;
+ struct SessionHandle *data = conn->data;
+
+ /* This was a re-use of a connection and we got a write error in the
+ * DO-phase. Then we DISCONNECT this connection and have another attempt to
+ * CONNECT and then DO again! The retry cannot possibly find another
+ * connection to re-use, since we only keep one possible connection for
+ * each. */
+
+ infof(data, "Re-used connection seems dead, get a new one\n");
+
+ connclose(conn, "Reconnect dead connection"); /* enforce close */
+ result = Curl_done(&conn, result, FALSE); /* we are so done with this */
+
+ /* conn may no longer be a good pointer, clear it to avoid mistakes by
+ parent functions */
+ *connp = NULL;
+
+ /*
+ * According to bug report #1330310. We need to check for CURLE_SEND_ERROR
+ * here as well. I figure this could happen when the request failed on a FTP
+ * connection and thus Curl_done() itself tried to use the connection
+ * (again). Slight Lack of feedback in the report, but I don't think this
+ * extra check can do much harm.
+ */
+ if(!result || (CURLE_SEND_ERROR == result)) {
+ bool async;
+ bool protocol_done = TRUE;
+
+ /* Now, redo the connect and get a new connection */
+ result = Curl_connect(data, connp, &async, &protocol_done);
+ if(!result) {
+ /* We have connected or sent away a name resolve query fine */
+
+ conn = *connp; /* setup conn to again point to something nice */
+ if(async) {
+ /* Now, if async is TRUE here, we need to wait for the name
+ to resolve */
+ result = Curl_resolver_wait_resolv(conn, NULL);
+ if(result)
+ return result;
+
+ /* Resolved, continue with the connection */
+ result = Curl_async_resolved(conn, &protocol_done);
+ if(result)
+ return result;
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
+
+ NOTE: that the *url is malloc()ed. */
+CURL_STATIC CURLcode Curl_retry_request(struct connectdata *conn,
+ char **url)
+{
+ struct SessionHandle *data = conn->data;
+
+ *url = NULL;
+
+ /* if we're talking upload, we can't do the checks below, unless the protocol
+ is HTTP as when uploading over HTTP we will still get a response */
+ if(data->set.upload &&
+ !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
+ return CURLE_OK;
+
+ if((data->req.bytecount + data->req.headerbytecount == 0) &&
+ conn->bits.reuse &&
+ !data->set.opt_no_body &&
+ (data->set.rtspreq != RTSPREQ_RECEIVE)) {
+ /* We got no data, we attempted to re-use a connection and yet we want a
+ "body". This might happen if the connection was left alive when we were
+ done using it before, but that was closed when we wanted to read from
+ it again. Bad luck. Retry the same request on a fresh connect! */
+ infof(conn->data, "Connection died, retrying a fresh connect\n");
+ *url = strdup(conn->data->change.url);
+ if(!*url)
+ return CURLE_OUT_OF_MEMORY;
+
+ connclose(conn, "retry"); /* close this connection */
+ conn->bits.retry = TRUE; /* mark this as a connection we're about
+ to retry. Marking it this way should
+ prevent i.e HTTP transfers to return
+ error just because nothing has been
+ transferred! */
+
+
+ if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
+ struct HTTP *http = data->req.protop;
+ if(http->writebytecount)
+ return Curl_readrewind(conn);
+ }
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Curl_setup_transfer() is called to setup some basic properties for the
+ * upcoming transfer.
+ */
+CURL_STATIC void
+Curl_setup_transfer(
+ struct connectdata *conn, /* connection data */
+ int sockindex, /* socket index to read from or -1 */
+ curl_off_t size, /* -1 if unknown at this point */
+ bool getheader, /* TRUE if header parsing is wanted */
+ curl_off_t *bytecountp, /* return number of bytes read or NULL */
+ int writesockindex, /* socket index to write to, it may very well be
+ the same we read from. -1 disables */
+ curl_off_t *writecountp /* return number of bytes written or NULL */
+ )
+{
+ struct SessionHandle *data;
+ struct SingleRequest *k;
+
+ DEBUGASSERT(conn != NULL);
+
+ data = conn->data;
+ k = &data->req;
+
+ DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
+
+ /* now copy all input parameters */
+ conn->sockfd = sockindex == -1 ?
+ CURL_SOCKET_BAD : conn->sock[sockindex];
+ conn->writesockfd = writesockindex == -1 ?
+ CURL_SOCKET_BAD:conn->sock[writesockindex];
+ k->getheader = getheader;
+
+ k->size = size;
+ k->bytecountp = bytecountp;
+ k->writebytecountp = writecountp;
+
+ /* The code sequence below is placed in this function just because all
+ necessary input is not always known in do_complete() as this function may
+ be called after that */
+
+ if(!k->getheader) {
+ k->header = FALSE;
+ if(size > 0)
+ Curl_pgrsSetDownloadSize(data, size);
+ }
+ /* we want header and/or body, if neither then don't do this! */
+ if(k->getheader || !data->set.opt_no_body) {
+
+ if(conn->sockfd != CURL_SOCKET_BAD)
+ k->keepon |= KEEP_RECV;
+
+ if(conn->writesockfd != CURL_SOCKET_BAD) {
+ struct HTTP *http = data->req.protop;
+ /* HTTP 1.1 magic:
+
+ Even if we require a 100-return code before uploading data, we might
+ need to write data before that since the REQUEST may not have been
+ finished sent off just yet.
+
+ Thus, we must check if the request has been sent before we set the
+ state info where we wait for the 100-return code
+ */
+ if((data->state.expect100header) &&
+ (conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ (http->sending == HTTPSEND_BODY)) {
+ /* wait with write until we either got 100-continue or a timeout */
+ k->exp100 = EXP100_AWAITING_CONTINUE;
+ k->start100 = Curl_tvnow();
+
+ /* Set a timeout for the multi interface. Add the inaccuracy margin so
+ that we don't fire slightly too early and get denied to run. */
+ Curl_expire(data, data->set.expect_100_timeout);
+ }
+ else {
+ if(data->state.expect100header)
+ /* when we've sent off the rest of the headers, we must await a
+ 100-continue but first finish sending the request */
+ k->exp100 = EXP100_SENDING_REQUEST;
+
+ /* enable the write bit when we're not waiting for continue */
+ k->keepon |= KEEP_SEND;
+ }
+ } /* if(conn->writesockfd != CURL_SOCKET_BAD) */
+ } /* if(k->getheader || !data->set.opt_no_body) */
+
+}
diff --git a/libcurl/src/lib/transfer.h b/libcurl/src/lib/transfer.h
new file mode 100644
index 0000000..6b0d9f9
--- /dev/null
+++ b/libcurl/src/lib/transfer.h
@@ -0,0 +1,70 @@
+#ifndef HEADER_CURL_TRANSFER_H
+#define HEADER_CURL_TRANSFER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+CURL_STATIC CURLcode Curl_pretransfer(struct SessionHandle *data);
+CURL_STATIC CURLcode Curl_second_connect(struct connectdata *conn);
+CURL_STATIC CURLcode Curl_posttransfer(struct SessionHandle *data);
+
+typedef enum {
+ FOLLOW_NONE, /* not used within the function, just a placeholder to
+ allow initing to this */
+ FOLLOW_FAKE, /* only records stuff, not actually following */
+ FOLLOW_RETRY, /* set if this is a request retry as opposed to a real
+ redirect following */
+ FOLLOW_REDIR, /* a full true redirect */
+ FOLLOW_LAST /* never used */
+} followtype;
+
+CURL_STATIC CURLcode Curl_follow(struct SessionHandle *data, char *newurl,
+ followtype type);
+
+
+CURL_STATIC CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
+CURL_STATIC int Curl_single_getsock(const struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+CURL_STATIC CURLcode Curl_readrewind(struct connectdata *conn);
+CURL_STATIC CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
+CURL_STATIC CURLcode Curl_reconnect_request(struct connectdata **connp);
+CURL_STATIC CURLcode Curl_retry_request(struct connectdata *conn, char **url);
+CURL_STATIC bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc);
+
+/* This sets up a forthcoming transfer */
+CURL_STATIC void
+Curl_setup_transfer (struct connectdata *data,
+ int sockindex, /* socket index to read from or -1 */
+ curl_off_t size, /* -1 if unknown at this point */
+ bool getheader, /* TRUE if header parsing is wanted */
+ curl_off_t *bytecountp, /* return number of bytes read */
+ int writesockindex, /* socket index to write to, it may
+ very well be the same we read from.
+ -1 disables */
+ curl_off_t *writecountp /* return number of bytes written */
+);
+
+CURL_STATIC long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
+ int pkt_size);
+
+#endif /* HEADER_CURL_TRANSFER_H */
+
diff --git a/libcurl/src/lib/url.c b/libcurl/src/lib/url.c
new file mode 100644
index 0000000..9c3c59c
--- /dev/null
+++ b/libcurl/src/lib/url.c
@@ -0,0 +1,6164 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
+#ifndef HAVE_SOCKET
+#error "We can't compile without socket() support!"
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifdef USE_LIBIDN
+#include <idna.h>
+#include <tld.h>
+#include <stringprep.h>
+#ifdef HAVE_IDN_FREE_H
+#include <idn-free.h>
+#else
+/* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */
+void idn_free (void *ptr);
+#endif
+#ifndef HAVE_IDN_FREE
+/* if idn_free() was not found in this version of libidn use free() instead */
+#define idn_free(x) (free)(x)
+#endif
+#elif defined(USE_WIN32_IDN)
+/* prototype for curl_win32_idn_to_ascii() */
+int curl_win32_idn_to_ascii(const char *in, char **out);
+#endif /* USE_LIBIDN */
+
+#include "urldata.h"
+#include "netrc.h"
+
+#include "formdata.h"
+#include "vtls/vtls.h"
+#include "hostip.h"
+#include "transfer.h"
+#include "sendf.h"
+#include "progress.h"
+#include "cookie.h"
+#include "strequal.h"
+#include "strerror.h"
+#include "escape.h"
+#include "strtok.h"
+#include "share.h"
+#include "content_encoding.h"
+#include "http_digest.h"
+#include "http_negotiate.h"
+#include "select.h"
+#include "multiif.h"
+#include "easyif.h"
+#include "speedcheck.h"
+#include "rawstr.h"
+#include "warnless.h"
+#include "non-ascii.h"
+#include "inet_pton.h"
+
+/* And now for the protocols */
+#include "ftp.h"
+#include "dict.h"
+#include "telnet.h"
+#include "tftp.h"
+#include "http.h"
+#include "file.h"
+#include "curl_ldap.h"
+#include "ssh.h"
+#include "imap.h"
+#include "url.h"
+#include "connect.h"
+#include "inet_ntop.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_wb.h"
+#include "socks.h"
+#include "curl_rtmp.h"
+#include "gopher.h"
+#include "http_proxy.h"
+#include "bundles.h"
+#include "conncache.h"
+#include "multihandle.h"
+#include "pipeline.h"
+#include "dotdot.h"
+#include "strdup.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local static prototypes */
+static struct connectdata *
+find_oldest_idle_connection(struct SessionHandle *data);
+static struct connectdata *
+find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
+ struct connectbundle *bundle);
+static void conn_free(struct connectdata *conn);
+static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
+static CURLcode do_init(struct connectdata *conn);
+static CURLcode parse_url_login(struct SessionHandle *data,
+ struct connectdata *conn,
+ char **userptr, char **passwdptr,
+ char **optionsptr);
+static CURLcode parse_login_details(const char *login, const size_t len,
+ char **userptr, char **passwdptr,
+ char **optionsptr);
+/*
+ * Protocol table.
+ */
+
+static const struct Curl_handler * const protocols[] = {
+
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_http,
+#endif
+
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_https,
+#endif
+
+#ifndef CURL_DISABLE_FTP
+ &Curl_handler_ftp,
+#endif
+
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+ &Curl_handler_ftps,
+#endif
+
+#ifndef CURL_DISABLE_TELNET
+ &Curl_handler_telnet,
+#endif
+
+#ifndef CURL_DISABLE_DICT
+ &Curl_handler_dict,
+#endif
+
+#ifndef CURL_DISABLE_LDAP
+ &Curl_handler_ldap,
+#if !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+ &Curl_handler_ldaps,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_FILE
+ &Curl_handler_file,
+#endif
+
+#ifndef CURL_DISABLE_TFTP
+ &Curl_handler_tftp,
+#endif
+
+#ifdef USE_LIBSSH2
+ &Curl_handler_scp,
+ &Curl_handler_sftp,
+#endif
+
+#ifndef CURL_DISABLE_IMAP
+ &Curl_handler_imap,
+#ifdef USE_SSL
+ &Curl_handler_imaps,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_POP3
+ &Curl_handler_pop3,
+#ifdef USE_SSL
+ &Curl_handler_pop3s,
+#endif
+#endif
+
+#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4) && \
+ (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
+ &Curl_handler_smb,
+#ifdef USE_SSL
+ &Curl_handler_smbs,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_SMTP
+ &Curl_handler_smtp,
+#ifdef USE_SSL
+ &Curl_handler_smtps,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_RTSP
+ &Curl_handler_rtsp,
+#endif
+
+#ifndef CURL_DISABLE_GOPHER
+ &Curl_handler_gopher,
+#endif
+
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmp,
+ &Curl_handler_rtmpt,
+ &Curl_handler_rtmpe,
+ &Curl_handler_rtmpte,
+ &Curl_handler_rtmps,
+ &Curl_handler_rtmpts,
+#endif
+
+ (struct Curl_handler *) NULL
+};
+
+/*
+ * Dummy handler for undefined protocol schemes.
+ */
+
+static const struct Curl_handler Curl_handler_dummy = {
+ "<no protocol>", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ ZERO_NULL, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ 0, /* defport */
+ 0, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+CURL_STATIC void Curl_freeset(struct SessionHandle *data)
+{
+ /* Free all dynamic strings stored in the data->set substructure. */
+ enum dupstring i;
+ for(i=(enum dupstring)0; i < STRING_LAST; i++) {
+ Curl_safefree(data->set.str[i]);
+ }
+
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ data->change.referer = NULL;
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ data->change.url = NULL;
+}
+
+static CURLcode setstropt(char **charp, char *s)
+{
+ /* Release the previous storage at `charp' and replace by a dynamic storage
+ copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
+
+ Curl_safefree(*charp);
+
+ if(s) {
+ s = strdup(s);
+
+ if(!s)
+ return CURLE_OUT_OF_MEMORY;
+
+ *charp = s;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
+{
+ CURLcode result = CURLE_OK;
+ char *user = NULL;
+ char *passwd = NULL;
+
+ /* Parse the login details if specified. It not then we treat NULL as a hint
+ to clear the existing data */
+ if(option) {
+ result = parse_login_details(option, strlen(option),
+ (userp ? &user : NULL),
+ (passwdp ? &passwd : NULL),
+ NULL);
+ }
+
+ if(!result) {
+ /* Store the username part of option if required */
+ if(userp) {
+ if(!user && option && option[0] == ':') {
+ /* Allocate an empty string instead of returning NULL as user name */
+ user = strdup("");
+ if(!user)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_safefree(*userp);
+ *userp = user;
+ }
+
+ /* Store the password part of option if required */
+ if(passwdp) {
+ Curl_safefree(*passwdp);
+ *passwdp = passwd;
+ }
+ }
+
+ return result;
+}
+
+CURL_STATIC CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src)
+{
+ CURLcode result = CURLE_OK;
+ enum dupstring i;
+
+ /* Copy src->set into dst->set first, then deal with the strings
+ afterwards */
+ dst->set = src->set;
+
+ /* clear all string pointers first */
+ memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
+
+ /* duplicate all strings */
+ for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
+ result = setstropt(&dst->set.str[i], src->set.str[i]);
+ if(result)
+ return result;
+ }
+
+ /* duplicate memory areas pointed to */
+ i = STRING_COPYPOSTFIELDS;
+ if(src->set.postfieldsize && src->set.str[i]) {
+ /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
+ dst->set.str[i] = Curl_memdup(src->set.str[i],
+ curlx_sotouz(src->set.postfieldsize));
+ if(!dst->set.str[i])
+ return CURLE_OUT_OF_MEMORY;
+ /* point to the new copy */
+ dst->set.postfields = dst->set.str[i];
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * This is the internal function curl_easy_cleanup() calls. This should
+ * cleanup and free all resources associated with this sessionhandle.
+ *
+ * NOTE: if we ever add something that attempts to write to a socket or
+ * similar here, we must ignore SIGPIPE first. It is currently only done
+ * when curl_easy_perform() is invoked.
+ */
+
+CURL_STATIC CURLcode Curl_close(struct SessionHandle *data)
+{
+ struct Curl_multi *m;
+
+ if(!data)
+ return CURLE_OK;
+
+ Curl_expire(data, 0); /* shut off timers */
+
+ m = data->multi;
+
+ if(m)
+ /* This handle is still part of a multi handle, take care of this first
+ and detach this handle from there. */
+ curl_multi_remove_handle(data->multi, data);
+
+ if(data->multi_easy)
+ /* when curl_easy_perform() is used, it creates its own multi handle to
+ use and this is the one */
+ curl_multi_cleanup(data->multi_easy);
+
+ /* Destroy the timeout list that is held in the easy handle. It is
+ /normally/ done by curl_multi_remove_handle() but this is "just in
+ case" */
+ if(data->state.timeoutlist) {
+ Curl_llist_destroy(data->state.timeoutlist, NULL);
+ data->state.timeoutlist = NULL;
+ }
+
+ data->magic = 0; /* force a clear AFTER the possibly enforced removal from
+ the multi handle, since that function uses the magic
+ field! */
+
+ if(data->state.rangestringalloc)
+ free(data->state.range);
+
+ /* Free the pathbuffer */
+ Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+
+ /* freed here just in case DONE wasn't called */
+ Curl_free_request_state(data);
+
+ /* Close down all open SSL info and sessions */
+ Curl_ssl_close_all(data);
+ Curl_safefree(data->state.first_host);
+ Curl_safefree(data->state.scratch);
+ Curl_ssl_free_certinfo(data);
+
+ /* Cleanup possible redirect junk */
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ data->change.referer = NULL;
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ data->change.url = NULL;
+
+ Curl_safefree(data->state.headerbuff);
+
+ Curl_flush_cookies(data, 1);
+
+ Curl_digest_cleanup(data);
+
+ Curl_safefree(data->info.contenttype);
+ Curl_safefree(data->info.wouldredirect);
+
+ /* this destroys the channel and we cannot use it anymore after this */
+ Curl_resolver_cleanup(data->state.resolver);
+
+ Curl_convert_close(data);
+
+ /* No longer a dirty share, if it exists */
+ if(data->share) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+ data->share->dirty--;
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+ }
+
+ Curl_freeset(data);
+ free(data);
+ return CURLE_OK;
+}
+
+/*
+ * Initialize the UserDefined fields within a SessionHandle.
+ * This may be safely called on a new or existing SessionHandle.
+ */
+CURL_STATIC CURLcode Curl_init_userdefined(struct UserDefined *set)
+{
+ CURLcode result = CURLE_OK;
+
+ set->out = stdout; /* default output to stdout */
+ set->in = stdin; /* default input from stdin */
+ set->err = stderr; /* default stderr to stderr */
+
+ /* use fwrite as default function to store output */
+ set->fwrite_func = (curl_write_callback)fwrite;
+
+ /* use fread as default function to read input */
+ set->fread_func = (curl_read_callback)fread;
+ set->is_fread_set = 0;
+ set->is_fwrite_set = 0;
+
+ set->seek_func = ZERO_NULL;
+ set->seek_client = ZERO_NULL;
+
+ /* conversion callbacks for non-ASCII hosts */
+ set->convfromnetwork = ZERO_NULL;
+ set->convtonetwork = ZERO_NULL;
+ set->convfromutf8 = ZERO_NULL;
+
+ set->filesize = -1; /* we don't know the size */
+ set->postfieldsize = -1; /* unknown size */
+ set->maxredirs = -1; /* allow any amount by default */
+
+ set->httpreq = HTTPREQ_GET; /* Default HTTP request */
+ set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
+ set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
+ set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
+ set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
+ set->ftp_filemethod = FTPFILE_MULTICWD;
+
+ set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
+
+ /* Set the default size of the SSL session ID cache */
+ set->ssl.max_ssl_sessions = 5;
+
+ set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
+ set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
+ set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
+ set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
+
+ /* make libcurl quiet by default: */
+ set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
+
+ /*
+ * libcurl 7.10 introduced SSL verification *by default*! This needs to be
+ * switched off unless wanted.
+ */
+ set->ssl.verifypeer = TRUE;
+ set->ssl.verifyhost = TRUE;
+#ifdef USE_TLS_SRP
+ set->ssl.authtype = CURL_TLSAUTH_NONE;
+#endif
+ set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
+ type */
+ set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
+
+ set->new_file_perms = 0644; /* Default permissions */
+ set->new_directory_perms = 0755; /* Default permissions */
+
+ /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
+ define since we internally only use the lower 16 bits for the passed
+ in bitmask to not conflict with the private bits */
+ set->allowed_protocols = CURLPROTO_ALL;
+ set->redir_protocols = CURLPROTO_ALL & /* All except FILE, SCP and SMB */
+ ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
+ CURLPROTO_SMBS);
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ /*
+ * disallow unprotected protection negotiation NEC reference implementation
+ * seem not to follow rfc1961 section 4.3/4.4
+ */
+ set->socks5_gssapi_nec = FALSE;
+ /* set default GSS-API service name */
+ result = setstropt(&set->str[STRING_SOCKS5_GSSAPI_SERVICE],
+ (char *) CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE);
+ if(result)
+ return result;
+#endif
+
+ /* This is our preferred CA cert bundle/path since install time */
+#if defined(CURL_CA_BUNDLE)
+ result = setstropt(&set->str[STRING_SSL_CAFILE], (char *) CURL_CA_BUNDLE);
+ if(result)
+ return result;
+#endif
+#if defined(CURL_CA_PATH)
+ result = setstropt(&set->str[STRING_SSL_CAPATH], (char *) CURL_CA_PATH);
+ if(result)
+ return result;
+#endif
+
+ set->wildcardmatch = FALSE;
+ set->chunk_bgn = ZERO_NULL;
+ set->chunk_end = ZERO_NULL;
+
+ /* tcp keepalives are disabled by default, but provide reasonable values for
+ * the interval and idle times.
+ */
+ set->tcp_keepalive = FALSE;
+ set->tcp_keepintvl = 60;
+ set->tcp_keepidle = 60;
+
+ set->ssl_enable_npn = TRUE;
+ set->ssl_enable_alpn = TRUE;
+
+ set->expect_100_timeout = 1000L; /* Wait for a second by default. */
+ set->sep_headers = TRUE; /* separated header lists by default */
+ return result;
+}
+
+/**
+ * Curl_open()
+ *
+ * @param curl is a pointer to a sessionhandle pointer that gets set by this
+ * function.
+ * @return CURLcode
+ */
+
+CURL_STATIC CURLcode Curl_open(struct SessionHandle **curl)
+{
+ CURLcode result;
+ struct SessionHandle *data;
+
+ /* Very simple start-up: alloc the struct, init it with zeroes and return */
+ data = calloc(1, sizeof(struct SessionHandle));
+ if(!data) {
+ /* this is a very serious error */
+ DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n"));
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ data->magic = CURLEASY_MAGIC_NUMBER;
+
+ result = Curl_resolver_init(&data->state.resolver);
+ if(result) {
+ DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
+ free(data);
+ return result;
+ }
+
+ /* We do some initial setup here, all those fields that can't be just 0 */
+
+ data->state.headerbuff = malloc(HEADERSIZE);
+ if(!data->state.headerbuff) {
+ DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ result = Curl_init_userdefined(&data->set);
+
+ data->state.headersize=HEADERSIZE;
+
+ Curl_convert_init(data);
+
+ /* most recent connection is not yet defined */
+ data->state.lastconnect = NULL;
+
+ data->progress.flags |= PGRS_HIDE;
+ data->state.current_speed = -1; /* init to negative == impossible */
+
+ data->wildcard.state = CURLWC_INIT;
+ data->wildcard.filelist = NULL;
+ data->set.fnmatch = ZERO_NULL;
+ data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
+ }
+
+ if(result) {
+ Curl_resolver_cleanup(data->state.resolver);
+ free(data->state.headerbuff);
+ Curl_freeset(data);
+ free(data);
+ data = NULL;
+ }
+ else
+ *curl = data;
+
+ return result;
+}
+
+CURL_STATIC CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
+ va_list param)
+{
+ char *argptr;
+ CURLcode result = CURLE_OK;
+ long arg;
+#ifndef CURL_DISABLE_HTTP
+ curl_off_t bigsize;
+#endif
+
+ switch(option) {
+ case CURLOPT_DNS_CACHE_TIMEOUT:
+ data->set.dns_cache_timeout = va_arg(param, long);
+ break;
+ case CURLOPT_DNS_USE_GLOBAL_CACHE:
+ /* remember we want this enabled */
+ arg = va_arg(param, long);
+ data->set.global_dns_cache = (0 != arg)?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_CIPHER_LIST:
+ /* set a list of cipher we want to use in the SSL connection */
+ result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RANDOM_FILE:
+ /*
+ * This is the path name to a file that contains random data to seed
+ * the random SSL stuff with. The file is only used for reading.
+ */
+ result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_EGDSOCKET:
+ /*
+ * The Entropy Gathering Daemon socket pathname
+ */
+ result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_MAXCONNECTS:
+ /*
+ * Set the absolute number of maximum simultaneous alive connection that
+ * libcurl is allowed to have.
+ */
+ data->set.maxconnects = va_arg(param, long);
+ break;
+ case CURLOPT_FORBID_REUSE:
+ /*
+ * When this transfer is done, it must not be left to be reused by a
+ * subsequent transfer but shall be closed immediately.
+ */
+ data->set.reuse_forbid = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FRESH_CONNECT:
+ /*
+ * This transfer shall not use a previously cached connection but
+ * should be made with a fresh new connect!
+ */
+ data->set.reuse_fresh = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_VERBOSE:
+ /*
+ * Verbose means infof() calls that give a lot of information about
+ * the connection and transfer procedures as well as internal choices.
+ */
+ data->set.verbose = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_HEADER:
+ /*
+ * Set to include the header in the general data output stream.
+ */
+ data->set.include_header = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_NOPROGRESS:
+ /*
+ * Shut off the internal supported progress meter
+ */
+ data->set.hide_progress = (0 != va_arg(param, long))?TRUE:FALSE;
+ if(data->set.hide_progress)
+ data->progress.flags |= PGRS_HIDE;
+ else
+ data->progress.flags &= ~PGRS_HIDE;
+ break;
+ case CURLOPT_NOBODY:
+ /*
+ * Do not include the body part in the output data stream.
+ */
+ data->set.opt_no_body = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FAILONERROR:
+ /*
+ * Don't output the >=400 error code HTML-page, but instead only
+ * return error.
+ */
+ data->set.http_fail_on_error = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_UPLOAD:
+ case CURLOPT_PUT:
+ /*
+ * We want to sent data to the remote host. If this is HTTP, that equals
+ * using the PUT request.
+ */
+ data->set.upload = (0 != va_arg(param, long))?TRUE:FALSE;
+ if(data->set.upload) {
+ /* If this is HTTP, PUT is what's needed to "upload" */
+ data->set.httpreq = HTTPREQ_PUT;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
+ then this can be changed to HEAD later on) */
+ data->set.httpreq = HTTPREQ_GET;
+ break;
+ case CURLOPT_FILETIME:
+ /*
+ * Try to get the file time of the remote document. The time will
+ * later (possibly) become available using curl_easy_getinfo().
+ */
+ data->set.get_filetime = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FTP_CREATE_MISSING_DIRS:
+ /*
+ * An FTP option that modifies an upload to create missing directories on
+ * the server.
+ */
+ switch(va_arg(param, long)) {
+ case 0:
+ data->set.ftp_create_missing_dirs = 0;
+ break;
+ case 1:
+ data->set.ftp_create_missing_dirs = 1;
+ break;
+ case 2:
+ data->set.ftp_create_missing_dirs = 2;
+ break;
+ default:
+ /* reserve other values for future use */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+ break;
+ case CURLOPT_SERVER_RESPONSE_TIMEOUT:
+ /*
+ * Option that specifies how quickly an server response must be obtained
+ * before it is considered failure. For pingpong protocols.
+ */
+ data->set.server_response_timeout = va_arg( param , long ) * 1000;
+ break;
+ case CURLOPT_TFTP_BLKSIZE:
+ /*
+ * TFTP option that specifies the block size to use for data transmission
+ */
+ data->set.tftp_blksize = va_arg(param, long);
+ break;
+ case CURLOPT_DIRLISTONLY:
+ /*
+ * An option that changes the command to one that asks for a list
+ * only, no file info details.
+ */
+ data->set.ftp_list_only = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_APPEND:
+ /*
+ * We want to upload and append to an existing file.
+ */
+ data->set.ftp_append = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FTP_FILEMETHOD:
+ /*
+ * How do access files over FTP.
+ */
+ data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
+ break;
+ case CURLOPT_NETRC:
+ /*
+ * Parse the $HOME/.netrc file
+ */
+ data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
+ break;
+ case CURLOPT_NETRC_FILE:
+ /*
+ * Use this file instead of the $HOME/.netrc file
+ */
+ result = setstropt(&data->set.str[STRING_NETRC_FILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_TRANSFERTEXT:
+ /*
+ * This option was previously named 'FTPASCII'. Renamed to work with
+ * more protocols than merely FTP.
+ *
+ * Transfer using ASCII (instead of BINARY).
+ */
+ data->set.prefer_ascii = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_TIMECONDITION:
+ /*
+ * Set HTTP time condition. This must be one of the defines in the
+ * curl/curl.h header file.
+ */
+ data->set.timecondition = (curl_TimeCond)va_arg(param, long);
+ break;
+ case CURLOPT_TIMEVALUE:
+ /*
+ * This is the value to compare with the remote document with the
+ * method set with CURLOPT_TIMECONDITION
+ */
+ data->set.timevalue = (time_t)va_arg(param, long);
+ break;
+ case CURLOPT_SSLVERSION:
+ /*
+ * Set explicit SSL version to try to connect with, as some SSL
+ * implementations are lame.
+ */
+#ifdef USE_SSL
+ data->set.ssl.version = va_arg(param, long);
+#else
+ result = CURLE_UNKNOWN_OPTION;
+#endif
+ break;
+
+#ifndef CURL_DISABLE_HTTP
+ case CURLOPT_AUTOREFERER:
+ /*
+ * Switch on automatic referer that gets set if curl follows locations.
+ */
+ data->set.http_auto_referer = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_ACCEPT_ENCODING:
+ /*
+ * String to use at the value of Accept-Encoding header.
+ *
+ * If the encoding is set to "" we use an Accept-Encoding header that
+ * encompasses all the encodings we support.
+ * If the encoding is set to NULL we don't send an Accept-Encoding header
+ * and ignore an received Content-Encoding header.
+ *
+ */
+ argptr = va_arg(param, char *);
+ result = setstropt(&data->set.str[STRING_ENCODING],
+ (argptr && !*argptr)?
+ (char *) ALL_CONTENT_ENCODINGS: argptr);
+ break;
+
+ case CURLOPT_TRANSFER_ENCODING:
+ data->set.http_transfer_encoding = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FOLLOWLOCATION:
+ /*
+ * Follow Location: header hints on a HTTP-server.
+ */
+ data->set.http_follow_location = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_UNRESTRICTED_AUTH:
+ /*
+ * Send authentication (user+password) when following locations, even when
+ * hostname changed.
+ */
+ data->set.http_disable_hostname_check_before_authentication =
+ (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_MAXREDIRS:
+ /*
+ * The maximum amount of hops you allow curl to follow Location:
+ * headers. This should mostly be used to detect never-ending loops.
+ */
+ data->set.maxredirs = va_arg(param, long);
+ break;
+
+ case CURLOPT_POSTREDIR:
+ {
+ /*
+ * Set the behaviour of POST when redirecting
+ * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
+ * CURL_REDIR_POST_301 - POST is kept as POST after 301
+ * CURL_REDIR_POST_302 - POST is kept as POST after 302
+ * CURL_REDIR_POST_303 - POST is kept as POST after 303
+ * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
+ * other - POST is kept as POST after 301 and 302
+ */
+ int postRedir = curlx_sltosi(va_arg(param, long));
+ data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
+ }
+ break;
+
+ case CURLOPT_POST:
+ /* Does this option serve a purpose anymore? Yes it does, when
+ CURLOPT_POSTFIELDS isn't used and the POST data is read off the
+ callback! */
+ if(va_arg(param, long)) {
+ data->set.httpreq = HTTPREQ_POST;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ data->set.httpreq = HTTPREQ_GET;
+ break;
+
+ case CURLOPT_COPYPOSTFIELDS:
+ /*
+ * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
+ * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
+ * CURLOPT_COPYPOSTFIELDS and not altered later.
+ */
+ argptr = va_arg(param, char *);
+
+ if(!argptr || data->set.postfieldsize == -1)
+ result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
+ else {
+ /*
+ * Check that requested length does not overflow the size_t type.
+ */
+
+ if((data->set.postfieldsize < 0) ||
+ ((sizeof(curl_off_t) != sizeof(size_t)) &&
+ (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ char * p;
+
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+
+ /* Allocate even when size == 0. This satisfies the need of possible
+ later address compare to detect the COPYPOSTFIELDS mode, and
+ to mark that postfields is used rather than read function or
+ form data.
+ */
+ p = malloc((size_t)(data->set.postfieldsize?
+ data->set.postfieldsize:1));
+
+ if(!p)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ if(data->set.postfieldsize)
+ memcpy(p, argptr, (size_t)data->set.postfieldsize);
+
+ data->set.str[STRING_COPYPOSTFIELDS] = p;
+ }
+ }
+ }
+
+ data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
+ data->set.httpreq = HTTPREQ_POST;
+ break;
+
+ case CURLOPT_POSTFIELDS:
+ /*
+ * Like above, but use static data instead of copying it.
+ */
+ data->set.postfields = va_arg(param, void *);
+ /* Release old copied data. */
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.httpreq = HTTPREQ_POST;
+ break;
+
+ case CURLOPT_POSTFIELDSIZE:
+ /*
+ * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+ * figure it out. Enables binary posts.
+ */
+ bigsize = va_arg(param, long);
+
+ if(data->set.postfieldsize < bigsize &&
+ data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+ /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.postfields = NULL;
+ }
+
+ data->set.postfieldsize = bigsize;
+ break;
+
+ case CURLOPT_POSTFIELDSIZE_LARGE:
+ /*
+ * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+ * figure it out. Enables binary posts.
+ */
+ bigsize = va_arg(param, curl_off_t);
+
+ if(data->set.postfieldsize < bigsize &&
+ data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+ /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.postfields = NULL;
+ }
+
+ data->set.postfieldsize = bigsize;
+ break;
+
+ case CURLOPT_HTTPPOST:
+ /*
+ * Set to make us do HTTP POST
+ */
+ data->set.httppost = va_arg(param, struct curl_httppost *);
+ data->set.httpreq = HTTPREQ_POST_FORM;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ break;
+
+ case CURLOPT_REFERER:
+ /*
+ * String to set in the HTTP Referer: field.
+ */
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ result = setstropt(&data->set.str[STRING_SET_REFERER],
+ va_arg(param, char *));
+ data->change.referer = data->set.str[STRING_SET_REFERER];
+ break;
+
+ case CURLOPT_USERAGENT:
+ /*
+ * String to use in the HTTP User-Agent field
+ */
+ result = setstropt(&data->set.str[STRING_USERAGENT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_HTTPHEADER:
+ /*
+ * Set a list with HTTP headers to use (or replace internals with)
+ */
+ data->set.headers = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_PROXYHEADER:
+ /*
+ * Set a list with proxy headers to use (or replace internals with)
+ *
+ * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
+ * long time we remain doing it this way until CURLOPT_PROXYHEADER is
+ * used. As soon as this option has been used, if set to anything but
+ * NULL, custom headers for proxies are only picked from this list.
+ *
+ * Set this option to NULL to restore the previous behavior.
+ */
+ data->set.proxyheaders = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_HEADEROPT:
+ /*
+ * Set header option.
+ */
+ arg = va_arg(param, long);
+ data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
+ break;
+
+ case CURLOPT_HTTP200ALIASES:
+ /*
+ * Set a list of aliases for HTTP 200 in response header
+ */
+ data->set.http200aliases = va_arg(param, struct curl_slist *);
+ break;
+
+#if !defined(CURL_DISABLE_COOKIES)
+ case CURLOPT_COOKIE:
+ /*
+ * Cookie string to send to the remote server in the request.
+ */
+ result = setstropt(&data->set.str[STRING_COOKIE],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_COOKIEFILE:
+ /*
+ * Set cookie file to read and parse. Can be used multiple times.
+ */
+ argptr = (char *)va_arg(param, void *);
+ if(argptr) {
+ struct curl_slist *cl;
+ /* append the cookie file name to the list of file names, and deal with
+ them later */
+ cl = curl_slist_append(data->change.cookielist, argptr);
+ if(!cl) {
+ curl_slist_free_all(data->change.cookielist);
+ data->change.cookielist = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->change.cookielist = cl; /* store the list for later use */
+ }
+ break;
+
+ case CURLOPT_COOKIEJAR:
+ /*
+ * Set cookie file name to dump all cookies to when we're done.
+ */
+ {
+ struct CookieInfo *newcookies;
+ result = setstropt(&data->set.str[STRING_COOKIEJAR],
+ va_arg(param, char *));
+
+ /*
+ * Activate the cookie parser. This may or may not already
+ * have been made.
+ */
+ newcookies = Curl_cookie_init(data, NULL, data->cookies,
+ data->set.cookiesession);
+ if(!newcookies)
+ result = CURLE_OUT_OF_MEMORY;
+ data->cookies = newcookies;
+ }
+ break;
+
+ case CURLOPT_COOKIESESSION:
+ /*
+ * Set this option to TRUE to start a new "cookie session". It will
+ * prevent the forthcoming read-cookies-from-file actions to accept
+ * cookies that are marked as being session cookies, as they belong to a
+ * previous session.
+ *
+ * In the original Netscape cookie spec, "session cookies" are cookies
+ * with no expire date set. RFC2109 describes the same action if no
+ * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
+ * a 'Discard' action that can enforce the discard even for cookies that
+ * have a Max-Age.
+ *
+ * We run mostly with the original cookie spec, as hardly anyone implements
+ * anything else.
+ */
+ data->set.cookiesession = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_COOKIELIST:
+ argptr = va_arg(param, char *);
+
+ if(argptr == NULL)
+ break;
+
+ if(Curl_raw_equal(argptr, "ALL")) {
+ /* clear all cookies */
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_clearall(data->cookies);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ else if(Curl_raw_equal(argptr, "SESS")) {
+ /* clear session cookies */
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_clearsess(data->cookies);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ else if(Curl_raw_equal(argptr, "FLUSH")) {
+ /* flush cookies to file, takes care of the locking */
+ Curl_flush_cookies(data, 0);
+ }
+ else if(Curl_raw_equal(argptr, "RELOAD")) {
+ /* reload cookies from file */
+ Curl_cookie_loadfiles(data);
+ break;
+ }
+ else {
+ if(!data->cookies)
+ /* if cookie engine was not running, activate it */
+ data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
+
+ argptr = strdup(argptr);
+ if(!argptr || !data->cookies) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(argptr);
+ }
+ else {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+
+ if(checkprefix("Set-Cookie:", argptr))
+ /* HTTP Header format line */
+ Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
+
+ else
+ /* Netscape format line */
+ Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ free(argptr);
+ }
+ }
+
+ break;
+#endif /* CURL_DISABLE_COOKIES */
+
+ case CURLOPT_HTTPGET:
+ /*
+ * Set to force us do HTTP GET
+ */
+ if(va_arg(param, long)) {
+ data->set.httpreq = HTTPREQ_GET;
+ data->set.upload = FALSE; /* switch off upload */
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ break;
+
+ case CURLOPT_HTTP_VERSION:
+ /*
+ * This sets a requested HTTP version to be used. The value is one of
+ * the listed enums in curl/curl.h.
+ */
+ arg = va_arg(param, long);
+#ifndef USE_NGHTTP2
+ if(arg == CURL_HTTP_VERSION_2_0)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ data->set.httpversion = arg;
+ break;
+
+ case CURLOPT_HTTPAUTH:
+ /*
+ * Set HTTP Authentication type BITMASK.
+ */
+ {
+ int bitcheck;
+ bool authbits;
+ unsigned long auth = va_arg(param, unsigned long);
+
+ if(auth == CURLAUTH_NONE) {
+ data->set.httpauth = auth;
+ break;
+ }
+
+ /* the DIGEST_IE bit is only used to set a special marker, for all the
+ rest we need to handle it as normal DIGEST */
+ data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
+
+ if(auth & CURLAUTH_DIGEST_IE) {
+ auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+ auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+ }
+
+ /* switch off bits we can't support */
+#ifndef USE_NTLM
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+ auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+ GSS-API or SSPI */
+#endif
+
+ /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+ bitcheck = 0;
+ authbits = FALSE;
+ while(bitcheck < 31) {
+ if(auth & (1UL << bitcheck++)) {
+ authbits = TRUE;
+ break;
+ }
+ }
+ if(!authbits)
+ return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+ data->set.httpauth = auth;
+ }
+ break;
+
+ case CURLOPT_EXPECT_100_TIMEOUT_MS:
+ /*
+ * Time to wait for a response to a HTTP request containing an
+ * Expect: 100-continue header before sending the data anyway.
+ */
+ data->set.expect_100_timeout = va_arg(param, long);
+ break;
+
+#endif /* CURL_DISABLE_HTTP */
+
+ case CURLOPT_CUSTOMREQUEST:
+ /*
+ * Set a custom string to use as request
+ */
+ result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
+ va_arg(param, char *));
+
+ /* we don't set
+ data->set.httpreq = HTTPREQ_CUSTOM;
+ here, we continue as if we were using the already set type
+ and this just changes the actual request keyword */
+ break;
+
+#ifndef CURL_DISABLE_PROXY
+ case CURLOPT_HTTPPROXYTUNNEL:
+ /*
+ * Tunnel operations through the proxy instead of normal proxy use
+ */
+ data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_PROXYPORT:
+ /*
+ * Explicitly set HTTP proxy port number.
+ */
+ data->set.proxyport = va_arg(param, long);
+ break;
+
+ case CURLOPT_PROXYAUTH:
+ /*
+ * Set HTTP Authentication type BITMASK.
+ */
+ {
+ int bitcheck;
+ bool authbits;
+ unsigned long auth = va_arg(param, unsigned long);
+
+ if(auth == CURLAUTH_NONE) {
+ data->set.proxyauth = auth;
+ break;
+ }
+
+ /* the DIGEST_IE bit is only used to set a special marker, for all the
+ rest we need to handle it as normal DIGEST */
+ data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
+
+ if(auth & CURLAUTH_DIGEST_IE) {
+ auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+ auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+ }
+ /* switch off bits we can't support */
+#ifndef USE_NTLM
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+ auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+ GSS-API or SSPI */
+#endif
+
+ /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+ bitcheck = 0;
+ authbits = FALSE;
+ while(bitcheck < 31) {
+ if(auth & (1UL << bitcheck++)) {
+ authbits = TRUE;
+ break;
+ }
+ }
+ if(!authbits)
+ return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+ data->set.proxyauth = auth;
+ }
+ break;
+
+ case CURLOPT_PROXY:
+ /*
+ * Set proxy server:port to use as HTTP proxy.
+ *
+ * If the proxy is set to "" we explicitly say that we don't want to use a
+ * proxy (even though there might be environment variables saying so).
+ *
+ * Setting it to NULL, means no proxy but allows the environment variables
+ * to decide for us.
+ */
+ result = setstropt(&data->set.str[STRING_PROXY],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_PROXYTYPE:
+ /*
+ * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
+ */
+ data->set.proxytype = (curl_proxytype)va_arg(param, long);
+ break;
+
+ case CURLOPT_PROXY_TRANSFER_MODE:
+ /*
+ * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
+ */
+ switch (va_arg(param, long)) {
+ case 0:
+ data->set.proxy_transfer_mode = FALSE;
+ break;
+ case 1:
+ data->set.proxy_transfer_mode = TRUE;
+ break;
+ default:
+ /* reserve other values for future use */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+ break;
+#endif /* CURL_DISABLE_PROXY */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ case CURLOPT_SOCKS5_GSSAPI_SERVICE:
+ /*
+ * Set GSS-API service name
+ */
+ result = setstropt(&data->set.str[STRING_SOCKS5_GSSAPI_SERVICE],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SOCKS5_GSSAPI_NEC:
+ /*
+ * set flag for nec socks5 support
+ */
+ data->set.socks5_gssapi_nec = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+#endif
+
+ case CURLOPT_HEADERDATA:
+ /*
+ * Custom pointer to pass the header write callback function
+ */
+ data->set.writeheader = (void *)va_arg(param, void *);
+ break;
+ case CURLOPT_ERRORBUFFER:
+ /*
+ * Error buffer provided by the caller to get the human readable
+ * error string in.
+ */
+ data->set.errorbuffer = va_arg(param, char *);
+ break;
+ case CURLOPT_WRITEDATA:
+ /*
+ * FILE pointer to write to. Or possibly
+ * used as argument to the write callback.
+ */
+ data->set.out = va_arg(param, void *);
+ break;
+ case CURLOPT_FTPPORT:
+ /*
+ * Use FTP PORT, this also specifies which IP address to use
+ */
+ result = setstropt(&data->set.str[STRING_FTPPORT],
+ va_arg(param, char *));
+ data->set.ftp_use_port = (NULL != data->set.str[STRING_FTPPORT]) ?
+ TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_EPRT:
+ data->set.ftp_use_eprt = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_EPSV:
+ data->set.ftp_use_epsv = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_PRET:
+ data->set.ftp_use_pret = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_SSL_CCC:
+ data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
+ break;
+
+ case CURLOPT_FTP_SKIP_PASV_IP:
+ /*
+ * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
+ * bypass of the IP address in PASV responses.
+ */
+ data->set.ftp_skip_ip = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_READDATA:
+ /*
+ * FILE pointer to read the file to be uploaded from. Or possibly
+ * used as argument to the read callback.
+ */
+ data->set.in = va_arg(param, void *);
+ break;
+ case CURLOPT_INFILESIZE:
+ /*
+ * If known, this should inform curl about the file size of the
+ * to-be-uploaded file.
+ */
+ data->set.filesize = va_arg(param, long);
+ break;
+ case CURLOPT_INFILESIZE_LARGE:
+ /*
+ * If known, this should inform curl about the file size of the
+ * to-be-uploaded file.
+ */
+ data->set.filesize = va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_LOW_SPEED_LIMIT:
+ /*
+ * The low speed limit that if transfers are below this for
+ * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
+ */
+ data->set.low_speed_limit=va_arg(param, long);
+ break;
+ case CURLOPT_MAX_SEND_SPEED_LARGE:
+ /*
+ * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
+ * bytes per second the transfer is throttled..
+ */
+ data->set.max_send_speed=va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_MAX_RECV_SPEED_LARGE:
+ /*
+ * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
+ * second the transfer is throttled..
+ */
+ data->set.max_recv_speed=va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_LOW_SPEED_TIME:
+ /*
+ * The low speed time that if transfers are below the set
+ * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
+ */
+ data->set.low_speed_time=va_arg(param, long);
+ break;
+ case CURLOPT_URL:
+ /*
+ * The URL to fetch.
+ */
+ if(data->change.url_alloc) {
+ /* the already set URL is allocated, free it first! */
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ result = setstropt(&data->set.str[STRING_SET_URL],
+ va_arg(param, char *));
+ data->change.url = data->set.str[STRING_SET_URL];
+ break;
+ case CURLOPT_PORT:
+ /*
+ * The port number to use when getting the URL
+ */
+ data->set.use_port = va_arg(param, long);
+ break;
+ case CURLOPT_TIMEOUT:
+ /*
+ * The maximum time you allow curl to use for a single transfer
+ * operation.
+ */
+ data->set.timeout = va_arg(param, long) * 1000L;
+ break;
+
+ case CURLOPT_TIMEOUT_MS:
+ data->set.timeout = va_arg(param, long);
+ break;
+
+ case CURLOPT_CONNECTTIMEOUT:
+ /*
+ * The maximum time you allow curl to use to connect.
+ */
+ data->set.connecttimeout = va_arg(param, long) * 1000L;
+ break;
+
+ case CURLOPT_CONNECTTIMEOUT_MS:
+ data->set.connecttimeout = va_arg(param, long);
+ break;
+
+ case CURLOPT_ACCEPTTIMEOUT_MS:
+ /*
+ * The maximum time you allow curl to wait for server connect
+ */
+ data->set.accepttimeout = va_arg(param, long);
+ break;
+
+ case CURLOPT_USERPWD:
+ /*
+ * user:password to use in the operation
+ */
+ result = setstropt_userpwd(va_arg(param, char *),
+ &data->set.str[STRING_USERNAME],
+ &data->set.str[STRING_PASSWORD]);
+ break;
+
+ case CURLOPT_USERNAME:
+ /*
+ * authentication user name to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_USERNAME],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_PASSWORD:
+ /*
+ * authentication password to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_PASSWORD],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_LOGIN_OPTIONS:
+ /*
+ * authentication options to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_OPTIONS],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_XOAUTH2_BEARER:
+ /*
+ * XOAUTH2 bearer token to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_BEARER],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_POSTQUOTE:
+ /*
+ * List of RAW FTP commands to use after a transfer
+ */
+ data->set.postquote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_PREQUOTE:
+ /*
+ * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
+ */
+ data->set.prequote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_QUOTE:
+ /*
+ * List of RAW FTP commands to use before a transfer
+ */
+ data->set.quote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_RESOLVE:
+ /*
+ * List of NAME:[address] names to populate the DNS cache with
+ * Prefix the NAME with dash (-) to _remove_ the name from the cache.
+ *
+ * Names added with this API will remain in the cache until explicitly
+ * removed or the handle is cleaned up.
+ *
+ * This API can remove any name from the DNS cache, but only entries
+ * that aren't actually in use right now will be pruned immediately.
+ */
+ data->set.resolve = va_arg(param, struct curl_slist *);
+ data->change.resolve = data->set.resolve;
+ break;
+ case CURLOPT_PROGRESSFUNCTION:
+ /*
+ * Progress callback function
+ */
+ data->set.fprogress = va_arg(param, curl_progress_callback);
+ if(data->set.fprogress)
+ data->progress.callback = TRUE; /* no longer internal */
+ else
+ data->progress.callback = FALSE; /* NULL enforces internal */
+ break;
+
+ case CURLOPT_XFERINFOFUNCTION:
+ /*
+ * Transfer info callback function
+ */
+ data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
+ if(data->set.fxferinfo)
+ data->progress.callback = TRUE; /* no longer internal */
+ else
+ data->progress.callback = FALSE; /* NULL enforces internal */
+
+ break;
+
+ case CURLOPT_PROGRESSDATA:
+ /*
+ * Custom client data to pass to the progress callback
+ */
+ data->set.progress_client = va_arg(param, void *);
+ break;
+
+#ifndef CURL_DISABLE_PROXY
+ case CURLOPT_PROXYUSERPWD:
+ /*
+ * user:password needed to use the proxy
+ */
+ result = setstropt_userpwd(va_arg(param, char *),
+ &data->set.str[STRING_PROXYUSERNAME],
+ &data->set.str[STRING_PROXYPASSWORD]);
+ break;
+ case CURLOPT_PROXYUSERNAME:
+ /*
+ * authentication user name to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXYPASSWORD:
+ /*
+ * authentication password to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_NOPROXY:
+ /*
+ * proxy exception list
+ */
+ result = setstropt(&data->set.str[STRING_NOPROXY],
+ va_arg(param, char *));
+ break;
+#endif
+
+ case CURLOPT_RANGE:
+ /*
+ * What range of the file you want to transfer
+ */
+ result = setstropt(&data->set.str[STRING_SET_RANGE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_RESUME_FROM:
+ /*
+ * Resume transfer at the give file position
+ */
+ data->set.set_resume_from = va_arg(param, long);
+ break;
+ case CURLOPT_RESUME_FROM_LARGE:
+ /*
+ * Resume transfer at the give file position
+ */
+ data->set.set_resume_from = va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_DEBUGFUNCTION:
+ /*
+ * stderr write callback.
+ */
+ data->set.fdebug = va_arg(param, curl_debug_callback);
+ /*
+ * if the callback provided is NULL, it'll use the default callback
+ */
+ break;
+ case CURLOPT_DEBUGDATA:
+ /*
+ * Set to a void * that should receive all error writes. This
+ * defaults to CURLOPT_STDERR for normal operations.
+ */
+ data->set.debugdata = va_arg(param, void *);
+ break;
+ case CURLOPT_STDERR:
+ /*
+ * Set to a FILE * that should receive all error writes. This
+ * defaults to stderr for normal operations.
+ */
+ data->set.err = va_arg(param, FILE *);
+ if(!data->set.err)
+ data->set.err = stderr;
+ break;
+ case CURLOPT_HEADERFUNCTION:
+ /*
+ * Set header write callback
+ */
+ data->set.fwrite_header = va_arg(param, curl_write_callback);
+ break;
+ case CURLOPT_WRITEFUNCTION:
+ /*
+ * Set data write callback
+ */
+ data->set.fwrite_func = va_arg(param, curl_write_callback);
+ if(!data->set.fwrite_func) {
+ data->set.is_fwrite_set = 0;
+ /* When set to NULL, reset to our internal default function */
+ data->set.fwrite_func = (curl_write_callback)fwrite;
+ }
+ else
+ data->set.is_fwrite_set = 1;
+ break;
+ case CURLOPT_READFUNCTION:
+ /*
+ * Read data callback
+ */
+ data->set.fread_func = va_arg(param, curl_read_callback);
+ if(!data->set.fread_func) {
+ data->set.is_fread_set = 0;
+ /* When set to NULL, reset to our internal default function */
+ data->set.fread_func = (curl_read_callback)fread;
+ }
+ else
+ data->set.is_fread_set = 1;
+ break;
+ case CURLOPT_SEEKFUNCTION:
+ /*
+ * Seek callback. Might be NULL.
+ */
+ data->set.seek_func = va_arg(param, curl_seek_callback);
+ break;
+ case CURLOPT_SEEKDATA:
+ /*
+ * Seek control callback. Might be NULL.
+ */
+ data->set.seek_client = va_arg(param, void *);
+ break;
+ case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
+ /*
+ * "Convert from network encoding" callback
+ */
+ data->set.convfromnetwork = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_CONV_TO_NETWORK_FUNCTION:
+ /*
+ * "Convert to network encoding" callback
+ */
+ data->set.convtonetwork = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_CONV_FROM_UTF8_FUNCTION:
+ /*
+ * "Convert from UTF-8 encoding" callback
+ */
+ data->set.convfromutf8 = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_IOCTLFUNCTION:
+ /*
+ * I/O control callback. Might be NULL.
+ */
+ data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
+ break;
+ case CURLOPT_IOCTLDATA:
+ /*
+ * I/O control data pointer. Might be NULL.
+ */
+ data->set.ioctl_client = va_arg(param, void *);
+ break;
+ case CURLOPT_SSLCERT:
+ /*
+ * String that holds file name of the SSL certificate to use
+ */
+ result = setstropt(&data->set.str[STRING_CERT],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLCERTTYPE:
+ /*
+ * String that holds file type of the SSL certificate to use
+ */
+ result = setstropt(&data->set.str[STRING_CERT_TYPE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLKEY:
+ /*
+ * String that holds file name of the SSL key to use
+ */
+ result = setstropt(&data->set.str[STRING_KEY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLKEYTYPE:
+ /*
+ * String that holds file type of the SSL key to use
+ */
+ result = setstropt(&data->set.str[STRING_KEY_TYPE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_KEYPASSWD:
+ /*
+ * String that holds the SSL or SSH private key password.
+ */
+ result = setstropt(&data->set.str[STRING_KEY_PASSWD],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLENGINE:
+ /*
+ * String that holds the SSL crypto engine.
+ */
+ argptr = va_arg(param, char *);
+ if(argptr && argptr[0])
+ result = Curl_ssl_set_engine(data, argptr);
+ break;
+
+ case CURLOPT_SSLENGINE_DEFAULT:
+ /*
+ * flag to set engine as default.
+ */
+ result = Curl_ssl_set_engine_default(data);
+ break;
+ case CURLOPT_CRLF:
+ /*
+ * Kludgy option to enable CRLF conversions. Subject for removal.
+ */
+ data->set.crlf = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_INTERFACE:
+ /*
+ * Set what interface or address/hostname to bind the socket to when
+ * performing an operation and thus what from-IP your connection will use.
+ */
+ result = setstropt(&data->set.str[STRING_DEVICE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_LOCALPORT:
+ /*
+ * Set what local port to bind the socket to when performing an operation.
+ */
+ data->set.localport = curlx_sltous(va_arg(param, long));
+ break;
+ case CURLOPT_LOCALPORTRANGE:
+ /*
+ * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
+ */
+ data->set.localportrange = curlx_sltosi(va_arg(param, long));
+ break;
+ case CURLOPT_KRBLEVEL:
+ /*
+ * A string that defines the kerberos security level.
+ */
+ result = setstropt(&data->set.str[STRING_KRB_LEVEL],
+ va_arg(param, char *));
+ data->set.krb = (NULL != data->set.str[STRING_KRB_LEVEL])?TRUE:FALSE;
+ break;
+ case CURLOPT_GSSAPI_DELEGATION:
+ /*
+ * GSS-API credential delegation
+ */
+ data->set.gssapi_delegation = va_arg(param, long);
+ break;
+ case CURLOPT_SSL_VERIFYPEER:
+ /*
+ * Enable peer SSL verifying.
+ */
+ data->set.ssl.verifypeer = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_VERIFYHOST:
+ /*
+ * Enable verification of the host name in the peer certificate
+ */
+ arg = va_arg(param, long);
+
+ /* Obviously people are not reading documentation and too many thought
+ this argument took a boolean when it wasn't and misused it. We thus ban
+ 1 as a sensible input and we warn about its use. Then we only have the
+ 2 action internally stored as TRUE. */
+
+ if(1 == arg) {
+ failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ data->set.ssl.verifyhost = (0 != arg)?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_VERIFYSTATUS:
+ /*
+ * Enable certificate status verifying.
+ */
+ if(!Curl_ssl_cert_status_request()) {
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ }
+
+ data->set.ssl.verifystatus = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_CTX_FUNCTION:
+#ifdef have_curlssl_ssl_ctx
+ /*
+ * Set a SSL_CTX callback
+ */
+ data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
+#else
+ result = CURLE_NOT_BUILT_IN;
+#endif
+ break;
+ case CURLOPT_SSL_CTX_DATA:
+#ifdef have_curlssl_ssl_ctx
+ /*
+ * Set a SSL_CTX callback parameter pointer
+ */
+ data->set.ssl.fsslctxp = va_arg(param, void *);
+#else
+ result = CURLE_NOT_BUILT_IN;
+#endif
+ break;
+ case CURLOPT_SSL_FALSESTART:
+ /*
+ * Enable TLS false start.
+ */
+ if(!Curl_ssl_false_start()) {
+ result = CURLE_NOT_BUILT_IN;
+ break;
+ }
+
+ data->set.ssl.falsestart = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_CERTINFO:
+#ifdef have_curlssl_certinfo
+ data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
+#else
+ result = CURLE_NOT_BUILT_IN;
+#endif
+ break;
+ case CURLOPT_PINNEDPUBLICKEY:
+ /*
+ * Set pinned public key for SSL connection.
+ * Specify file name of the public key in DER format.
+ */
+ result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_CAINFO:
+ /*
+ * Set CA info for SSL connection. Specify file name of the CA certificate
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CAFILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_CAPATH:
+#ifdef have_curlssl_ca_path /* not supported by all backends */
+ /*
+ * Set CA path info for SSL connection. Specify directory name of the CA
+ * certificates which have been prepared using openssl c_rehash utility.
+ */
+ /* This does not work on windows. */
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH],
+ va_arg(param, char *));
+#else
+ result = CURLE_NOT_BUILT_IN;
+#endif
+ break;
+ case CURLOPT_CRLFILE:
+ /*
+ * Set CRL file info for SSL connection. Specify file name of the CRL
+ * to check certificates revocation
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_ISSUERCERT:
+ /*
+ * Set Issuer certificate file
+ * to check certificates issuer
+ */
+ result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_TELNETOPTIONS:
+ /*
+ * Set a linked list of telnet options
+ */
+ data->set.telnet_options = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_BUFFERSIZE:
+ /*
+ * The application kindly asks for a differently sized receive buffer.
+ * If it seems reasonable, we'll use it.
+ */
+ data->set.buffer_size = va_arg(param, long);
+
+ if((data->set.buffer_size> (BUFSIZE -1 )) ||
+ (data->set.buffer_size < 1))
+ data->set.buffer_size = 0; /* huge internal default */
+
+ break;
+
+ case CURLOPT_NOSIGNAL:
+ /*
+ * The application asks not to set any signal() or alarm() handlers,
+ * even when using a timeout.
+ */
+ data->set.no_signal = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_SHARE:
+ {
+ struct Curl_share *set;
+ set = va_arg(param, struct Curl_share *);
+
+ /* disconnect from old share, if any */
+ if(data->share) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+ if(data->dns.hostcachetype == HCACHE_SHARED) {
+ data->dns.hostcache = NULL;
+ data->dns.hostcachetype = HCACHE_NONE;
+ }
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(data->share->cookies == data->cookies)
+ data->cookies = NULL;
+#endif
+
+ if(data->share->sslsession == data->state.session)
+ data->state.session = NULL;
+
+ data->share->dirty--;
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+ data->share = NULL;
+ }
+
+ /* use new share if it set */
+ data->share = set;
+ if(data->share) {
+
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+ data->share->dirty++;
+
+ if(data->share->hostcache) {
+ /* use shared host cache */
+ data->dns.hostcache = data->share->hostcache;
+ data->dns.hostcachetype = HCACHE_SHARED;
+ }
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(data->share->cookies) {
+ /* use shared cookie list, first free own one if any */
+ Curl_cookie_cleanup(data->cookies);
+ /* enable cookies since we now use a share that uses cookies! */
+ data->cookies = data->share->cookies;
+ }
+#endif /* CURL_DISABLE_HTTP */
+ if(data->share->sslsession) {
+ data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+ data->state.session = data->share->sslsession;
+ }
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+
+ }
+ /* check for host cache not needed,
+ * it will be done by curl_easy_perform */
+ }
+ break;
+
+ case CURLOPT_PRIVATE:
+ /*
+ * Set private data pointer.
+ */
+ data->set.private_data = va_arg(param, void *);
+ break;
+
+ case CURLOPT_MAXFILESIZE:
+ /*
+ * Set the maximum size of a file to download.
+ */
+ data->set.max_filesize = va_arg(param, long);
+ break;
+
+#ifdef USE_SSL
+ case CURLOPT_USE_SSL:
+ /*
+ * Make transfers attempt to use SSL/TLS.
+ */
+ data->set.use_ssl = (curl_usessl)va_arg(param, long);
+ break;
+
+ case CURLOPT_SSL_OPTIONS:
+ arg = va_arg(param, long);
+ data->set.ssl_enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ break;
+
+#endif
+ case CURLOPT_FTPSSLAUTH:
+ /*
+ * Set a specific auth for FTP-SSL transfers.
+ */
+ data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
+ break;
+
+ case CURLOPT_IPRESOLVE:
+ data->set.ipver = va_arg(param, long);
+ break;
+
+ case CURLOPT_MAXFILESIZE_LARGE:
+ /*
+ * Set the maximum size of a file to download.
+ */
+ data->set.max_filesize = va_arg(param, curl_off_t);
+ break;
+
+ case CURLOPT_TCP_NODELAY:
+ /*
+ * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
+ * algorithm
+ */
+ data->set.tcp_nodelay = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_ACCOUNT:
+ result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_IGNORE_CONTENT_LENGTH:
+ data->set.ignorecl = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_CONNECT_ONLY:
+ /*
+ * No data transfer, set up connection and let application use the socket
+ */
+ data->set.connect_only = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_ALTERNATIVE_TO_USER:
+ result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SOCKOPTFUNCTION:
+ /*
+ * socket callback function: called after socket() but before connect()
+ */
+ data->set.fsockopt = va_arg(param, curl_sockopt_callback);
+ break;
+
+ case CURLOPT_SOCKOPTDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.sockopt_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_OPENSOCKETFUNCTION:
+ /*
+ * open/create socket callback function: called instead of socket(),
+ * before connect()
+ */
+ data->set.fopensocket = va_arg(param, curl_opensocket_callback);
+ break;
+
+ case CURLOPT_OPENSOCKETDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.opensocket_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_CLOSESOCKETFUNCTION:
+ /*
+ * close socket callback function: called instead of close()
+ * when shutting down a connection
+ */
+ data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
+ break;
+
+ case CURLOPT_CLOSESOCKETDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.closesocket_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_SSL_SESSIONID_CACHE:
+ data->set.ssl.sessionid = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+#ifdef USE_LIBSSH2
+ /* we only include SSH options if explicitly built to support SSH */
+ case CURLOPT_SSH_AUTH_TYPES:
+ data->set.ssh_auth_types = va_arg(param, long);
+ break;
+
+ case CURLOPT_SSH_PUBLIC_KEYFILE:
+ /*
+ * Use this file instead of the $HOME/.ssh/id_dsa.pub file
+ */
+ result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SSH_PRIVATE_KEYFILE:
+ /*
+ * Use this file instead of the $HOME/.ssh/id_dsa file
+ */
+ result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
+ /*
+ * Option to allow for the MD5 of the host public key to be checked
+ * for validation purposes.
+ */
+ result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
+ va_arg(param, char *));
+ break;
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ case CURLOPT_SSH_KNOWNHOSTS:
+ /*
+ * Store the file name to read known hosts from.
+ */
+ result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SSH_KEYFUNCTION:
+ /* setting to NULL is fine since the ssh.c functions themselves will
+ then rever to use the internal default */
+ data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
+ break;
+
+ case CURLOPT_SSH_KEYDATA:
+ /*
+ * Custom client data to pass to the SSH keyfunc callback
+ */
+ data->set.ssh_keyfunc_userp = va_arg(param, void *);
+ break;
+#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
+
+#endif /* USE_LIBSSH2 */
+
+ case CURLOPT_HTTP_TRANSFER_DECODING:
+ /*
+ * disable libcurl transfer encoding is used
+ */
+ data->set.http_te_skip = (0 == va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_HTTP_CONTENT_DECODING:
+ /*
+ * raw data passed to the application when content encoding is used
+ */
+ data->set.http_ce_skip = (0 == va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_NEW_FILE_PERMS:
+ /*
+ * Uses these permissions instead of 0644
+ */
+ data->set.new_file_perms = va_arg(param, long);
+ break;
+
+ case CURLOPT_NEW_DIRECTORY_PERMS:
+ /*
+ * Uses these permissions instead of 0755
+ */
+ data->set.new_directory_perms = va_arg(param, long);
+ break;
+
+ case CURLOPT_ADDRESS_SCOPE:
+ /*
+ * We always get longs when passed plain numericals, but for this value we
+ * know that an unsigned int will always hold the value so we blindly
+ * typecast to this type
+ */
+ data->set.scope_id = curlx_sltoui(va_arg(param, long));
+ break;
+
+ case CURLOPT_PROTOCOLS:
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+ data->set.allowed_protocols = va_arg(param, long);
+ break;
+
+ case CURLOPT_REDIR_PROTOCOLS:
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ data->set.redir_protocols = va_arg(param, long);
+ break;
+
+ case CURLOPT_MAIL_FROM:
+ /* Set the SMTP mail originator */
+ result = setstropt(&data->set.str[STRING_MAIL_FROM],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_MAIL_AUTH:
+ /* Set the SMTP auth originator */
+ result = setstropt(&data->set.str[STRING_MAIL_AUTH],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_MAIL_RCPT:
+ /* Set the list of mail recipients */
+ data->set.mail_rcpt = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_SASL_IR:
+ /* Enable/disable SASL initial response */
+ data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_RTSP_REQUEST:
+ {
+ /*
+ * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
+ * Would this be better if the RTSPREQ_* were just moved into here?
+ */
+ long curl_rtspreq = va_arg(param, long);
+ Curl_RtspReq rtspreq = RTSPREQ_NONE;
+ switch(curl_rtspreq) {
+ case CURL_RTSPREQ_OPTIONS:
+ rtspreq = RTSPREQ_OPTIONS;
+ break;
+
+ case CURL_RTSPREQ_DESCRIBE:
+ rtspreq = RTSPREQ_DESCRIBE;
+ break;
+
+ case CURL_RTSPREQ_ANNOUNCE:
+ rtspreq = RTSPREQ_ANNOUNCE;
+ break;
+
+ case CURL_RTSPREQ_SETUP:
+ rtspreq = RTSPREQ_SETUP;
+ break;
+
+ case CURL_RTSPREQ_PLAY:
+ rtspreq = RTSPREQ_PLAY;
+ break;
+
+ case CURL_RTSPREQ_PAUSE:
+ rtspreq = RTSPREQ_PAUSE;
+ break;
+
+ case CURL_RTSPREQ_TEARDOWN:
+ rtspreq = RTSPREQ_TEARDOWN;
+ break;
+
+ case CURL_RTSPREQ_GET_PARAMETER:
+ rtspreq = RTSPREQ_GET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_SET_PARAMETER:
+ rtspreq = RTSPREQ_SET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_RECORD:
+ rtspreq = RTSPREQ_RECORD;
+ break;
+
+ case CURL_RTSPREQ_RECEIVE:
+ rtspreq = RTSPREQ_RECEIVE;
+ break;
+ default:
+ rtspreq = RTSPREQ_NONE;
+ }
+
+ data->set.rtspreq = rtspreq;
+ break;
+ }
+
+
+ case CURLOPT_RTSP_SESSION_ID:
+ /*
+ * Set the RTSP Session ID manually. Useful if the application is
+ * resuming a previously established RTSP session
+ */
+ result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_STREAM_URI:
+ /*
+ * Set the Stream URI for the RTSP request. Unless the request is
+ * for generic server options, the application will need to set this.
+ */
+ result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_TRANSPORT:
+ /*
+ * The content of the Transport: header for the RTSP request
+ */
+ result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_CLIENT_CSEQ:
+ /*
+ * Set the CSEQ number to issue for the next RTSP request. Useful if the
+ * application is resuming a previously broken connection. The CSEQ
+ * will increment from this new number henceforth.
+ */
+ data->state.rtsp_next_client_CSeq = va_arg(param, long);
+ break;
+
+ case CURLOPT_RTSP_SERVER_CSEQ:
+ /* Same as the above, but for server-initiated requests */
+ data->state.rtsp_next_client_CSeq = va_arg(param, long);
+ break;
+
+ case CURLOPT_INTERLEAVEDATA:
+ data->set.rtp_out = va_arg(param, void *);
+ break;
+ case CURLOPT_INTERLEAVEFUNCTION:
+ /* Set the user defined RTP write function */
+ data->set.fwrite_rtp = va_arg(param, curl_write_callback);
+ break;
+
+ case CURLOPT_WILDCARDMATCH:
+ data->set.wildcardmatch = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_CHUNK_BGN_FUNCTION:
+ data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
+ break;
+ case CURLOPT_CHUNK_END_FUNCTION:
+ data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
+ break;
+ case CURLOPT_FNMATCH_FUNCTION:
+ data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
+ break;
+ case CURLOPT_CHUNK_DATA:
+ data->wildcard.customptr = va_arg(param, void *);
+ break;
+ case CURLOPT_FNMATCH_DATA:
+ data->set.fnmatch_data = va_arg(param, void *);
+ break;
+#ifdef USE_TLS_SRP
+ case CURLOPT_TLSAUTH_USERNAME:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_TLSAUTH_PASSWORD:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_TLSAUTH_TYPE:
+ if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP;
+ else
+ data->set.ssl.authtype = CURL_TLSAUTH_NONE;
+ break;
+#endif
+ case CURLOPT_DNS_SERVERS:
+ result = Curl_set_dns_servers(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_INTERFACE:
+ result = Curl_set_dns_interface(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_LOCAL_IP4:
+ result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_LOCAL_IP6:
+ result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
+ break;
+
+ case CURLOPT_TCP_KEEPALIVE:
+ data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_TCP_KEEPIDLE:
+ data->set.tcp_keepidle = va_arg(param, long);
+ break;
+ case CURLOPT_TCP_KEEPINTVL:
+ data->set.tcp_keepintvl = va_arg(param, long);
+ break;
+ case CURLOPT_SSL_ENABLE_NPN:
+ data->set.ssl_enable_npn = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_ENABLE_ALPN:
+ data->set.ssl_enable_alpn = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+#ifdef USE_UNIX_SOCKETS
+ case CURLOPT_UNIX_SOCKET_PATH:
+ result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
+ va_arg(param, char *));
+ break;
+#endif
+
+ case CURLOPT_PATH_AS_IS:
+ data->set.path_as_is = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ default:
+ /* unknown tag and its companion, just ignore: */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+
+ return result;
+}
+
+static void conn_free(struct connectdata *conn)
+{
+ if(!conn)
+ return;
+
+ /* possible left-overs from the async name resolvers */
+ Curl_resolver_cancel(conn);
+
+ /* close the SSL stuff before we close any sockets since they will/may
+ write to the sockets */
+ Curl_ssl_close(conn, FIRSTSOCKET);
+ Curl_ssl_close(conn, SECONDARYSOCKET);
+
+ /* close possibly still open sockets */
+ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
+ Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
+ if(CURL_SOCKET_BAD != conn->tempsock[0])
+ Curl_closesocket(conn, conn->tempsock[0]);
+ if(CURL_SOCKET_BAD != conn->tempsock[1])
+ Curl_closesocket(conn, conn->tempsock[1]);
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
+ defined(NTLM_WB_ENABLED)
+ Curl_ntlm_wb_cleanup(conn);
+#endif
+
+ Curl_safefree(conn->user);
+ Curl_safefree(conn->passwd);
+ Curl_safefree(conn->xoauth2_bearer);
+ Curl_safefree(conn->options);
+ Curl_safefree(conn->proxyuser);
+ Curl_safefree(conn->proxypasswd);
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ Curl_safefree(conn->allocptr.uagent);
+ Curl_safefree(conn->allocptr.userpwd);
+ Curl_safefree(conn->allocptr.accept_encoding);
+ Curl_safefree(conn->allocptr.te);
+ Curl_safefree(conn->allocptr.rangeline);
+ Curl_safefree(conn->allocptr.ref);
+ Curl_safefree(conn->allocptr.host);
+ Curl_safefree(conn->allocptr.cookiehost);
+ Curl_safefree(conn->allocptr.rtsp_transport);
+ Curl_safefree(conn->trailer);
+ Curl_safefree(conn->host.rawalloc); /* host name buffer */
+ Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
+ Curl_safefree(conn->master_buffer);
+
+ Curl_llist_destroy(conn->send_pipe, NULL);
+ Curl_llist_destroy(conn->recv_pipe, NULL);
+
+ conn->send_pipe = NULL;
+ conn->recv_pipe = NULL;
+
+ Curl_safefree(conn->localdev);
+ Curl_free_ssl_config(&conn->ssl_config);
+
+ free(conn); /* free all the connection oriented data */
+}
+
+/*
+ * Disconnects the given connection. Note the connection may not be the
+ * primary connection, like when freeing room in the connection cache or
+ * killing of a dead old connection.
+ *
+ * This function MUST NOT reset state in the SessionHandle struct if that
+ * isn't strictly bound to the life-time of *this* particular connection.
+ *
+ */
+
+CURL_STATIC CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct SessionHandle *data;
+ if(!conn)
+ return CURLE_OK; /* this is closed and fine already */
+ data = conn->data;
+
+ if(!data) {
+ DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
+ return CURLE_OK;
+ }
+
+ if(conn->dns_entry != NULL) {
+ Curl_resolv_unlock(data, conn->dns_entry);
+ conn->dns_entry = NULL;
+ }
+
+ Curl_hostcache_prune(data); /* kill old DNS cache entries */
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
+ /* Cleanup NTLM connection-related data */
+ Curl_http_ntlm_cleanup(conn);
+#endif
+
+ if(conn->handler->disconnect)
+ /* This is set if protocol-specific cleanups should be made */
+ conn->handler->disconnect(conn, dead_connection);
+
+ /* unlink ourselves! */
+ infof(data, "Closing connection %ld\n", conn->connection_id);
+ Curl_conncache_remove_conn(data->state.conn_cache, conn);
+
+#if defined(USE_LIBIDN)
+ if(conn->host.encalloc)
+ idn_free(conn->host.encalloc); /* encoded host name buffer, must be freed
+ with idn_free() since this was allocated
+ by libidn */
+ if(conn->proxy.encalloc)
+ idn_free(conn->proxy.encalloc); /* encoded proxy name buffer, must be
+ freed with idn_free() since this was
+ allocated by libidn */
+#elif defined(USE_WIN32_IDN)
+ free(conn->host.encalloc); /* encoded host name buffer, must be freed with
+ idn_free() since this was allocated by
+ curl_win32_idn_to_ascii */
+ free(conn->proxy.encalloc); /* encoded proxy name buffer, must be freed
+ with idn_free() since this was allocated by
+ curl_win32_idn_to_ascii */
+#endif
+
+ Curl_ssl_close(conn, FIRSTSOCKET);
+
+ /* Indicate to all handles on the pipe that we're dead */
+ if(Curl_multi_pipeline_enabled(data->multi)) {
+ signalPipeClose(conn->send_pipe, TRUE);
+ signalPipeClose(conn->recv_pipe, TRUE);
+ }
+
+ conn_free(conn);
+
+ return CURLE_OK;
+}
+
+/*
+ * This function should return TRUE if the socket is to be assumed to
+ * be dead. Most commonly this happens when the server has closed the
+ * connection due to inactivity.
+ */
+static bool SocketIsDead(curl_socket_t sock)
+{
+ int sval;
+ bool ret_val = TRUE;
+
+ sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
+ if(sval == 0)
+ /* timeout */
+ ret_val = FALSE;
+
+ return ret_val;
+}
+
+static bool IsPipeliningPossible(const struct SessionHandle *handle,
+ const struct connectdata *conn)
+{
+ if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ Curl_multi_pipeline_enabled(handle->multi) &&
+ (handle->set.httpreq == HTTPREQ_GET ||
+ handle->set.httpreq == HTTPREQ_HEAD) &&
+ handle->set.httpversion != CURL_HTTP_VERSION_1_0)
+ return TRUE;
+
+ return FALSE;
+}
+
+CURL_STATIC bool Curl_isPipeliningEnabled(const struct SessionHandle *handle)
+{
+ return Curl_multi_pipeline_enabled(handle->multi);
+}
+
+CURL_STATIC CURLcode Curl_addHandleToPipeline(struct SessionHandle *data,
+ struct curl_llist *pipeline)
+{
+ if(!Curl_llist_insert_next(pipeline, pipeline->tail, data))
+ return CURLE_OUT_OF_MEMORY;
+ return CURLE_OK;
+}
+
+CURL_STATIC int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
+ struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr;
+
+ curr = pipeline->head;
+ while(curr) {
+ if(curr->ptr == handle) {
+ Curl_llist_remove(pipeline, curr, NULL);
+ return 1; /* we removed a handle */
+ }
+ curr = curr->next;
+ }
+
+ return 0;
+}
+
+#if 0 /* this code is saved here as it is useful for debugging purposes */
+static void Curl_printPipeline(struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr;
+
+ curr = pipeline->head;
+ while(curr) {
+ struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
+ infof(data, "Handle in pipeline: %s\n", data->state.path);
+ curr = curr->next;
+ }
+}
+#endif
+
+static struct SessionHandle* gethandleathead(struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr = pipeline->head;
+ if(curr) {
+ return (struct SessionHandle *) curr->ptr;
+ }
+
+ return NULL;
+}
+
+/* remove the specified connection from all (possible) pipelines and related
+ queues */
+CURL_STATIC void Curl_getoff_all_pipelines(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ bool recv_head = (conn->readchannel_inuse &&
+ (gethandleathead(conn->recv_pipe) == data)) ? TRUE : FALSE;
+
+ bool send_head = (conn->writechannel_inuse &&
+ (gethandleathead(conn->send_pipe) == data)) ? TRUE : FALSE;
+
+ if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
+ conn->readchannel_inuse = FALSE;
+ if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head)
+ conn->writechannel_inuse = FALSE;
+}
+
+static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
+{
+ struct curl_llist_element *curr;
+
+ if(!pipeline)
+ return;
+
+ curr = pipeline->head;
+ while(curr) {
+ struct curl_llist_element *next = curr->next;
+ struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
+
+#ifdef DEBUGBUILD /* debug-only code */
+ if(data->magic != CURLEASY_MAGIC_NUMBER) {
+ /* MAJOR BADNESS */
+ infof(data, "signalPipeClose() found BAAD easy handle\n");
+ }
+#endif
+
+ if(pipe_broke)
+ data->state.pipe_broke = TRUE;
+ Curl_multi_handlePipeBreak(data);
+ Curl_llist_remove(pipeline, curr, NULL);
+ curr = next;
+ }
+}
+
+/*
+ * This function finds the connection in the connection
+ * cache that has been unused for the longest time.
+ *
+ * Returns the pointer to the oldest idle connection, or NULL if none was
+ * found.
+ */
+static struct connectdata *
+find_oldest_idle_connection(struct SessionHandle *data)
+{
+ struct conncache *bc = data->state.conn_cache;
+ struct curl_hash_iterator iter;
+ struct curl_llist_element *curr;
+ struct curl_hash_element *he;
+ long highscore=-1;
+ long score;
+ struct timeval now;
+ struct connectdata *conn_candidate = NULL;
+ struct connectbundle *bundle;
+
+ now = Curl_tvnow();
+
+ Curl_hash_start_iterate(bc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct connectdata *conn;
+
+ bundle = he->ptr;
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+
+ if(!conn->inuse) {
+ /* Set higher score for the age passed since the connection was used */
+ score = Curl_tvdiff(now, conn->now);
+
+ if(score > highscore) {
+ highscore = score;
+ conn_candidate = conn;
+ }
+ }
+ curr = curr->next;
+ }
+
+ he = Curl_hash_next_element(&iter);
+ }
+
+ return conn_candidate;
+}
+
+/*
+ * This function finds the connection in the connection
+ * bundle that has been unused for the longest time.
+ *
+ * Returns the pointer to the oldest idle connection, or NULL if none was
+ * found.
+ */
+static struct connectdata *
+find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
+ struct connectbundle *bundle)
+{
+ struct curl_llist_element *curr;
+ long highscore=-1;
+ long score;
+ struct timeval now;
+ struct connectdata *conn_candidate = NULL;
+ struct connectdata *conn;
+
+ (void)data;
+
+ now = Curl_tvnow();
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+
+ if(!conn->inuse) {
+ /* Set higher score for the age passed since the connection was used */
+ score = Curl_tvdiff(now, conn->now);
+
+ if(score > highscore) {
+ highscore = score;
+ conn_candidate = conn;
+ }
+ }
+ curr = curr->next;
+ }
+
+ return conn_candidate;
+}
+
+/*
+ * This function checks if given connection is dead and disconnects if so.
+ * (That also removes it from the connection cache.)
+ *
+ * Returns TRUE if the connection actually was dead and disconnected.
+ */
+static bool disconnect_if_dead(struct connectdata *conn,
+ struct SessionHandle *data)
+{
+ size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
+ if(!pipeLen && !conn->inuse) {
+ /* The check for a dead socket makes sense only if there are no
+ handles in pipeline and the connection isn't already marked in
+ use */
+ bool dead;
+ if(conn->handler->protocol & CURLPROTO_RTSP)
+ /* RTSP is a special case due to RTP interleaving */
+ dead = Curl_rtsp_connisdead(conn);
+ else
+ dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
+
+ if(dead) {
+ conn->data = data;
+ infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
+
+ /* disconnect resources */
+ Curl_disconnect(conn, /* dead_connection */TRUE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Wrapper to use disconnect_if_dead() function in Curl_conncache_foreach()
+ *
+ * Returns always 0.
+ */
+static int call_disconnect_if_dead(struct connectdata *conn,
+ void *param)
+{
+ struct SessionHandle* data = (struct SessionHandle*)param;
+ disconnect_if_dead(conn, data);
+ return 0; /* continue iteration */
+}
+
+/*
+ * This function scans the connection cache for half-open/dead connections,
+ * closes and removes them.
+ * The cleanup is done at most once per second.
+ */
+static void prune_dead_connections(struct SessionHandle *data)
+{
+ struct timeval now = Curl_tvnow();
+ long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+
+ if(elapsed >= 1000L) {
+ Curl_conncache_foreach(data->state.conn_cache, data,
+ call_disconnect_if_dead);
+ data->state.conn_cache->last_cleanup = now;
+ }
+}
+
+/*
+ * Given one filled in connection struct (named needle), this function should
+ * detect if there already is one that has all the significant details
+ * exactly the same and thus should be used instead.
+ *
+ * If there is a match, this function returns TRUE - and has marked the
+ * connection as 'in-use'. It must later be called with ConnectionDone() to
+ * return back to 'idle' (unused) state.
+ *
+ * The force_reuse flag is set if the connection must be used, even if
+ * the pipelining strategy wants to open a new connection instead of reusing.
+ */
+static bool
+ConnectionExists(struct SessionHandle *data,
+ struct connectdata *needle,
+ struct connectdata **usethis,
+ bool *force_reuse)
+{
+ struct connectdata *check;
+ struct connectdata *chosen = 0;
+ bool canPipeline = IsPipeliningPossible(data, needle);
+#ifdef USE_NTLM
+ bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) ||
+ (data->state.authhost.want & CURLAUTH_NTLM_WB)) &&
+ (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE;
+#endif
+ struct connectbundle *bundle;
+
+ *force_reuse = FALSE;
+
+ /* We can't pipe if the site is blacklisted */
+ if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
+ canPipeline = FALSE;
+ }
+
+ /* Look up the bundle with all the connections to this
+ particular host */
+ bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
+ if(bundle) {
+ size_t max_pipe_len = Curl_multi_max_pipeline_length(data->multi);
+ size_t best_pipe_len = max_pipe_len;
+ struct curl_llist_element *curr;
+
+ infof(data, "Found bundle for host %s: %p\n",
+ needle->host.name, (void *)bundle);
+
+ /* We can't pipe if we don't know anything about the server */
+ if(canPipeline && !bundle->server_supports_pipelining) {
+ infof(data, "Server doesn't support pipelining\n");
+ canPipeline = FALSE;
+ }
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ bool match = FALSE;
+#if defined(USE_NTLM)
+ bool credentialsMatch = FALSE;
+#endif
+ size_t pipeLen;
+
+ /*
+ * Note that if we use a HTTP proxy, we check connections to that
+ * proxy and not to the actual remote server.
+ */
+ check = curr->ptr;
+ curr = curr->next;
+
+ if(disconnect_if_dead(check, data))
+ continue;
+
+ pipeLen = check->send_pipe->size + check->recv_pipe->size;
+
+ if(canPipeline) {
+ /* Make sure the pipe has only GET requests */
+ struct SessionHandle* sh = gethandleathead(check->send_pipe);
+ struct SessionHandle* rh = gethandleathead(check->recv_pipe);
+ if(sh) {
+ if(!IsPipeliningPossible(sh, check))
+ continue;
+ }
+ else if(rh) {
+ if(!IsPipeliningPossible(rh, check))
+ continue;
+ }
+ }
+ else {
+ if(pipeLen > 0) {
+ /* can only happen within multi handles, and means that another easy
+ handle is using this connection */
+ continue;
+ }
+
+ if(Curl_resolver_asynch()) {
+ /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
+ completed yet and until then we don't re-use this connection */
+ if(!check->ip_addr_str[0]) {
+ infof(data,
+ "Connection #%ld is still name resolving, can't reuse\n",
+ check->connection_id);
+ continue;
+ }
+ }
+
+ if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) ||
+ check->bits.close) {
+ /* Don't pick a connection that hasn't connected yet or that is going
+ to get closed. */
+ infof(data, "Connection #%ld isn't open enough, can't reuse\n",
+ check->connection_id);
+#ifdef DEBUGBUILD
+ if(check->recv_pipe->size > 0) {
+ infof(data,
+ "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
+ check->connection_id);
+ }
+#endif
+ continue;
+ }
+ }
+
+ if((needle->handler->flags&PROTOPT_SSL) !=
+ (check->handler->flags&PROTOPT_SSL))
+ /* don't do mixed SSL and non-SSL connections */
+ if(!(needle->handler->protocol & check->handler->protocol))
+ /* except protocols that have been upgraded via TLS */
+ continue;
+
+ if(needle->handler->flags&PROTOPT_SSL) {
+ if((data->set.ssl.verifypeer != check->verifypeer) ||
+ (data->set.ssl.verifyhost != check->verifyhost))
+ continue;
+ }
+
+ if(needle->bits.proxy != check->bits.proxy)
+ /* don't do mixed proxy and non-proxy connections */
+ continue;
+
+ if(!canPipeline && check->inuse)
+ /* this request can't be pipelined but the checked connection is
+ already in use so we skip it */
+ continue;
+
+ if(needle->localdev || needle->localport) {
+ /* If we are bound to a specific local end (IP+port), we must not
+ re-use a random other one, although if we didn't ask for a
+ particular one we can reuse one that was bound.
+
+ This comparison is a bit rough and too strict. Since the input
+ parameters can be specified in numerous ways and still end up the
+ same it would take a lot of processing to make it really accurate.
+ Instead, this matching will assume that re-uses of bound connections
+ will most likely also re-use the exact same binding parameters and
+ missing out a few edge cases shouldn't hurt anyone very much.
+ */
+ if((check->localport != needle->localport) ||
+ (check->localportrange != needle->localportrange) ||
+ !check->localdev ||
+ !needle->localdev ||
+ strcmp(check->localdev, needle->localdev))
+ continue;
+ }
+
+ if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST))
+#ifdef USE_NTLM
+ || (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE)
+#endif
+ ) {
+ /* This protocol requires credentials per connection or is HTTP+NTLM,
+ so verify that we're using the same name and password as well */
+ if(!strequal(needle->user, check->user) ||
+ !strequal(needle->passwd, check->passwd)) {
+ /* one of them was different */
+ continue;
+ }
+#if defined(USE_NTLM)
+ credentialsMatch = TRUE;
+#endif
+ }
+
+ if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL ||
+ (needle->bits.httpproxy && check->bits.httpproxy &&
+ needle->bits.tunnel_proxy && check->bits.tunnel_proxy &&
+ Curl_raw_equal(needle->proxy.name, check->proxy.name) &&
+ (needle->port == check->port))) {
+ /* The requested connection does not use a HTTP proxy or it uses SSL or
+ it is a non-SSL protocol tunneled over the same http proxy name and
+ port number or it is a non-SSL protocol which is allowed to be
+ upgraded via TLS */
+
+ if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
+ needle->handler->protocol & check->handler->protocol) &&
+ Curl_raw_equal(needle->host.name, check->host.name) &&
+ needle->remote_port == check->remote_port) {
+ if(needle->handler->flags & PROTOPT_SSL) {
+ /* This is a SSL connection so verify that we're using the same
+ SSL options as well */
+ if(!Curl_ssl_config_matches(&needle->ssl_config,
+ &check->ssl_config)) {
+ DEBUGF(infof(data,
+ "Connection #%ld has different SSL parameters, "
+ "can't reuse\n",
+ check->connection_id));
+ continue;
+ }
+ else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
+ DEBUGF(infof(data,
+ "Connection #%ld has not started SSL connect, "
+ "can't reuse\n",
+ check->connection_id));
+ continue;
+ }
+ }
+ match = TRUE;
+ }
+ }
+ else { /* The requested needle connection is using a proxy,
+ is the checked one using the same host, port and type? */
+ if(check->bits.proxy &&
+ (needle->proxytype == check->proxytype) &&
+ (needle->bits.tunnel_proxy == check->bits.tunnel_proxy) &&
+ Curl_raw_equal(needle->proxy.name, check->proxy.name) &&
+ needle->port == check->port) {
+ /* This is the same proxy connection, use it! */
+ match = TRUE;
+ }
+ }
+
+ if(match) {
+#if defined(USE_NTLM)
+ /* If we are looking for an HTTP+NTLM connection, check if this is
+ already authenticating with the right credentials. If not, keep
+ looking so that we can reuse NTLM connections if
+ possible. (Especially we must not reuse the same connection if
+ partway through a handshake!) */
+ if(wantNTLMhttp) {
+ if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) {
+ chosen = check;
+
+ /* We must use this connection, no other */
+ *force_reuse = TRUE;
+ break;
+ }
+ else if(credentialsMatch)
+ /* this is a backup choice */
+ chosen = check;
+ continue;
+ }
+#endif
+
+ if(canPipeline) {
+ /* We can pipeline if we want to. Let's continue looking for
+ the optimal connection to use, i.e the shortest pipe that is not
+ blacklisted. */
+
+ if(pipeLen == 0) {
+ /* We have the optimal connection. Let's stop looking. */
+ chosen = check;
+ break;
+ }
+
+ /* We can't use the connection if the pipe is full */
+ if(pipeLen >= max_pipe_len)
+ continue;
+
+ /* We can't use the connection if the pipe is penalized */
+ if(Curl_pipeline_penalized(data, check))
+ continue;
+
+ if(pipeLen < best_pipe_len) {
+ /* This connection has a shorter pipe so far. We'll pick this
+ and continue searching */
+ chosen = check;
+ best_pipe_len = pipeLen;
+ continue;
+ }
+ }
+ else {
+ /* We have found a connection. Let's stop searching. */
+ chosen = check;
+ break;
+ }
+ }
+ }
+ }
+
+ if(chosen) {
+ *usethis = chosen;
+ return TRUE; /* yes, we found one to use! */
+ }
+
+ return FALSE; /* no matching connecting exists */
+}
+
+/* Mark the connection as 'idle', or close it if the cache is full.
+ Returns TRUE if the connection is kept, or FALSE if it was closed. */
+static bool
+ConnectionDone(struct SessionHandle *data, struct connectdata *conn)
+{
+ /* data->multi->maxconnects can be negative, deal with it. */
+ size_t maxconnects =
+ (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
+ data->multi->maxconnects;
+ struct connectdata *conn_candidate = NULL;
+
+ /* Mark the current connection as 'unused' */
+ conn->inuse = FALSE;
+
+ if(maxconnects > 0 &&
+ data->state.conn_cache->num_connections > maxconnects) {
+ infof(data, "Connection cache is full, closing the oldest one.\n");
+
+ conn_candidate = find_oldest_idle_connection(data);
+
+ if(conn_candidate) {
+ /* Set the connection's owner correctly */
+ conn_candidate->data = data;
+
+ /* the winner gets the honour of being disconnected */
+ (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ }
+ }
+
+ return (conn_candidate == conn) ? FALSE : TRUE;
+}
+
+/*
+ * The given input connection struct pointer is to be stored in the connection
+ * cache. If the cache is already full, least interesting existing connection
+ * (if any) gets closed.
+ *
+ * The given connection should be unique. That must've been checked prior to
+ * this call.
+ */
+static CURLcode ConnectionStore(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ return Curl_conncache_add_conn(data->state.conn_cache, conn);
+}
+
+/* after a TCP connection to the proxy has been verified, this function does
+ the next magic step.
+
+ Note: this function's sub-functions call failf()
+
+*/
+CURL_STATIC CURLcode Curl_connected_proxy(struct connectdata *conn,
+ int sockindex)
+{
+ if(!conn->bits.proxy || sockindex)
+ /* this magic only works for the primary socket as the secondary is used
+ for FTP only and it has FTP specific magic in ftp.c */
+ return CURLE_OK;
+
+ switch(conn->proxytype) {
+#ifndef CURL_DISABLE_PROXY
+ case CURLPROXY_SOCKS5:
+ case CURLPROXY_SOCKS5_HOSTNAME:
+ return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
+ conn->host.name, conn->remote_port,
+ FIRSTSOCKET, conn);
+
+ case CURLPROXY_SOCKS4:
+ return Curl_SOCKS4(conn->proxyuser, conn->host.name,
+ conn->remote_port, FIRSTSOCKET, conn, FALSE);
+
+ case CURLPROXY_SOCKS4A:
+ return Curl_SOCKS4(conn->proxyuser, conn->host.name,
+ conn->remote_port, FIRSTSOCKET, conn, TRUE);
+
+#endif /* CURL_DISABLE_PROXY */
+ case CURLPROXY_HTTP:
+ case CURLPROXY_HTTP_1_0:
+ /* do nothing here. handled later. */
+ break;
+ default:
+ break;
+ } /* switch proxytype */
+
+ return CURLE_OK;
+}
+
+/*
+ * verboseconnect() displays verbose information after a connect
+ */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+CURL_STATIC void Curl_verboseconnect(struct connectdata *conn)
+{
+ if(conn->data->set.verbose)
+ infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
+ conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
+ conn->ip_addr_str, conn->port, conn->connection_id);
+}
+#endif
+
+CURL_STATIC int Curl_protocol_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn->handler->proto_getsock)
+ return conn->handler->proto_getsock(conn, socks, numsocks);
+ return GETSOCK_BLANK;
+}
+
+CURL_STATIC int Curl_doing_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn && conn->handler->doing_getsock)
+ return conn->handler->doing_getsock(conn, socks, numsocks);
+ return GETSOCK_BLANK;
+}
+
+/*
+ * We are doing protocol-specific connecting and this is being called over and
+ * over from the multi interface until the connection phase is done on
+ * protocol layer.
+ */
+
+CURL_STATIC CURLcode Curl_protocol_connecting(struct connectdata *conn,
+ bool *done)
+{
+ CURLcode result=CURLE_OK;
+
+ if(conn && conn->handler->connecting) {
+ *done = FALSE;
+ result = conn->handler->connecting(conn, done);
+ }
+ else
+ *done = TRUE;
+
+ return result;
+}
+
+/*
+ * We are DOING this is being called over and over from the multi interface
+ * until the DOING phase is done on protocol layer.
+ */
+
+CURL_STATIC CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
+{
+ CURLcode result=CURLE_OK;
+
+ if(conn && conn->handler->doing) {
+ *done = FALSE;
+ result = conn->handler->doing(conn, done);
+ }
+ else
+ *done = TRUE;
+
+ return result;
+}
+
+/*
+ * We have discovered that the TCP connection has been successful, we can now
+ * proceed with some action.
+ *
+ */
+CURL_STATIC CURLcode Curl_protocol_connect(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode result=CURLE_OK;
+
+ *protocol_done = FALSE;
+
+ if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
+ /* We already are connected, get back. This may happen when the connect
+ worked fine in the first call, like when we connect to a local server
+ or proxy. Note that we don't know if the protocol is actually done.
+
+ Unless this protocol doesn't have any protocol-connect callback, as
+ then we know we're done. */
+ if(!conn->handler->connecting)
+ *protocol_done = TRUE;
+
+ return CURLE_OK;
+ }
+
+ if(!conn->bits.protoconnstart) {
+
+ result = Curl_proxy_connect(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
+ (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
+ /* when using an HTTP tunnel proxy, await complete tunnel establishment
+ before proceeding further. Return CURLE_OK so we'll be called again */
+ return CURLE_OK;
+
+ if(conn->handler->connect_it) {
+ /* is there a protocol-specific connect() procedure? */
+
+ /* Call the protocol-specific connect function */
+ result = conn->handler->connect_it(conn, protocol_done);
+ }
+ else
+ *protocol_done = TRUE;
+
+ /* it has started, possibly even completed but that knowledge isn't stored
+ in this bit! */
+ if(!result)
+ conn->bits.protoconnstart = TRUE;
+ }
+
+ return result; /* pass back status */
+}
+
+/*
+ * Helpers for IDNA convertions.
+ */
+static bool is_ASCII_name(const char *hostname)
+{
+ const unsigned char *ch = (const unsigned char*)hostname;
+
+ while(*ch) {
+ if(*ch++ & 0x80)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#ifdef USE_LIBIDN
+/*
+ * Check if characters in hostname is allowed in Top Level Domain.
+ */
+static bool tld_check_name(struct SessionHandle *data,
+ const char *ace_hostname)
+{
+ size_t err_pos;
+ char *uc_name = NULL;
+ int rc;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ const char *tld_errmsg = "<no msg>";
+#else
+ (void)data;
+#endif
+
+ /* Convert (and downcase) ACE-name back into locale's character set */
+ rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
+ if(rc != IDNA_SUCCESS)
+ return FALSE;
+
+ rc = tld_check_lz(uc_name, &err_pos, NULL);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef HAVE_TLD_STRERROR
+ if(rc != TLD_SUCCESS)
+ tld_errmsg = tld_strerror((Tld_rc)rc);
+#endif
+ if(rc == TLD_INVALID)
+ infof(data, "WARNING: %s; pos %u = `%c'/0x%02X\n",
+ tld_errmsg, err_pos, uc_name[err_pos],
+ uc_name[err_pos] & 255);
+ else if(rc != TLD_SUCCESS)
+ infof(data, "WARNING: TLD check for %s failed; %s\n",
+ uc_name, tld_errmsg);
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+ if(uc_name)
+ idn_free(uc_name);
+ if(rc != TLD_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+#endif
+
+/*
+ * Perform any necessary IDN conversion of hostname
+ */
+static void fix_hostname(struct SessionHandle *data,
+ struct connectdata *conn, struct hostname *host)
+{
+ size_t len;
+
+#ifndef USE_LIBIDN
+ (void)data;
+ (void)conn;
+#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void)conn;
+#endif
+
+ /* set the name we use to display the host name */
+ host->dispname = host->name;
+
+ len = strlen(host->name);
+ if(len && (host->name[len-1] == '.'))
+ /* strip off a single trailing dot if present, primarily for SNI but
+ there's no use for it */
+ host->name[len-1]=0;
+
+ if(!is_ASCII_name(host->name)) {
+#ifdef USE_LIBIDN
+ /*************************************************************
+ * Check name for non-ASCII and convert hostname to ACE form.
+ *************************************************************/
+ if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
+ char *ace_hostname = NULL;
+ int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
+ infof (data, "Input domain encoded as `%s'\n",
+ stringprep_locale_charset ());
+ if(rc != IDNA_SUCCESS)
+ infof(data, "Failed to convert %s to ACE; %s\n",
+ host->name, Curl_idn_strerror(conn, rc));
+ else {
+ /* tld_check_name() displays a warning if the host name contains
+ "illegal" characters for this TLD */
+ (void)tld_check_name(data, ace_hostname);
+
+ host->encalloc = ace_hostname;
+ /* change the name pointer to point to the encoded hostname */
+ host->name = host->encalloc;
+ }
+ }
+#elif defined(USE_WIN32_IDN)
+ /*************************************************************
+ * Check name for non-ASCII and convert hostname to ACE form.
+ *************************************************************/
+ char *ace_hostname = NULL;
+ int rc = curl_win32_idn_to_ascii(host->name, &ace_hostname);
+ if(rc == 0)
+ infof(data, "Failed to convert %s to ACE;\n",
+ host->name);
+ else {
+ host->encalloc = ace_hostname;
+ /* change the name pointer to point to the encoded hostname */
+ host->name = host->encalloc;
+ }
+#else
+ infof(data, "IDN support not present, can't parse Unicode domains\n");
+#endif
+ }
+}
+
+static void llist_dtor(void *user, void *element)
+{
+ (void)user;
+ (void)element;
+ /* Do nothing */
+}
+
+/*
+ * Allocate and initialize a new connectdata object.
+ */
+static struct connectdata *allocate_conn(struct SessionHandle *data)
+{
+ struct connectdata *conn = calloc(1, sizeof(struct connectdata));
+ if(!conn)
+ return NULL;
+
+ conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
+ already from start to avoid NULL
+ situations and checks */
+
+ /* and we setup a few fields in case we end up actually using this struct */
+
+ conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->connection_id = -1; /* no ID */
+ conn->port = -1; /* unknown at this point */
+ conn->remote_port = -1; /* unknown */
+
+ /* Default protocol-independent behavior doesn't support persistent
+ connections, so we set this to force-close. Protocols that support
+ this need to set this to FALSE in their "curl_do" functions. */
+ connclose(conn, "Default to force-close");
+
+ /* Store creation time to help future close decision making */
+ conn->created = Curl_tvnow();
+
+ conn->data = data; /* Setup the association between this connection
+ and the SessionHandle */
+
+ conn->proxytype = data->set.proxytype; /* type */
+
+#ifdef CURL_DISABLE_PROXY
+
+ conn->bits.proxy = FALSE;
+ conn->bits.httpproxy = FALSE;
+ conn->bits.proxy_user_passwd = FALSE;
+ conn->bits.tunnel_proxy = FALSE;
+
+#else /* CURL_DISABLE_PROXY */
+
+ /* note that these two proxy bits are now just on what looks to be
+ requested, they may be altered down the road */
+ conn->bits.proxy = (data->set.str[STRING_PROXY] &&
+ *data->set.str[STRING_PROXY])?TRUE:FALSE;
+ conn->bits.httpproxy = (conn->bits.proxy &&
+ (conn->proxytype == CURLPROXY_HTTP ||
+ conn->proxytype == CURLPROXY_HTTP_1_0))?TRUE:FALSE;
+ conn->bits.proxy_user_passwd =
+ (NULL != data->set.str[STRING_PROXYUSERNAME])?TRUE:FALSE;
+ conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
+
+#endif /* CURL_DISABLE_PROXY */
+
+ conn->bits.user_passwd = (NULL != data->set.str[STRING_USERNAME])?TRUE:FALSE;
+ conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
+ conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
+
+ conn->verifypeer = data->set.ssl.verifypeer;
+ conn->verifyhost = data->set.ssl.verifyhost;
+
+ conn->ip_version = data->set.ipver;
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
+ defined(NTLM_WB_ENABLED)
+ conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+ conn->ntlm_auth_hlpr_pid = 0;
+ conn->challenge_header = NULL;
+ conn->response_header = NULL;
+#endif
+
+ if(Curl_multi_pipeline_enabled(data->multi) &&
+ !conn->master_buffer) {
+ /* Allocate master_buffer to be used for pipelining */
+ conn->master_buffer = calloc(BUFSIZE, sizeof (char));
+ if(!conn->master_buffer)
+ goto error;
+ }
+
+ /* Initialize the pipeline lists */
+ conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
+ conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
+ if(!conn->send_pipe || !conn->recv_pipe)
+ goto error;
+
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CLEAR;
+#endif
+
+ /* Store the local bind parameters that will be used for this connection */
+ if(data->set.str[STRING_DEVICE]) {
+ conn->localdev = strdup(data->set.str[STRING_DEVICE]);
+ if(!conn->localdev)
+ goto error;
+ }
+ conn->localportrange = data->set.localportrange;
+ conn->localport = data->set.localport;
+
+ /* the close socket stuff needs to be copied to the connection struct as
+ it may live on without (this specific) SessionHandle */
+ conn->fclosesocket = data->set.fclosesocket;
+ conn->closesocket_client = data->set.closesocket_client;
+
+ return conn;
+ error:
+
+ Curl_llist_destroy(conn->send_pipe, NULL);
+ Curl_llist_destroy(conn->recv_pipe, NULL);
+
+ conn->send_pipe = NULL;
+ conn->recv_pipe = NULL;
+
+ free(conn->master_buffer);
+ free(conn->localdev);
+ free(conn);
+ return NULL;
+}
+
+static CURLcode findprotocol(struct SessionHandle *data,
+ struct connectdata *conn,
+ const char *protostr)
+{
+ const struct Curl_handler * const *pp;
+ const struct Curl_handler *p;
+
+ /* Scan protocol handler table and match against 'protostr' to set a few
+ variables based on the URL. Now that the handler may be changed later
+ when the protocol specific setup function is called. */
+ for(pp = protocols; (p = *pp) != NULL; pp++) {
+ if(Curl_raw_equal(p->scheme, protostr)) {
+ /* Protocol found in table. Check if allowed */
+ if(!(data->set.allowed_protocols & p->protocol))
+ /* nope, get out */
+ break;
+
+ /* it is allowed for "normal" request, now do an extra check if this is
+ the result of a redirect */
+ if(data->state.this_is_a_follow &&
+ !(data->set.redir_protocols & p->protocol))
+ /* nope, get out */
+ break;
+
+ /* Perform setup complement if some. */
+ conn->handler = conn->given = p;
+
+ /* 'port' and 'remote_port' are set in setup_connection_internals() */
+ return CURLE_OK;
+ }
+ }
+
+
+ /* The protocol was not found in the table, but we don't have to assign it
+ to anything since it is already assigned to a dummy-struct in the
+ create_conn() function when the connectdata struct is allocated. */
+ failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
+ protostr);
+
+ return CURLE_UNSUPPORTED_PROTOCOL;
+}
+
+/*
+ * Parse URL and fill in the relevant members of the connection struct.
+ */
+static CURLcode parseurlandfillconn(struct SessionHandle *data,
+ struct connectdata *conn,
+ bool *prot_missing,
+ char **userp, char **passwdp,
+ char **optionsp)
+{
+ char *at;
+ char *fragment;
+ char *path = data->state.path;
+ char *query;
+ int rc;
+ char protobuf[16] = "";
+ const char *protop = "";
+ CURLcode result;
+ bool rebuild_url = FALSE;
+
+ *prot_missing = FALSE;
+
+ /* We might pass the entire URL into the request so we need to make sure
+ * there are no bad characters in there.*/
+ if(strpbrk(data->change.url, "\r\n")) {
+ failf(data, "Illegal characters found in URL");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /*************************************************************
+ * Parse the URL.
+ *
+ * We need to parse the url even when using the proxy, because we will need
+ * the hostname and port in case we are trying to SSL connect through the
+ * proxy -- and we don't know if we will need to use SSL until we parse the
+ * url ...
+ ************************************************************/
+ if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
+ protobuf, path)) &&
+ Curl_raw_equal(protobuf, "file")) {
+ if(path[0] == '/' && path[1] == '/') {
+ /* Allow omitted hostname (e.g. file:/<path>). This is not strictly
+ * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
+ * file://localhost/<path> is similar to how other schemes treat missing
+ * hostnames. See RFC 1808. */
+
+ /* This cannot be done with strcpy() in a portable manner, since the
+ memory areas overlap! */
+ memmove(path, path + 2, strlen(path + 2)+1);
+ }
+ /*
+ * we deal with file://<host>/<path> differently since it supports no
+ * hostname other than "localhost" and "127.0.0.1", which is unique among
+ * the URL protocols specified in RFC 1738
+ */
+ if(path[0] != '/') {
+ /* the URL included a host name, we ignore host names in file:// URLs
+ as the standards don't define what to do with them */
+ char *ptr=strchr(path, '/');
+ if(ptr) {
+ /* there was a slash present
+
+ RFC1738 (section 3.1, page 5) says:
+
+ The rest of the locator consists of data specific to the scheme,
+ and is known as the "url-path". It supplies the details of how the
+ specified resource can be accessed. Note that the "/" between the
+ host (or port) and the url-path is NOT part of the url-path.
+
+ As most agents use file://localhost/foo to get '/foo' although the
+ slash preceding foo is a separator and not a slash for the path,
+ a URL as file://localhost//foo must be valid as well, to refer to
+ the same file with an absolute path.
+ */
+
+ if(ptr[1] && ('/' == ptr[1]))
+ /* if there was two slashes, we skip the first one as that is then
+ used truly as a separator */
+ ptr++;
+
+ /* This cannot be made with strcpy, as the memory chunks overlap! */
+ memmove(path, ptr, strlen(ptr)+1);
+ }
+ }
+
+ protop = "file"; /* protocol string */
+ }
+ else {
+ /* clear path */
+ path[0]=0;
+
+ if(2 > sscanf(data->change.url,
+ "%15[^\n:]://%[^\n/?]%[^\n]",
+ protobuf,
+ conn->host.name, path)) {
+
+ /*
+ * The URL was badly formatted, let's try the browser-style _without_
+ * protocol specified like 'http://'.
+ */
+ rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
+ if(1 > rc) {
+ /*
+ * We couldn't even get this format.
+ * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is
+ * assigned, but the return value is EOF!
+ */
+#if defined(__DJGPP__) && (DJGPP_MINOR == 4)
+ if(!(rc == -1 && *conn->host.name))
+#endif
+ {
+ failf(data, "<url> malformed");
+ return CURLE_URL_MALFORMAT;
+ }
+ }
+
+ /*
+ * Since there was no protocol part specified, we guess what protocol it
+ * is based on the first letters of the server name.
+ */
+
+ /* Note: if you add a new protocol, please update the list in
+ * lib/version.c too! */
+
+ if(checkprefix("FTP.", conn->host.name))
+ protop = "ftp";
+ else if(checkprefix("DICT.", conn->host.name))
+ protop = "DICT";
+ else if(checkprefix("LDAP.", conn->host.name))
+ protop = "LDAP";
+ else if(checkprefix("IMAP.", conn->host.name))
+ protop = "IMAP";
+ else if(checkprefix("SMTP.", conn->host.name))
+ protop = "smtp";
+ else if(checkprefix("POP3.", conn->host.name))
+ protop = "pop3";
+ else {
+ protop = "http";
+ }
+
+ *prot_missing = TRUE; /* not given in URL */
+ }
+ else
+ protop = protobuf;
+ }
+
+ /* We search for '?' in the host name (but only on the right side of a
+ * @-letter to allow ?-letters in username and password) to handle things
+ * like http://example.com?param= (notice the missing '/').
+ */
+ at = strchr(conn->host.name, '@');
+ if(at)
+ query = strchr(at+1, '?');
+ else
+ query = strchr(conn->host.name, '?');
+
+ if(query) {
+ /* We must insert a slash before the '?'-letter in the URL. If the URL had
+ a slash after the '?', that is where the path currently begins and the
+ '?string' is still part of the host name.
+
+ We must move the trailing part from the host name and put it first in
+ the path. And have it all prefixed with a slash.
+ */
+
+ size_t hostlen = strlen(query);
+ size_t pathlen = strlen(path);
+
+ /* move the existing path plus the zero byte forward, to make room for
+ the host-name part */
+ memmove(path+hostlen+1, path, pathlen+1);
+
+ /* now copy the trailing host part in front of the existing path */
+ memcpy(path+1, query, hostlen);
+
+ path[0]='/'; /* prepend the missing slash */
+ rebuild_url = TRUE;
+
+ *query=0; /* now cut off the hostname at the ? */
+ }
+ else if(!path[0]) {
+ /* if there's no path set, use a single slash */
+ strcpy(path, "/");
+ rebuild_url = TRUE;
+ }
+
+ /* If the URL is malformatted (missing a '/' after hostname before path) we
+ * insert a slash here. The only letter except '/' we accept to start a path
+ * is '?'.
+ */
+ if(path[0] == '?') {
+ /* We need this function to deal with overlapping memory areas. We know
+ that the memory area 'path' points to is 'urllen' bytes big and that
+ is bigger than the path. Use +1 to move the zero byte too. */
+ memmove(&path[1], path, strlen(path)+1);
+ path[0] = '/';
+ rebuild_url = TRUE;
+ }
+ else if(!data->set.path_as_is) {
+ /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
+ char *newp = Curl_dedotdotify(path);
+ if(!newp)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(strcmp(newp, path)) {
+ rebuild_url = TRUE;
+ free(data->state.pathbuffer);
+ data->state.pathbuffer = newp;
+ data->state.path = newp;
+ path = newp;
+ }
+ else
+ free(newp);
+ }
+
+ /*
+ * "rebuild_url" means that one or more URL components have been modified so
+ * we need to generate an updated full version. We need the corrected URL
+ * when communicating over HTTP proxy and we don't know at this point if
+ * we're using a proxy or not.
+ */
+ if(rebuild_url) {
+ char *reurl;
+
+ size_t plen = strlen(path); /* new path, should be 1 byte longer than
+ the original */
+ size_t urllen = strlen(data->change.url); /* original URL length */
+
+ size_t prefixlen = strlen(conn->host.name);
+
+ if(!*prot_missing)
+ prefixlen += strlen(protop) + strlen("://");
+
+ reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
+ if(!reurl)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* copy the prefix */
+ memcpy(reurl, data->change.url, prefixlen);
+
+ /* append the trailing piece + zerobyte */
+ memcpy(&reurl[prefixlen], path, plen + 1);
+
+ /* possible free the old one */
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ infof(data, "Rebuilt URL to: %s\n", reurl);
+
+ data->change.url = reurl;
+ data->change.url_alloc = TRUE; /* free this later */
+ }
+
+ /*
+ * Parse the login details from the URL and strip them out of
+ * the host name
+ */
+ result = parse_url_login(data, conn, userp, passwdp, optionsp);
+ if(result)
+ return result;
+
+ if(conn->host.name[0] == '[') {
+ /* This looks like an IPv6 address literal. See if there is an address
+ scope if there is no location header */
+ char *percent = strchr(conn->host.name, '%');
+ if(percent) {
+ unsigned int identifier_offset = 3;
+ char *endp;
+ unsigned long scope;
+ if(strncmp("%25", percent, 3) != 0) {
+ infof(data,
+ "Please URL encode %% as %%25, see RFC 6874.\n");
+ identifier_offset = 1;
+ }
+ scope = strtoul(percent + identifier_offset, &endp, 10);
+ if(*endp == ']') {
+ /* The address scope was well formed. Knock it out of the
+ hostname. */
+ memmove(percent, endp, strlen(endp)+1);
+ conn->scope_id = (unsigned int)scope;
+ }
+ else {
+ /* Zone identifier is not numeric */
+#if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
+ char ifname[IFNAMSIZ + 2];
+ char *square_bracket;
+ unsigned int scopeidx = 0;
+ strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
+ /* Ensure nullbyte termination */
+ ifname[IFNAMSIZ + 1] = '\0';
+ square_bracket = strchr(ifname, ']');
+ if(square_bracket) {
+ /* Remove ']' */
+ *square_bracket = '\0';
+ scopeidx = if_nametoindex(ifname);
+ if(scopeidx == 0) {
+ infof(data, "Invalid network interface: %s; %s\n", ifname,
+ strerror(errno));
+ }
+ }
+ if(scopeidx > 0) {
+ char *p = percent + identifier_offset + strlen(ifname);
+
+ /* Remove zone identifier from hostname */
+ memmove(percent, p, strlen(p) + 1);
+ conn->scope_id = scopeidx;
+ }
+ else
+#endif /* HAVE_NET_IF_H && IFNAMSIZ */
+ infof(data, "Invalid IPv6 address format\n");
+ }
+ }
+ }
+
+ if(data->set.scope_id)
+ /* Override any scope that was set above. */
+ conn->scope_id = data->set.scope_id;
+
+ /* Remove the fragment part of the path. Per RFC 2396, this is always the
+ last part of the URI. We are looking for the first '#' so that we deal
+ gracefully with non conformant URI such as http://example.com#foo#bar. */
+ fragment = strchr(path, '#');
+ if(fragment) {
+ *fragment = 0;
+
+ /* we know the path part ended with a fragment, so we know the full URL
+ string does too and we need to cut it off from there so it isn't used
+ over proxy */
+ fragment = strchr(data->change.url, '#');
+ if(fragment)
+ *fragment = 0;
+ }
+
+ /*
+ * So if the URL was A://B/C#D,
+ * protop is A
+ * conn->host.name is B
+ * data->state.path is /C
+ */
+
+ return findprotocol(data, conn, protop);
+}
+
+/*
+ * If we're doing a resumed transfer, we need to setup our stuff
+ * properly.
+ */
+static CURLcode setup_range(struct SessionHandle *data)
+{
+ struct UrlState *s = &data->state;
+ s->resume_from = data->set.set_resume_from;
+ if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
+ if(s->rangestringalloc)
+ free(s->range);
+
+ if(s->resume_from)
+ s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
+ else
+ s->range = strdup(data->set.str[STRING_SET_RANGE]);
+
+ s->rangestringalloc = (s->range)?TRUE:FALSE;
+
+ if(!s->range)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* tell ourselves to fetch this range */
+ s->use_range = TRUE; /* enable range download */
+ }
+ else
+ s->use_range = FALSE; /* disable range download */
+
+ return CURLE_OK;
+}
+
+
+/*
+ * setup_connection_internals() -
+ *
+ * Setup connection internals specific to the requested protocol in the
+ * SessionHandle. This is inited and setup before the connection is made but
+ * is about the particular protocol that is to be used.
+ *
+ * This MUST get called after proxy magic has been figured out.
+ */
+static CURLcode setup_connection_internals(struct connectdata *conn)
+{
+ const struct Curl_handler * p;
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+
+ /* in some case in the multi state-machine, we go back to the CONNECT state
+ and then a second (or third or...) call to this function will be made
+ without doing a DISCONNECT or DONE in between (since the connection is
+ yet in place) and therefore this function needs to first make sure
+ there's no lingering previous data allocated. */
+ Curl_free_request_state(data);
+
+ memset(&data->req, 0, sizeof(struct SingleRequest));
+ data->req.maxdownload = -1;
+
+ conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
+
+ /* Perform setup complement if some. */
+ p = conn->handler;
+
+ if(p->setup_connection) {
+ result = (*p->setup_connection)(conn);
+
+ if(result)
+ return result;
+
+ p = conn->handler; /* May have changed. */
+ }
+
+ if(conn->port < 0)
+ /* we check for -1 here since if proxy was detected already, this
+ was very likely already set to the proxy port */
+ conn->port = p->defport;
+
+ /* only if remote_port was not already parsed off the URL we use the
+ default port number */
+ if(conn->remote_port < 0)
+ conn->remote_port = (unsigned short)conn->given->defport;
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_free_request_state() should free temp data that was allocated in the
+ * SessionHandle for this single request.
+ */
+
+CURL_STATIC void Curl_free_request_state(struct SessionHandle *data)
+{
+ Curl_safefree(data->req.protop);
+ Curl_safefree(data->req.newurl);
+}
+
+
+#ifndef CURL_DISABLE_PROXY
+/****************************************************************
+* Checks if the host is in the noproxy list. returns true if it matches
+* and therefore the proxy should NOT be used.
+****************************************************************/
+static bool check_noproxy(const char* name, const char* no_proxy)
+{
+ /* no_proxy=domain1.dom,host.domain2.dom
+ * (a comma-separated list of hosts which should
+ * not be proxied, or an asterisk to override
+ * all proxy variables)
+ */
+ size_t tok_start;
+ size_t tok_end;
+ const char* separator = ", ";
+ size_t no_proxy_len;
+ size_t namelen;
+ char *endptr;
+
+ if(no_proxy && no_proxy[0]) {
+ if(Curl_raw_equal("*", no_proxy)) {
+ return TRUE;
+ }
+
+ /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ no_proxy_len = strlen(no_proxy);
+ endptr = strchr(name, ':');
+ if(endptr)
+ namelen = endptr - name;
+ else
+ namelen = strlen(name);
+
+ for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
+ while(tok_start < no_proxy_len &&
+ strchr(separator, no_proxy[tok_start]) != NULL) {
+ /* Look for the beginning of the token. */
+ ++tok_start;
+ }
+
+ if(tok_start == no_proxy_len)
+ break; /* It was all trailing separator chars, no more tokens. */
+
+ for(tok_end = tok_start; tok_end < no_proxy_len &&
+ strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
+ /* Look for the end of the token. */
+ ;
+
+ /* To match previous behaviour, where it was necessary to specify
+ * ".local.com" to prevent matching "notlocal.com", we will leave
+ * the '.' off.
+ */
+ if(no_proxy[tok_start] == '.')
+ ++tok_start;
+
+ if((tok_end - tok_start) <= namelen) {
+ /* Match the last part of the name to the domain we are checking. */
+ const char *checkn = name + namelen - (tok_end - tok_start);
+ if(Curl_raw_nequal(no_proxy + tok_start, checkn,
+ tok_end - tok_start)) {
+ if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
+ /* We either have an exact match, or the previous character is a .
+ * so it is within the same domain, so no proxy for this host.
+ */
+ return TRUE;
+ }
+ }
+ } /* if((tok_end - tok_start) <= namelen) */
+ } /* for(tok_start = 0; tok_start < no_proxy_len;
+ tok_start = tok_end + 1) */
+ } /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ return FALSE;
+}
+
+/****************************************************************
+* Detect what (if any) proxy to use. Remember that this selects a host
+* name and is not limited to HTTP proxies only.
+* The returned pointer must be freed by the caller (unless NULL)
+****************************************************************/
+static char *detect_proxy(struct connectdata *conn)
+{
+ char *proxy = NULL;
+
+#ifndef CURL_DISABLE_HTTP
+ /* If proxy was not specified, we check for default proxy environment
+ * variables, to enable i.e Lynx compliance:
+ *
+ * http_proxy=http://some.server.dom:port/
+ * https_proxy=http://some.server.dom:port/
+ * ftp_proxy=http://some.server.dom:port/
+ * no_proxy=domain1.dom,host.domain2.dom
+ * (a comma-separated list of hosts which should
+ * not be proxied, or an asterisk to override
+ * all proxy variables)
+ * all_proxy=http://some.server.dom:port/
+ * (seems to exist for the CERN www lib. Probably
+ * the first to check for.)
+ *
+ * For compatibility, the all-uppercase versions of these variables are
+ * checked if the lowercase versions don't exist.
+ */
+ char *no_proxy=NULL;
+ char proxy_env[128];
+
+ no_proxy=curl_getenv("no_proxy");
+ if(!no_proxy)
+ no_proxy=curl_getenv("NO_PROXY");
+
+ if(!check_noproxy(conn->host.name, no_proxy)) {
+ /* It was not listed as without proxy */
+ const char *protop = conn->handler->scheme;
+ char *envp = proxy_env;
+ char *prox;
+
+ /* Now, build <protocol>_proxy and check for such a one to use */
+ while(*protop)
+ *envp++ = (char)tolower((int)*protop++);
+
+ /* append _proxy */
+ strcpy(envp, "_proxy");
+
+ /* read the protocol proxy: */
+ prox=curl_getenv(proxy_env);
+
+ /*
+ * We don't try the uppercase version of HTTP_PROXY because of
+ * security reasons:
+ *
+ * When curl is used in a webserver application
+ * environment (cgi or php), this environment variable can
+ * be controlled by the web server user by setting the
+ * http header 'Proxy:' to some value.
+ *
+ * This can cause 'internal' http/ftp requests to be
+ * arbitrarily redirected by any external attacker.
+ */
+ if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
+ /* There was no lowercase variable, try the uppercase version: */
+ Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
+ prox=curl_getenv(proxy_env);
+ }
+
+ if(prox)
+ proxy = prox; /* use this */
+ else {
+ proxy = curl_getenv("all_proxy"); /* default proxy to use */
+ if(!proxy)
+ proxy=curl_getenv("ALL_PROXY");
+ }
+ } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
+ non-proxy */
+ free(no_proxy);
+
+#else /* !CURL_DISABLE_HTTP */
+
+ (void)conn;
+#endif /* CURL_DISABLE_HTTP */
+
+ return proxy;
+}
+
+/*
+ * If this is supposed to use a proxy, we need to figure out the proxy
+ * host name, so that we can re-use an existing connection
+ * that may exist registered to the same proxy host.
+ * proxy will be freed before this function returns.
+ */
+static CURLcode parse_proxy(struct SessionHandle *data,
+ struct connectdata *conn, char *proxy)
+{
+ char *prox_portno;
+ char *endofprot;
+
+ /* We use 'proxyptr' to point to the proxy name from now on... */
+ char *proxyptr;
+ char *portptr;
+ char *atsign;
+
+ /* We do the proxy host string parsing here. We want the host name and the
+ * port name. Accept a protocol:// prefix
+ */
+
+ /* Parse the protocol part if present */
+ endofprot = strstr(proxy, "://");
+ if(endofprot) {
+ proxyptr = endofprot+3;
+ if(checkprefix("socks5h", proxy))
+ conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
+ else if(checkprefix("socks5", proxy))
+ conn->proxytype = CURLPROXY_SOCKS5;
+ else if(checkprefix("socks4a", proxy))
+ conn->proxytype = CURLPROXY_SOCKS4A;
+ else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
+ conn->proxytype = CURLPROXY_SOCKS4;
+ /* Any other xxx:// : change to http proxy */
+ }
+ else
+ proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
+
+ /* Is there a username and password given in this proxy url? */
+ atsign = strchr(proxyptr, '@');
+ if(atsign) {
+ char *proxyuser = NULL;
+ char *proxypasswd = NULL;
+ CURLcode result =
+ parse_login_details(proxyptr, atsign - proxyptr,
+ &proxyuser, &proxypasswd, NULL);
+ if(!result) {
+ /* found user and password, rip them out. note that we are
+ unescaping them, as there is otherwise no way to have a
+ username or password with reserved characters like ':' in
+ them. */
+ Curl_safefree(conn->proxyuser);
+ if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
+ conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
+ else
+ conn->proxyuser = strdup("");
+
+ if(!conn->proxyuser)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ Curl_safefree(conn->proxypasswd);
+ if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
+ conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+ else
+ conn->proxypasswd = strdup("");
+
+ if(!conn->proxypasswd)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!result) {
+ conn->bits.proxy_user_passwd = TRUE; /* enable it */
+ atsign++; /* the right side of the @-letter */
+
+ proxyptr = atsign; /* now use this instead */
+ }
+ }
+
+ free(proxyuser);
+ free(proxypasswd);
+
+ if(result)
+ return result;
+ }
+
+ /* start scanning for port number at this point */
+ portptr = proxyptr;
+
+ /* detect and extract RFC6874-style IPv6-addresses */
+ if(*proxyptr == '[') {
+ char *ptr = ++proxyptr; /* advance beyond the initial bracket */
+ while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
+ ptr++;
+ if(*ptr == '%') {
+ /* There might be a zone identifier */
+ if(strncmp("%25", ptr, 3))
+ infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
+ ptr++;
+ /* Allow unresered characters as defined in RFC 3986 */
+ while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
+ (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
+ ptr++;
+ }
+ if(*ptr == ']')
+ /* yeps, it ended nicely with a bracket as well */
+ *ptr++ = 0;
+ else
+ infof(data, "Invalid IPv6 address format\n");
+ portptr = ptr;
+ /* Note that if this didn't end with a bracket, we still advanced the
+ * proxyptr first, but I can't see anything wrong with that as no host
+ * name nor a numeric can legally start with a bracket.
+ */
+ }
+
+ /* Get port number off proxy.server.com:1080 */
+ prox_portno = strchr(portptr, ':');
+ if(prox_portno) {
+ *prox_portno = 0x0; /* cut off number from host name */
+ prox_portno ++;
+ /* now set the local port number */
+ conn->port = strtol(prox_portno, NULL, 10);
+ }
+ else {
+ if(proxyptr[0]=='/')
+ /* If the first character in the proxy string is a slash, fail
+ immediately. The following code will otherwise clear the string which
+ will lead to code running as if no proxy was set! */
+ return CURLE_COULDNT_RESOLVE_PROXY;
+
+ /* without a port number after the host name, some people seem to use
+ a slash so we strip everything from the first slash */
+ atsign = strchr(proxyptr, '/');
+ if(atsign)
+ *atsign = 0x0; /* cut off path part from host name */
+
+ if(data->set.proxyport)
+ /* None given in the proxy string, then get the default one if it is
+ given */
+ conn->port = data->set.proxyport;
+ }
+
+ /* now, clone the cleaned proxy host name */
+ conn->proxy.rawalloc = strdup(proxyptr);
+ conn->proxy.name = conn->proxy.rawalloc;
+
+ if(!conn->proxy.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+/*
+ * Extract the user and password from the authentication string
+ */
+static CURLcode parse_proxy_auth(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ char proxyuser[MAX_CURL_USER_LENGTH]="";
+ char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
+
+ if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
+ strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
+ MAX_CURL_USER_LENGTH);
+ proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
+ }
+ if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
+ strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
+ MAX_CURL_PASSWORD_LENGTH);
+ proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
+ }
+
+ conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
+ if(!conn->proxyuser)
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+ if(!conn->proxypasswd)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+#endif /* CURL_DISABLE_PROXY */
+
+/*
+ * parse_url_login()
+ *
+ * Parse the login details (user name, password and options) from the URL and
+ * strip them out of the host name
+ *
+ * Inputs: data->set.use_netrc (CURLOPT_NETRC)
+ * conn->host.name
+ *
+ * Outputs: (almost :- all currently undefined)
+ * conn->bits.user_passwd - non-zero if non-default passwords exist
+ * user - non-zero length if defined
+ * passwd - non-zero length if defined
+ * options - non-zero length if defined
+ * conn->host.name - remove user name and password
+ */
+static CURLcode parse_url_login(struct SessionHandle *data,
+ struct connectdata *conn,
+ char **user, char **passwd, char **options)
+{
+ CURLcode result = CURLE_OK;
+ char *userp = NULL;
+ char *passwdp = NULL;
+ char *optionsp = NULL;
+
+ /* At this point, we're hoping all the other special cases have
+ * been taken care of, so conn->host.name is at most
+ * [user[:password][;options]]@]hostname
+ *
+ * We need somewhere to put the embedded details, so do that first.
+ */
+
+ char *ptr = strchr(conn->host.name, '@');
+ char *login = conn->host.name;
+
+ DEBUGASSERT(!**user);
+ DEBUGASSERT(!**passwd);
+ DEBUGASSERT(!**options);
+
+ if(!ptr)
+ goto out;
+
+ /* We will now try to extract the
+ * possible login information in a string like:
+ * ftp://user:password@ftp.my.site:8021/README */
+ conn->host.name = ++ptr;
+
+ /* So the hostname is sane. Only bother interpreting the
+ * results if we could care. It could still be wasted
+ * work because it might be overtaken by the programmatically
+ * set user/passwd, but doing that first adds more cases here :-(
+ */
+
+ if(data->set.use_netrc == CURL_NETRC_REQUIRED)
+ goto out;
+
+ /* We could use the login information in the URL so extract it */
+ result = parse_login_details(login, ptr - login - 1,
+ &userp, &passwdp, &optionsp);
+ if(result)
+ goto out;
+
+ if(userp) {
+ char *newname;
+
+ /* We have a user in the URL */
+ conn->bits.userpwd_in_url = TRUE;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+
+ /* Decode the user */
+ newname = curl_easy_unescape(data, userp, 0, NULL);
+ if(!newname) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ free(*user);
+ *user = newname;
+ }
+
+ if(passwdp) {
+ /* We have a password in the URL so decode it */
+ char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
+ if(!newpasswd) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ free(*passwd);
+ *passwd = newpasswd;
+ }
+
+ if(optionsp) {
+ /* We have an options list in the URL so decode it */
+ char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
+ if(!newoptions) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ free(*options);
+ *options = newoptions;
+ }
+
+
+ out:
+
+ free(userp);
+ free(passwdp);
+ free(optionsp);
+
+ return result;
+}
+
+/*
+ * parse_login_details()
+ *
+ * This is used to parse a login string for user name, password and options in
+ * the following formats:
+ *
+ * user
+ * user:password
+ * user:password;options
+ * user;options
+ * user;options:password
+ * :password
+ * :password;options
+ * ;options
+ * ;options:password
+ *
+ * Parameters:
+ *
+ * login [in] - The login string.
+ * len [in] - The length of the login string.
+ * userp [in/out] - The address where a pointer to newly allocated memory
+ * holding the user will be stored upon completion.
+ * passdwp [in/out] - The address where a pointer to newly allocated memory
+ * holding the password will be stored upon completion.
+ * optionsp [in/out] - The address where a pointer to newly allocated memory
+ * holding the options will be stored upon completion.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode parse_login_details(const char *login, const size_t len,
+ char **userp, char **passwdp,
+ char **optionsp)
+{
+ CURLcode result = CURLE_OK;
+ char *ubuf = NULL;
+ char *pbuf = NULL;
+ char *obuf = NULL;
+ const char *psep = NULL;
+ const char *osep = NULL;
+ size_t ulen;
+ size_t plen;
+ size_t olen;
+
+ /* Attempt to find the password separator */
+ if(passwdp) {
+ psep = strchr(login, ':');
+
+ /* Within the constraint of the login string */
+ if(psep >= login + len)
+ psep = NULL;
+ }
+
+ /* Attempt to find the options separator */
+ if(optionsp) {
+ osep = strchr(login, ';');
+
+ /* Within the constraint of the login string */
+ if(osep >= login + len)
+ osep = NULL;
+ }
+
+ /* Calculate the portion lengths */
+ ulen = (psep ?
+ (size_t)(osep && psep > osep ? osep - login : psep - login) :
+ (osep ? (size_t)(osep - login) : len));
+ plen = (psep ?
+ (osep && osep > psep ? (size_t)(osep - psep) :
+ (size_t)(login + len - psep)) - 1 : 0);
+ olen = (osep ?
+ (psep && psep > osep ? (size_t)(psep - osep) :
+ (size_t)(login + len - osep)) - 1 : 0);
+
+ /* Allocate the user portion buffer */
+ if(userp && ulen) {
+ ubuf = malloc(ulen + 1);
+ if(!ubuf)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Allocate the password portion buffer */
+ if(!result && passwdp && plen) {
+ pbuf = malloc(plen + 1);
+ if(!pbuf) {
+ free(ubuf);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Allocate the options portion buffer */
+ if(!result && optionsp && olen) {
+ obuf = malloc(olen + 1);
+ if(!obuf) {
+ free(pbuf);
+ free(ubuf);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ if(!result) {
+ /* Store the user portion if necessary */
+ if(ubuf) {
+ memcpy(ubuf, login, ulen);
+ ubuf[ulen] = '\0';
+ Curl_safefree(*userp);
+ *userp = ubuf;
+ }
+
+ /* Store the password portion if necessary */
+ if(pbuf) {
+ memcpy(pbuf, psep + 1, plen);
+ pbuf[plen] = '\0';
+ Curl_safefree(*passwdp);
+ *passwdp = pbuf;
+ }
+
+ /* Store the options portion if necessary */
+ if(obuf) {
+ memcpy(obuf, osep + 1, olen);
+ obuf[olen] = '\0';
+ Curl_safefree(*optionsp);
+ *optionsp = obuf;
+ }
+ }
+
+ return result;
+}
+
+/*************************************************************
+ * Figure out the remote port number and fix it in the URL
+ *
+ * No matter if we use a proxy or not, we have to figure out the remote
+ * port number of various reasons.
+ *
+ * To be able to detect port number flawlessly, we must not confuse them
+ * IPv6-specified addresses in the [0::1] style. (RFC2732)
+ *
+ * The conn->host.name is currently [user:passwd@]host[:port] where host
+ * could be a hostname, IPv4 address or IPv6 address.
+ *
+ * The port number embedded in the URL is replaced, if necessary.
+ *************************************************************/
+static CURLcode parse_remote_port(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ char *portptr;
+ char endbracket;
+
+ /* Note that at this point, the IPv6 address cannot contain any scope
+ suffix as that has already been removed in the parseurlandfillconn()
+ function */
+ if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
+ &endbracket)) &&
+ (']' == endbracket)) {
+ /* this is a RFC2732-style specified IP-address */
+ conn->bits.ipv6_ip = TRUE;
+
+ conn->host.name++; /* skip over the starting bracket */
+ portptr = strchr(conn->host.name, ']');
+ if(portptr) {
+ *portptr++ = '\0'; /* zero terminate, killing the bracket */
+ if(':' != *portptr)
+ portptr = NULL; /* no port number available */
+ }
+ }
+ else {
+#ifdef ENABLE_IPV6
+ struct in6_addr in6;
+ if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
+ /* This is a numerical IPv6 address, meaning this is a wrongly formatted
+ URL */
+ failf(data, "IPv6 numerical address used in URL without brackets");
+ return CURLE_URL_MALFORMAT;
+ }
+#endif
+
+ portptr = strrchr(conn->host.name, ':');
+ }
+
+ if(data->set.use_port && data->state.allow_port) {
+ /* if set, we use this and ignore the port possibly given in the URL */
+ conn->remote_port = (unsigned short)data->set.use_port;
+ if(portptr)
+ *portptr = '\0'; /* cut off the name there anyway - if there was a port
+ number - since the port number is to be ignored! */
+ if(conn->bits.httpproxy) {
+ /* we need to create new URL with the new port number */
+ char *url;
+ char type[12]="";
+
+ if(conn->bits.type_set)
+ snprintf(type, sizeof(type), ";type=%c",
+ data->set.prefer_ascii?'A':
+ (data->set.ftp_list_only?'D':'I'));
+
+ /*
+ * This synthesized URL isn't always right--suffixes like ;type=A are
+ * stripped off. It would be better to work directly from the original
+ * URL and simply replace the port part of it.
+ */
+ url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
+ conn->bits.ipv6_ip?"[":"", conn->host.name,
+ conn->bits.ipv6_ip?"]":"", conn->remote_port,
+ data->state.slash_removed?"/":"", data->state.path,
+ type);
+ if(!url)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
+ }
+ }
+ else if(portptr) {
+ /* no CURLOPT_PORT given, extract the one from the URL */
+
+ char *rest;
+ long port;
+
+ port=strtol(portptr+1, &rest, 10); /* Port number must be decimal */
+
+ if((port < 0) || (port > 0xffff)) {
+ /* Single unix standard says port numbers are 16 bits long */
+ failf(data, "Port number out of range");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ else if(rest != &portptr[1]) {
+ *portptr = '\0'; /* cut off the name there */
+ conn->remote_port = curlx_ultous(port);
+ }
+ else
+ /* Browser behavior adaptation. If there's a colon with no digits after,
+ just cut off the name there which makes us ignore the colon and just
+ use the default port. Firefox and Chrome both do that. */
+ *portptr = '\0';
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Override the login details from the URL with that in the CURLOPT_USERPWD
+ * option or a .netrc file, if applicable.
+ */
+static CURLcode override_login(struct SessionHandle *data,
+ struct connectdata *conn,
+ char **userp, char **passwdp, char **optionsp)
+{
+ if(data->set.str[STRING_USERNAME]) {
+ free(*userp);
+ *userp = strdup(data->set.str[STRING_USERNAME]);
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->set.str[STRING_PASSWORD]) {
+ free(*passwdp);
+ *passwdp = strdup(data->set.str[STRING_PASSWORD]);
+ if(!*passwdp)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->set.str[STRING_OPTIONS]) {
+ free(*optionsp);
+ *optionsp = strdup(data->set.str[STRING_OPTIONS]);
+ if(!*optionsp)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ conn->bits.netrc = FALSE;
+ if(data->set.use_netrc != CURL_NETRC_IGNORED) {
+ int ret = Curl_parsenetrc(conn->host.name,
+ userp, passwdp,
+ data->set.str[STRING_NETRC_FILE]);
+ if(ret > 0) {
+ infof(data, "Couldn't find host %s in the "
+ DOT_CHAR "netrc file; using defaults\n",
+ conn->host.name);
+ }
+ else if(ret < 0 ) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ /* set bits.netrc TRUE to remember that we got the name from a .netrc
+ file, so that it is safe to use even if we followed a Location: to a
+ different host or similar. */
+ conn->bits.netrc = TRUE;
+
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+ }
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Set the login details so they're available in the connection
+ */
+static CURLcode set_login(struct connectdata *conn,
+ const char *user, const char *passwd,
+ const char *options)
+{
+ CURLcode result = CURLE_OK;
+
+ /* If our protocol needs a password and we have none, use the defaults */
+ if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
+ /* Store the default user */
+ conn->user = strdup(CURL_DEFAULT_USER);
+
+ /* Store the default password */
+ if(conn->user)
+ conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
+ else
+ conn->passwd = NULL;
+
+ /* This is the default password, so DON'T set conn->bits.user_passwd */
+ }
+ else {
+ /* Store the user, zero-length if not set */
+ conn->user = strdup(user);
+
+ /* Store the password (only if user is present), zero-length if not set */
+ if(conn->user)
+ conn->passwd = strdup(passwd);
+ else
+ conn->passwd = NULL;
+ }
+
+ if(!conn->user || !conn->passwd)
+ result = CURLE_OUT_OF_MEMORY;
+
+ /* Store the options, null if not set */
+ if(!result && options[0]) {
+ conn->options = strdup(options);
+
+ if(!conn->options)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ return result;
+}
+
+/*************************************************************
+ * Resolve the address of the server or proxy
+ *************************************************************/
+static CURLcode resolve_server(struct SessionHandle *data,
+ struct connectdata *conn,
+ bool *async)
+{
+ CURLcode result=CURLE_OK;
+ long timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ /*************************************************************
+ * Resolve the name of the server or proxy
+ *************************************************************/
+ if(conn->bits.reuse)
+ /* We're reusing the connection - no need to resolve anything, and
+ fix_hostname() was called already in create_conn() for the re-use
+ case. */
+ *async = FALSE;
+
+ else {
+ /* this is a fresh connect */
+ int rc;
+ struct Curl_dns_entry *hostaddr;
+
+ /* set a pointer to the hostname we display */
+ fix_hostname(data, conn, &conn->host);
+
+#ifdef USE_UNIX_SOCKETS
+ if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ /* Unix domain sockets are local. The host gets ignored, just use the
+ * specified domain socket address. Do not cache "DNS entries". There is
+ * no DNS involved and we already have the filesystem path available */
+ const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
+
+ hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
+ if(!hostaddr)
+ result = CURLE_OUT_OF_MEMORY;
+ else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
+ hostaddr->inuse++;
+ else {
+ /* Long paths are not supported for now */
+ if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
+ failf(data, "Unix socket path too long: '%s'", path);
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ free(hostaddr);
+ hostaddr = NULL;
+ }
+ }
+ else
+#endif
+ if(!conn->proxy.name || !*conn->proxy.name) {
+ /* If not connecting via a proxy, extract the port from the URL, if it is
+ * there, thus overriding any defaults that might have been set above. */
+ conn->port = conn->remote_port; /* it is the same port */
+
+ /* Resolve target host right on */
+ rc = Curl_resolv_timeout(conn, conn->host.name, (int)conn->port,
+ &hostaddr, timeout_ms);
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+
+ else if(rc == CURLRESOLV_TIMEDOUT)
+ result = CURLE_OPERATION_TIMEDOUT;
+
+ else if(!hostaddr) {
+ failf(data, "Couldn't resolve host '%s'", conn->host.dispname);
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ /* don't return yet, we need to clean up the timeout first */
+ }
+ }
+ else {
+ /* This is a proxy that hasn't been resolved yet. */
+
+ /* IDN-fix the proxy name */
+ fix_hostname(data, conn, &conn->proxy);
+
+ /* resolve proxy */
+ rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
+ &hostaddr, timeout_ms);
+
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+
+ else if(rc == CURLRESOLV_TIMEDOUT)
+ result = CURLE_OPERATION_TIMEDOUT;
+
+ else if(!hostaddr) {
+ failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
+ result = CURLE_COULDNT_RESOLVE_PROXY;
+ /* don't return yet, we need to clean up the timeout first */
+ }
+ }
+ DEBUGASSERT(conn->dns_entry == NULL);
+ conn->dns_entry = hostaddr;
+ }
+
+ return result;
+}
+
+/*
+ * Cleanup the connection just allocated before we can move along and use the
+ * previously existing one. All relevant data is copied over and old_conn is
+ * ready for freeing once this function returns.
+ */
+static void reuse_conn(struct connectdata *old_conn,
+ struct connectdata *conn)
+{
+ free(old_conn->proxy.rawalloc);
+
+ /* free the SSL config struct from this connection struct as this was
+ allocated in vain and is targeted for destruction */
+ Curl_free_ssl_config(&old_conn->ssl_config);
+
+ conn->data = old_conn->data;
+
+ /* get the user+password information from the old_conn struct since it may
+ * be new for this request even when we re-use an existing connection */
+ conn->bits.user_passwd = old_conn->bits.user_passwd;
+ if(conn->bits.user_passwd) {
+ /* use the new user name and password though */
+ Curl_safefree(conn->user);
+ Curl_safefree(conn->passwd);
+ conn->user = old_conn->user;
+ conn->passwd = old_conn->passwd;
+ old_conn->user = NULL;
+ old_conn->passwd = NULL;
+ }
+
+ conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
+ if(conn->bits.proxy_user_passwd) {
+ /* use the new proxy user name and proxy password though */
+ Curl_safefree(conn->proxyuser);
+ Curl_safefree(conn->proxypasswd);
+ conn->proxyuser = old_conn->proxyuser;
+ conn->proxypasswd = old_conn->proxypasswd;
+ old_conn->proxyuser = NULL;
+ old_conn->proxypasswd = NULL;
+ }
+
+ /* host can change, when doing keepalive with a proxy or if the case is
+ different this time etc */
+ Curl_safefree(conn->host.rawalloc);
+ conn->host=old_conn->host;
+
+ /* persist connection info in session handle */
+ Curl_persistconninfo(conn);
+
+ /* re-use init */
+ conn->bits.reuse = TRUE; /* yes, we're re-using here */
+
+ Curl_safefree(old_conn->user);
+ Curl_safefree(old_conn->passwd);
+ Curl_safefree(old_conn->proxyuser);
+ Curl_safefree(old_conn->proxypasswd);
+ Curl_safefree(old_conn->localdev);
+
+ Curl_llist_destroy(old_conn->send_pipe, NULL);
+ Curl_llist_destroy(old_conn->recv_pipe, NULL);
+
+ old_conn->send_pipe = NULL;
+ old_conn->recv_pipe = NULL;
+
+ Curl_safefree(old_conn->master_buffer);
+}
+
+/**
+ * create_conn() sets up a new connectdata struct, or re-uses an already
+ * existing one, and resolves host name.
+ *
+ * if this function returns CURLE_OK and *async is set to TRUE, the resolve
+ * response will be coming asynchronously. If *async is FALSE, the name is
+ * already resolved.
+ *
+ * @param data The sessionhandle pointer
+ * @param in_connect is set to the next connection data pointer
+ * @param async is set TRUE when an async DNS resolution is pending
+ * @see Curl_setup_conn()
+ *
+ * *NOTE* this function assigns the conn->data pointer!
+ */
+
+static CURLcode create_conn(struct SessionHandle *data,
+ struct connectdata **in_connect,
+ bool *async)
+{
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn;
+ struct connectdata *conn_temp = NULL;
+ size_t urllen;
+ char *user = NULL;
+ char *passwd = NULL;
+ char *options = NULL;
+ bool reuse;
+ char *proxy = NULL;
+ bool prot_missing = FALSE;
+ bool no_connections_available = FALSE;
+ bool force_reuse = FALSE;
+ size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
+ size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
+
+ *async = FALSE;
+
+ /*************************************************************
+ * Check input data
+ *************************************************************/
+
+ if(!data->change.url) {
+ result = CURLE_URL_MALFORMAT;
+ goto out;
+ }
+
+ /* First, split up the current URL in parts so that we can use the
+ parts for checking against the already present connections. In order
+ to not have to modify everything at once, we allocate a temporary
+ connection data struct and fill in for comparison purposes. */
+ conn = allocate_conn(data);
+
+ if(!conn) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ /* We must set the return variable as soon as possible, so that our
+ parent can cleanup any possible allocs we may have done before
+ any failure */
+ *in_connect = conn;
+
+ /* This initing continues below, see the comment "Continue connectdata
+ * initialization here" */
+
+ /***********************************************************
+ * We need to allocate memory to store the path in. We get the size of the
+ * full URL to be sure, and we need to make it at least 256 bytes since
+ * other parts of the code will rely on this fact
+ ***********************************************************/
+#define LEAST_PATH_ALLOC 256
+ urllen=strlen(data->change.url);
+ if(urllen < LEAST_PATH_ALLOC)
+ urllen=LEAST_PATH_ALLOC;
+
+ /*
+ * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
+ * 1 - an extra terminating zero
+ * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
+ */
+
+ Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+
+ data->state.pathbuffer = malloc(urllen+2);
+ if(NULL == data->state.pathbuffer) {
+ result = CURLE_OUT_OF_MEMORY; /* really bad error */
+ goto out;
+ }
+ data->state.path = data->state.pathbuffer;
+
+ conn->host.rawalloc = malloc(urllen+2);
+ if(NULL == conn->host.rawalloc) {
+ Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ conn->host.name = conn->host.rawalloc;
+ conn->host.name[0] = 0;
+
+ user = strdup("");
+ passwd = strdup("");
+ options = strdup("");
+ if(!user || !passwd || !options) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
+ &options);
+ if(result)
+ goto out;
+
+ /*************************************************************
+ * No protocol part in URL was used, add it!
+ *************************************************************/
+ if(prot_missing) {
+ /* We're guessing prefixes here and if we're told to use a proxy or if
+ we're gonna follow a Location: later or... then we need the protocol
+ part added so that we have a valid URL. */
+ char *reurl;
+
+ reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
+
+ if(!reurl) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ data->change.url = reurl;
+ data->change.url_alloc = TRUE; /* free this later */
+ }
+
+ /*************************************************************
+ * If the protocol can't handle url query strings, then cut
+ * off the unhandable part
+ *************************************************************/
+ if((conn->given->flags&PROTOPT_NOURLQUERY)) {
+ char *path_q_sep = strchr(conn->data->state.path, '?');
+ if(path_q_sep) {
+ /* according to rfc3986, allow the query (?foo=bar)
+ also on protocols that can't handle it.
+
+ cut the string-part after '?'
+ */
+
+ /* terminate the string */
+ path_q_sep[0] = 0;
+ }
+ }
+
+ if(data->set.str[STRING_BEARER]) {
+ conn->xoauth2_bearer = strdup(data->set.str[STRING_BEARER]);
+ if(!conn->xoauth2_bearer) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ }
+
+#ifndef CURL_DISABLE_PROXY
+ /*************************************************************
+ * Extract the user and password from the authentication string
+ *************************************************************/
+ if(conn->bits.proxy_user_passwd) {
+ result = parse_proxy_auth(data, conn);
+ if(result)
+ goto out;
+ }
+
+ /*************************************************************
+ * Detect what (if any) proxy to use
+ *************************************************************/
+ if(data->set.str[STRING_PROXY]) {
+ proxy = strdup(data->set.str[STRING_PROXY]);
+ /* if global proxy is set, this is it */
+ if(NULL == proxy) {
+ failf(data, "memory shortage");
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ }
+
+ if(data->set.str[STRING_NOPROXY] &&
+ check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
+ free(proxy); /* proxy is in exception list */
+ proxy = NULL;
+ }
+ else if(!proxy)
+ proxy = detect_proxy(conn);
+
+#ifdef USE_UNIX_SOCKETS
+ if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
+ proxy = NULL;
+ }
+#endif
+
+ if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
+ free(proxy); /* Don't bother with an empty proxy string or if the
+ protocol doesn't work with network */
+ proxy = NULL;
+ }
+
+ /***********************************************************************
+ * If this is supposed to use a proxy, we need to figure out the proxy host
+ * name, proxy type and port number, so that we can re-use an existing
+ * connection that may exist registered to the same proxy host.
+ ***********************************************************************/
+ if(proxy) {
+ result = parse_proxy(data, conn, proxy);
+
+ free(proxy); /* parse_proxy copies the proxy string */
+ proxy = NULL;
+
+ if(result)
+ goto out;
+
+ if((conn->proxytype == CURLPROXY_HTTP) ||
+ (conn->proxytype == CURLPROXY_HTTP_1_0)) {
+#ifdef CURL_DISABLE_HTTP
+ /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
+ result = CURLE_UNSUPPORTED_PROTOCOL;
+ goto out;
+#else
+ /* force this connection's protocol to become HTTP if not already
+ compatible - if it isn't tunneling through */
+ if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ !conn->bits.tunnel_proxy)
+ conn->handler = &Curl_handler_http;
+
+ conn->bits.httpproxy = TRUE;
+#endif
+ }
+ else
+ conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
+ conn->bits.proxy = TRUE;
+ }
+ else {
+ /* we aren't using the proxy after all... */
+ conn->bits.proxy = FALSE;
+ conn->bits.httpproxy = FALSE;
+ conn->bits.proxy_user_passwd = FALSE;
+ conn->bits.tunnel_proxy = FALSE;
+ }
+
+#endif /* CURL_DISABLE_PROXY */
+
+ /*************************************************************
+ * If the protocol is using SSL and HTTP proxy is used, we set
+ * the tunnel_proxy bit.
+ *************************************************************/
+ if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
+ conn->bits.tunnel_proxy = TRUE;
+
+ /*************************************************************
+ * Figure out the remote port number and fix it in the URL
+ *************************************************************/
+ result = parse_remote_port(data, conn);
+ if(result)
+ goto out;
+
+ /* Check for overridden login details and set them accordingly so they
+ they are known when protocol->setup_connection is called! */
+ result = override_login(data, conn, &user, &passwd, &options);
+ if(result)
+ goto out;
+ result = set_login(conn, user, passwd, options);
+ if(result)
+ goto out;
+
+ /*************************************************************
+ * Setup internals depending on protocol. Needs to be done after
+ * we figured out what/if proxy to use.
+ *************************************************************/
+ result = setup_connection_internals(conn);
+ if(result)
+ goto out;
+
+ conn->recv[FIRSTSOCKET] = Curl_recv_plain;
+ conn->send[FIRSTSOCKET] = Curl_send_plain;
+ conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
+ conn->send[SECONDARYSOCKET] = Curl_send_plain;
+
+ /***********************************************************************
+ * file: is a special case in that it doesn't need a network connection
+ ***********************************************************************/
+#ifndef CURL_DISABLE_FILE
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ bool done;
+ /* this is supposed to be the connect function so we better at least check
+ that the file is present here! */
+ DEBUGASSERT(conn->handler->connect_it);
+ result = conn->handler->connect_it(conn, &done);
+
+ /* Setup a "faked" transfer that'll do nothing */
+ if(!result) {
+ conn->data = data;
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
+
+ ConnectionStore(data, conn);
+
+ /*
+ * Setup whatever necessary for a resumed transfer
+ */
+ result = setup_range(data);
+ if(result) {
+ DEBUGASSERT(conn->handler->done);
+ /* we ignore the return code for the protocol-specific DONE */
+ (void)conn->handler->done(conn, result, FALSE);
+ goto out;
+ }
+
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
+ -1, NULL); /* no upload */
+ }
+
+ /* since we skip do_init() */
+ do_init(conn);
+
+ goto out;
+ }
+#endif
+
+ /* Get a cloned copy of the SSL config situation stored in the
+ connection struct. But to get this going nicely, we must first make
+ sure that the strings in the master copy are pointing to the correct
+ strings in the session handle strings array!
+
+ Keep in mind that the pointers in the master copy are pointing to strings
+ that will be freed as part of the SessionHandle struct, but all cloned
+ copies will be separately allocated.
+ */
+ data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
+#ifdef USE_TLS_SRP
+ data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+#endif
+
+ if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ prune_dead_connections(data);
+
+ /*************************************************************
+ * Check the current list of connections to see if we can
+ * re-use an already existing one or if we have to create a
+ * new one.
+ *************************************************************/
+
+ /* reuse_fresh is TRUE if we are told to use a new connection by force, but
+ we only acknowledge this option if this is not a re-used connection
+ already (which happens due to follow-location or during a HTTP
+ authentication phase). */
+ if(data->set.reuse_fresh && !data->state.this_is_a_follow)
+ reuse = FALSE;
+ else
+ reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse);
+
+ /* If we found a reusable connection, we may still want to
+ open a new connection if we are pipelining. */
+ if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
+ size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
+ if(pipelen > 0) {
+ infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
+ conn_temp->connection_id, pipelen);
+
+ if(conn_temp->bundle->num_connections < max_host_connections &&
+ data->state.conn_cache->num_connections < max_total_connections) {
+ /* We want a new connection anyway */
+ reuse = FALSE;
+
+ infof(data, "We can reuse, but we want a new connection anyway\n");
+ }
+ }
+ }
+
+ if(reuse) {
+ /*
+ * We already have a connection for this, we got the former connection
+ * in the conn_temp variable and thus we need to cleanup the one we
+ * just allocated before we can move along and use the previously
+ * existing one.
+ */
+ conn_temp->inuse = TRUE; /* mark this as being in use so that no other
+ handle in a multi stack may nick it */
+ reuse_conn(conn, conn_temp);
+ free(conn); /* we don't need this anymore */
+ conn = conn_temp;
+ *in_connect = conn;
+
+ /* set a pointer to the hostname we display */
+ fix_hostname(data, conn, &conn->host);
+
+ infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
+ conn->connection_id,
+ conn->bits.proxy?"proxy":"host",
+ conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
+ }
+ else {
+ /* We have decided that we want a new connection. However, we may not
+ be able to do that if we have reached the limit of how many
+ connections we are allowed to open. */
+ struct connectbundle *bundle;
+
+ bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
+ if(max_host_connections > 0 && bundle &&
+ (bundle->num_connections >= max_host_connections)) {
+ struct connectdata *conn_candidate;
+
+ /* The bundle is full. Let's see if we can kill a connection. */
+ conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle);
+
+ if(conn_candidate) {
+ /* Set the connection's owner correctly, then kill it */
+ conn_candidate->data = data;
+ (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ }
+ else
+ no_connections_available = TRUE;
+ }
+
+ if(max_total_connections > 0 &&
+ (data->state.conn_cache->num_connections >= max_total_connections)) {
+ struct connectdata *conn_candidate;
+
+ /* The cache is full. Let's see if we can kill a connection. */
+ conn_candidate = find_oldest_idle_connection(data);
+
+ if(conn_candidate) {
+ /* Set the connection's owner correctly, then kill it */
+ conn_candidate->data = data;
+ (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ }
+ else
+ no_connections_available = TRUE;
+ }
+
+
+ if(no_connections_available) {
+ infof(data, "No connections available.\n");
+
+ conn_free(conn);
+ *in_connect = NULL;
+
+ result = CURLE_NO_CONNECTION_AVAILABLE;
+ goto out;
+ }
+ else {
+ /*
+ * This is a brand new connection, so let's store it in the connection
+ * cache of ours!
+ */
+ ConnectionStore(data, conn);
+ }
+
+#if defined(USE_NTLM)
+ /* If NTLM is requested in a part of this connection, make sure we don't
+ assume the state is fine as this is a fresh connection and NTLM is
+ connection based. */
+ if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+ data->state.authhost.done) {
+ infof(data, "NTLM picked AND auth done set, clear picked!\n");
+ data->state.authhost.picked = CURLAUTH_NONE;
+ }
+
+ if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+ data->state.authproxy.done) {
+ infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
+ data->state.authproxy.picked = CURLAUTH_NONE;
+ }
+#endif
+ }
+
+ /* Mark the connection as used */
+ conn->inuse = TRUE;
+
+ /* Setup and init stuff before DO starts, in preparing for the transfer. */
+ do_init(conn);
+
+ /*
+ * Setup whatever necessary for a resumed transfer
+ */
+ result = setup_range(data);
+ if(result)
+ goto out;
+
+ /* Continue connectdata initialization here. */
+
+ /*
+ * Inherit the proper values from the urldata struct AFTER we have arranged
+ * the persistent connection stuff
+ */
+ conn->fread_func = data->set.fread_func;
+ conn->fread_in = data->set.in;
+ conn->seek_func = data->set.seek_func;
+ conn->seek_client = data->set.seek_client;
+
+ /*************************************************************
+ * Resolve the address of the server or proxy
+ *************************************************************/
+ result = resolve_server(data, conn, async);
+
+ out:
+
+ free(options);
+ free(passwd);
+ free(user);
+ free(proxy);
+ return result;
+}
+
+/* Curl_setup_conn() is called after the name resolve initiated in
+ * create_conn() is all done.
+ *
+ * Curl_setup_conn() also handles reused connections
+ *
+ * conn->data MUST already have been setup fine (in create_conn)
+ */
+
+CURL_STATIC CURLcode Curl_setup_conn(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ Curl_pgrsTime(data, TIMER_NAMELOOKUP);
+
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ /* nothing to setup when not using a network */
+ *protocol_done = TRUE;
+ return result;
+ }
+ *protocol_done = FALSE; /* default to not done */
+
+ /* set proxy_connect_closed to false unconditionally already here since it
+ is used strictly to provide extra information to a parent function in the
+ case of proxy CONNECT failures and we must make sure we don't have it
+ lingering set from a previous invoke */
+ conn->bits.proxy_connect_closed = FALSE;
+
+ /*
+ * Set user-agent. Used for HTTP, but since we can attempt to tunnel
+ * basically anything through a http proxy we can't limit this based on
+ * protocol.
+ */
+ if(data->set.str[STRING_USERAGENT]) {
+ Curl_safefree(conn->allocptr.uagent);
+ conn->allocptr.uagent =
+ aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
+ if(!conn->allocptr.uagent)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ data->req.headerbytecount = 0;
+
+#ifdef CURL_DO_LINEEND_CONV
+ data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
+#endif /* CURL_DO_LINEEND_CONV */
+
+ /* set start time here for timeout purposes in the connect procedure, it
+ is later set again for the progress meter purpose */
+ conn->now = Curl_tvnow();
+
+ if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
+ conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
+ result = Curl_connecthost(conn, conn->dns_entry);
+ if(result)
+ return result;
+ }
+ else {
+ Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
+ *protocol_done = TRUE;
+ Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
+ Curl_verboseconnect(conn);
+ }
+
+ conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
+ set this here perhaps a second time */
+
+#ifdef __EMX__
+ /*
+ * This check is quite a hack. We're calling _fsetmode to fix the problem
+ * with fwrite converting newline characters (you get mangled text files,
+ * and corrupted binary files when you download to stdout and redirect it to
+ * a file).
+ */
+
+ if((data->set.out)->_handle == NULL) {
+ _fsetmode(stdout, "b");
+ }
+#endif
+
+ return result;
+}
+
+CURL_STATIC CURLcode Curl_connect(struct SessionHandle *data,
+ struct connectdata **in_connect,
+ bool *asyncp,
+ bool *protocol_done)
+{
+ CURLcode result;
+
+ *asyncp = FALSE; /* assume synchronous resolves by default */
+
+ /* call the stuff that needs to be called */
+ result = create_conn(data, in_connect, asyncp);
+
+ if(!result) {
+ /* no error */
+ if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size)
+ /* pipelining */
+ *protocol_done = TRUE;
+ else if(!*asyncp) {
+ /* DNS resolution is done: that's either because this is a reused
+ connection, in which case DNS was unnecessary, or because DNS
+ really did finish already (synch resolver/fast async resolve) */
+ result = Curl_setup_conn(*in_connect, protocol_done);
+ }
+ }
+
+ if(result == CURLE_NO_CONNECTION_AVAILABLE) {
+ *in_connect = NULL;
+ return result;
+ }
+
+ if(result && *in_connect) {
+ /* We're not allowed to return failure with memory left allocated
+ in the connectdata struct, free those here */
+ Curl_disconnect(*in_connect, FALSE); /* close the connection */
+ *in_connect = NULL; /* return a NULL */
+ }
+
+ return result;
+}
+
+CURL_STATIC CURLcode Curl_done(struct connectdata **connp,
+ CURLcode status, /* an error if this is called after an
+ error was detected */
+ bool premature)
+{
+ CURLcode result;
+ struct connectdata *conn;
+ struct SessionHandle *data;
+
+ DEBUGASSERT(*connp);
+
+ conn = *connp;
+ data = conn->data;
+
+ if(conn->bits.done)
+ /* Stop if Curl_done() has already been called */
+ return CURLE_OK;
+
+ Curl_getoff_all_pipelines(data, conn);
+
+ if((conn->send_pipe->size + conn->recv_pipe->size != 0 &&
+ !data->set.reuse_forbid &&
+ !conn->bits.close))
+ /* Stop if pipeline is not empty and we do not have to close
+ connection. */
+ return CURLE_OK;
+
+ conn->bits.done = TRUE; /* called just now! */
+
+ /* Cleanup possible redirect junk */
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+ free(data->req.location);
+ data->req.location = NULL;
+
+ Curl_resolver_cancel(conn);
+
+ if(conn->dns_entry) {
+ Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
+ conn->dns_entry = NULL;
+ }
+
+ switch(status) {
+ case CURLE_ABORTED_BY_CALLBACK:
+ case CURLE_READ_ERROR:
+ case CURLE_WRITE_ERROR:
+ /* When we're aborted due to a callback return code it basically have to
+ be counted as premature as there is trouble ahead if we don't. We have
+ many callbacks and protocols work differently, we could potentially do
+ this more fine-grained in the future. */
+ premature = TRUE;
+ default:
+ break;
+ }
+
+ /* this calls the protocol-specific function pointer previously set */
+ if(conn->handler->done)
+ result = conn->handler->done(conn, status, premature);
+ else
+ result = status;
+
+ if(!result && Curl_pgrsDone(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+
+ /* if the transfer was completed in a paused state there can be buffered
+ data left to write and then kill */
+ free(data->state.tempwrite);
+ data->state.tempwrite = NULL;
+
+ /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
+ forced us to close this connection. This is ignored for requests taking
+ place in a NTLM authentication handshake
+
+ if conn->bits.close is TRUE, it means that the connection should be
+ closed in spite of all our efforts to be nice, due to protocol
+ restrictions in our or the server's end
+
+ if premature is TRUE, it means this connection was said to be DONE before
+ the entire request operation is complete and thus we can't know in what
+ state it is for re-using, so we're forced to close it. In a perfect world
+ we can add code that keep track of if we really must close it here or not,
+ but currently we have no such detail knowledge.
+ */
+
+ if((data->set.reuse_forbid
+#if defined(USE_NTLM)
+ && !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
+ conn->proxyntlm.state == NTLMSTATE_TYPE2)
+#endif
+ ) || conn->bits.close || premature) {
+ CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
+
+ /* If we had an error already, make sure we return that one. But
+ if we got a new error, return that. */
+ if(!result && res2)
+ result = res2;
+ }
+ else {
+ /* the connection is no longer in use */
+ if(ConnectionDone(data, conn)) {
+ /* remember the most recently used connection */
+ data->state.lastconnect = conn;
+
+ infof(data, "Connection #%ld to host %s left intact\n",
+ conn->connection_id,
+ conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
+ }
+ else
+ data->state.lastconnect = NULL;
+ }
+
+ *connp = NULL; /* to make the caller of this function better detect that
+ this was either closed or handed over to the connection
+ cache here, and therefore cannot be used from this point on
+ */
+ Curl_free_request_state(data);
+
+ return result;
+}
+
+/*
+ * do_init() inits the readwrite session. This is inited each time (in the DO
+ * function before the protocol-specific DO functions are invoked) for a
+ * transfer, sometimes multiple times on the same SessionHandle. Make sure
+ * nothing in here depends on stuff that are setup dynamically for the
+ * transfer.
+ */
+
+static CURLcode do_init(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+
+ conn->bits.done = FALSE; /* Curl_done() is not called yet */
+ conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
+ data->state.expect100header = FALSE;
+
+ if(data->set.opt_no_body)
+ /* in HTTP lingo, no body means using the HEAD request... */
+ data->set.httpreq = HTTPREQ_HEAD;
+ else if(HTTPREQ_HEAD == data->set.httpreq)
+ /* ... but if unset there really is no perfect method that is the
+ "opposite" of HEAD but in reality most people probably think GET
+ then. The important thing is that we can't let it remain HEAD if the
+ opt_no_body is set FALSE since then we'll behave wrong when getting
+ HTTP. */
+ data->set.httpreq = HTTPREQ_GET;
+
+ k->start = Curl_tvnow(); /* start time */
+ k->now = k->start; /* current time is now */
+ k->header = TRUE; /* assume header */
+
+ k->bytecount = 0;
+
+ k->buf = data->state.buffer;
+ k->uploadbuf = data->state.uploadbuffer;
+ k->hbufp = data->state.headerbuff;
+ k->ignorebody=FALSE;
+
+ Curl_speedinit(data);
+
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+
+ return CURLE_OK;
+}
+
+/*
+ * do_complete is called when the DO actions are complete.
+ *
+ * We init chunking and trailer bits to their default values here immediately
+ * before receiving any header data for the current request in the pipeline.
+ */
+static void do_complete(struct connectdata *conn)
+{
+ conn->data->req.chunk=FALSE;
+ conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
+ conn->sockfd:conn->writesockfd)+1;
+ Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
+}
+
+CURL_STATIC CURLcode Curl_do(struct connectdata **connp, bool *done)
+{
+ CURLcode result=CURLE_OK;
+ struct connectdata *conn = *connp;
+ struct SessionHandle *data = conn->data;
+
+ if(conn->handler->do_it) {
+ /* generic protocol-specific function pointer set in curl_connect() */
+ result = conn->handler->do_it(conn, done);
+
+ /* This was formerly done in transfer.c, but we better do it here */
+ if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
+ /*
+ * If the connection is using an easy handle, call reconnect
+ * to re-establish the connection. Otherwise, let the multi logic
+ * figure out how to re-establish the connection.
+ */
+ if(!data->multi) {
+ result = Curl_reconnect_request(connp);
+
+ if(!result) {
+ /* ... finally back to actually retry the DO phase */
+ conn = *connp; /* re-assign conn since Curl_reconnect_request
+ creates a new connection */
+ result = conn->handler->do_it(conn, done);
+ }
+ }
+ else
+ return result;
+ }
+
+ if(!result && *done)
+ /* do_complete must be called after the protocol-specific DO function */
+ do_complete(conn);
+ }
+ return result;
+}
+
+/*
+ * Curl_do_more() is called during the DO_MORE multi state. It is basically a
+ * second stage DO state which (wrongly) was introduced to support FTP's
+ * second connection.
+ *
+ * TODO: A future libcurl should be able to work away this state.
+ *
+ * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
+ * DOING state there's more work to do!
+ */
+
+CURL_STATIC CURLcode Curl_do_more(struct connectdata *conn, int *complete)
+{
+ CURLcode result=CURLE_OK;
+
+ *complete = 0;
+
+ if(conn->handler->do_more)
+ result = conn->handler->do_more(conn, complete);
+
+ if(!result && (*complete == 1))
+ /* do_complete must be called after the protocol-specific DO function */
+ do_complete(conn);
+
+ return result;
+}
diff --git a/libcurl/src/lib/url.h b/libcurl/src/lib/url.h
new file mode 100644
index 0000000..d36a479
--- /dev/null
+++ b/libcurl/src/lib/url.h
@@ -0,0 +1,82 @@
+#ifndef HEADER_CURL_URL_H
+#define HEADER_CURL_URL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * Prototypes for library-wide functions provided by url.c
+ */
+
+CURL_STATIC CURLcode Curl_open(struct SessionHandle **curl);
+CURL_STATIC CURLcode Curl_init_userdefined(struct UserDefined *set);
+CURL_STATIC CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
+ va_list arg);
+CURL_STATIC CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src);
+CURL_STATIC void Curl_freeset(struct SessionHandle * data);
+CURL_STATIC CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
+CURL_STATIC CURLcode Curl_connect(struct SessionHandle *, struct connectdata **,
+ bool *async, bool *protocol_connect);
+CURL_STATIC CURLcode Curl_do(struct connectdata **, bool *done);
+CURL_STATIC CURLcode Curl_do_more(struct connectdata *, int *completed);
+CURL_STATIC CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
+CURL_STATIC CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
+CURL_STATIC CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
+CURL_STATIC CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
+CURL_STATIC CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
+CURL_STATIC CURLcode Curl_setup_conn(struct connectdata *conn,
+ bool *protocol_done);
+CURL_STATIC void Curl_free_request_state(struct SessionHandle *data);
+
+CURL_STATIC int Curl_protocol_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+CURL_STATIC int Curl_doing_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+CURL_STATIC bool Curl_isPipeliningEnabled(const struct SessionHandle *handle);
+CURL_STATIC CURLcode Curl_addHandleToPipeline(struct SessionHandle *handle,
+ struct curl_llist *pipeline);
+CURL_STATIC int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
+ struct curl_llist *pipeline);
+/* remove the specified connection from all (possible) pipelines and related
+ queues */
+CURL_STATIC void Curl_getoff_all_pipelines(struct SessionHandle *data,
+ struct connectdata *conn);
+
+CURL_STATIC void Curl_close_connections(struct SessionHandle *data);
+
+#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
+#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
+ service */
+
+CURL_STATIC CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+#define Curl_verboseconnect(x) Curl_nop_stmt
+#else
+CURL_STATIC void Curl_verboseconnect(struct connectdata *conn);
+#endif
+
+
+#endif /* HEADER_CURL_URL_H */
diff --git a/libcurl/src/lib/urldata.h b/libcurl/src/lib/urldata.h
new file mode 100644
index 0000000..b1b1a67
--- /dev/null
+++ b/libcurl/src/lib/urldata.h
@@ -0,0 +1,1695 @@
+#ifndef HEADER_CURL_URLDATA_H
+#define HEADER_CURL_URLDATA_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This file is for lib internal stuff */
+
+#include "curl_setup.h"
+
+#define PORT_FTP 21
+#define PORT_FTPS 990
+#define PORT_TELNET 23
+#define PORT_HTTP 80
+#define PORT_HTTPS 443
+#define PORT_DICT 2628
+#define PORT_LDAP 389
+#define PORT_LDAPS 636
+#define PORT_TFTP 69
+#define PORT_SSH 22
+#define PORT_IMAP 143
+#define PORT_IMAPS 993
+#define PORT_POP3 110
+#define PORT_POP3S 995
+#define PORT_SMB 445
+#define PORT_SMBS 445
+#define PORT_SMTP 25
+#define PORT_SMTPS 465 /* sometimes called SSMTP */
+#define PORT_RTSP 554
+#define PORT_RTMP 1935
+#define PORT_RTMPT PORT_HTTP
+#define PORT_RTMPS PORT_HTTPS
+#define PORT_GOPHER 70
+
+#define DICT_MATCH "/MATCH:"
+#define DICT_MATCH2 "/M:"
+#define DICT_MATCH3 "/FIND:"
+#define DICT_DEFINE "/DEFINE:"
+#define DICT_DEFINE2 "/D:"
+#define DICT_DEFINE3 "/LOOKUP:"
+
+#define CURL_DEFAULT_USER "anonymous"
+#define CURL_DEFAULT_PASSWORD "ftp@example.com"
+
+/* Convenience defines for checking protocols or their SSL based version. Each
+ protocol handler should only ever have a single CURLPROTO_ in its protocol
+ field. */
+#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS)
+#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS)
+#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S)
+#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS)
+#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS)
+
+#define DEFAULT_CONNCACHE_SIZE 5
+
+/* length of longest IPv6 address string including the trailing null */
+#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")
+
+/* Default FTP/IMAP etc response timeout in milliseconds.
+ Symbian OS panics when given a timeout much greater than 1/2 hour.
+*/
+#define RESP_TIMEOUT (1800*1000)
+
+#include "cookie.h"
+#include "formdata.h"
+
+#ifdef USE_OPENSSL
+#include <openssl/ssl.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
+#endif /* USE_OPENSSL */
+
+#ifdef USE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+#ifdef USE_POLARSSL
+#include <polarssl/ssl.h>
+#include <polarssl/version.h>
+#if POLARSSL_VERSION_NUMBER<0x01010000
+#include <polarssl/havege.h>
+#else
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
+#endif /* USE_POLARSSL */
+
+#ifdef USE_CYASSL
+#undef OCSP_REQUEST /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
+#undef OCSP_RESPONSE /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
+#include <cyassl/openssl/ssl.h>
+#endif
+
+#ifdef USE_NSS
+#include <nspr.h>
+#include <pk11pub.h>
+#endif
+
+#ifdef USE_GSKIT
+#include <gskssl.h>
+#endif
+
+#ifdef USE_AXTLS
+#include <axTLS/config.h>
+#include <axTLS/ssl.h>
+#undef malloc
+#undef calloc
+#undef realloc
+#endif /* USE_AXTLS */
+
+#ifdef USE_SCHANNEL
+#include "curl_sspi.h"
+#include <schnlsp.h>
+#include <schannel.h>
+#endif
+
+#ifdef USE_DARWINSSL
+#include <Security/Security.h>
+/* For some reason, when building for iOS, the omnibus header above does
+ * not include SecureTransport.h as of iOS SDK 5.1. */
+#include <Security/SecureTransport.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "timeval.h"
+
+#ifdef HAVE_ZLIB_H
+#include <zlib.h> /* for content-encoding */
+#ifdef __SYMBIAN32__
+/* zlib pollutes the namespace with this definition */
+#undef WIN32
+#endif
+#endif
+
+#include <curl/curl.h>
+
+#include "http_chunks.h" /* for the structs and enum stuff */
+#include "hostip.h"
+#include "hash.h"
+#include "splay.h"
+
+#include "imap.h"
+#include "pop3.h"
+#include "smtp.h"
+#include "ftp.h"
+#include "file.h"
+#include "ssh.h"
+#include "http.h"
+#include "rtsp.h"
+#include "smb.h"
+#include "wildcard.h"
+#include "multihandle.h"
+
+#ifdef HAVE_GSSAPI
+# ifdef HAVE_GSSGNU
+# include <gss.h>
+# elif defined HAVE_GSSMIT
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_generic.h>
+# else
+# include <gssapi.h>
+# endif
+#endif
+
+#ifdef HAVE_LIBSSH2_H
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+#endif /* HAVE_LIBSSH2_H */
+
+/* Download buffer size, keep it fairly big for speed reasons */
+#undef BUFSIZE
+#define BUFSIZE CURL_MAX_WRITE_SIZE
+
+/* Initial size of the buffer to store headers in, it'll be enlarged in case
+ of need. */
+#define HEADERSIZE 256
+
+#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
+
+/* Some convenience macros to get the larger/smaller value out of two given.
+ We prefix with CURL to prevent name collisions. */
+#define CURLMAX(x,y) ((x)>(y)?(x):(y))
+#define CURLMIN(x,y) ((x)<(y)?(x):(y))
+
+
+#ifdef HAVE_GSSAPI
+/* Types needed for krb5-ftp connections */
+struct krb5buffer {
+ void *data;
+ size_t size;
+ size_t index;
+ int eof_flag;
+};
+
+enum protection_level {
+ PROT_NONE, /* first in list */
+ PROT_CLEAR,
+ PROT_SAFE,
+ PROT_CONFIDENTIAL,
+ PROT_PRIVATE,
+ PROT_CMD,
+ PROT_LAST /* last in list */
+};
+#endif
+
+#ifdef USE_SCHANNEL
+/* Structs to store Schannel handles */
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+ bool cached;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+#endif
+
+/* enum for the nonblocking SSL connection state machine */
+typedef enum {
+ ssl_connect_1,
+ ssl_connect_2,
+ ssl_connect_2_reading,
+ ssl_connect_2_writing,
+ ssl_connect_3,
+ ssl_connect_done
+} ssl_connect_state;
+
+typedef enum {
+ ssl_connection_none,
+ ssl_connection_negotiating,
+ ssl_connection_complete
+} ssl_connection_state;
+
+/* struct for data related to each SSL connection */
+struct ssl_connect_data {
+ /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
+ but at least asked to or meaning to use it. See 'state' for the exact
+ current state of the connection. */
+ bool use;
+ ssl_connection_state state;
+#ifdef USE_OPENSSL
+ /* these ones requires specific SSL-types */
+ SSL_CTX* ctx;
+ SSL* handle;
+ X509* server_cert;
+ ssl_connect_state connecting_state;
+#endif /* USE_OPENSSL */
+#ifdef USE_GNUTLS
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t cred;
+#ifdef USE_TLS_SRP
+ gnutls_srp_client_credentials_t srp_client_cred;
+#endif
+ ssl_connect_state connecting_state;
+#endif /* USE_GNUTLS */
+#ifdef USE_POLARSSL
+ ctr_drbg_context ctr_drbg;
+ entropy_context entropy;
+ ssl_context ssl;
+ ssl_session ssn;
+ int server_fd;
+ x509_crt cacert;
+ x509_crt clicert;
+ x509_crl crl;
+ rsa_context rsa;
+ ssl_connect_state connecting_state;
+#endif /* USE_POLARSSL */
+#ifdef USE_CYASSL
+ SSL_CTX* ctx;
+ SSL* handle;
+ ssl_connect_state connecting_state;
+#endif /* USE_CYASSL */
+#ifdef USE_NSS
+ PRFileDesc *handle;
+ char *client_nickname;
+ struct SessionHandle *data;
+ struct curl_llist *obj_list;
+ PK11GenericObject *obj_clicert;
+ ssl_connect_state connecting_state;
+#endif /* USE_NSS */
+#ifdef USE_GSKIT
+ gsk_handle handle;
+ int iocport;
+ ssl_connect_state connecting_state;
+#endif
+#ifdef USE_AXTLS
+ SSL_CTX* ssl_ctx;
+ SSL* ssl;
+ ssl_connect_state connecting_state;
+#endif /* USE_AXTLS */
+#ifdef USE_SCHANNEL
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ ssl_connect_state connecting_state;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ unsigned long req_flags, ret_flags;
+#endif /* USE_SCHANNEL */
+#ifdef USE_DARWINSSL
+ SSLContextRef ssl_ctx;
+ curl_socket_t ssl_sockfd;
+ ssl_connect_state connecting_state;
+ bool ssl_direction; /* true if writing, false if reading */
+ size_t ssl_write_buffered_length;
+#endif /* USE_DARWINSSL */
+};
+
+struct ssl_config_data {
+ long version; /* what version the client wants to use */
+ long certverifyresult; /* result from the certificate verification */
+
+ bool verifypeer; /* set TRUE if this is desired */
+ bool verifyhost; /* set TRUE if CN/SAN must match hostname */
+ bool verifystatus; /* set TRUE if certificate status must be checked */
+ char *CApath; /* certificate dir (doesn't work on windows) */
+ char *CAfile; /* certificate to verify peer against */
+ const char *CRLfile; /* CRL to check certificate revocation */
+ const char *issuercert;/* optional issuer certificate filename */
+ char *random_file; /* path to file containing "random" data */
+ char *egdsocket; /* path to file containing the EGD daemon socket */
+ char *cipher_list; /* list of ciphers to use */
+ size_t max_ssl_sessions; /* SSL session id cache size */
+ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
+ void *fsslctxp; /* parameter for call back */
+ bool sessionid; /* cache session IDs or not */
+ bool certinfo; /* gather lots of certificate info */
+ bool falsestart;
+
+#ifdef USE_TLS_SRP
+ char *username; /* TLS username (for, e.g., SRP) */
+ char *password; /* TLS password (for, e.g., SRP) */
+ enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
+#endif
+};
+
+/* information stored about one single SSL session */
+struct curl_ssl_session {
+ char *name; /* host name for which this ID was used */
+ void *sessionid; /* as returned from the SSL layer */
+ size_t idsize; /* if known, otherwise 0 */
+ long age; /* just a number, the higher the more recent */
+ int remote_port; /* remote port to connect to */
+ struct ssl_config_data ssl_config; /* setup for this session */
+};
+
+/* Struct used for Digest challenge-response authentication */
+struct digestdata {
+#if defined(USE_WINDOWS_SSPI)
+ BYTE *input_token;
+ size_t input_token_len;
+#else
+ char *nonce;
+ char *cnonce;
+ char *realm;
+ int algo;
+ bool stale; /* set true for re-negotiation */
+ char *opaque;
+ char *qop;
+ char *algorithm;
+ int nc; /* nounce count */
+#endif
+};
+
+typedef enum {
+ NTLMSTATE_NONE,
+ NTLMSTATE_TYPE1,
+ NTLMSTATE_TYPE2,
+ NTLMSTATE_TYPE3,
+ NTLMSTATE_LAST
+} curlntlm;
+
+#ifdef USE_WINDOWS_SSPI
+#include "curl_sspi.h"
+#endif
+
+#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
+#include <iconv.h>
+#endif
+
+/* Struct used for GSSAPI (Kerberos V5) authentication */
+#if defined(USE_KERBEROS5)
+struct kerberos5data {
+#if defined(USE_WINDOWS_SSPI)
+ CredHandle *credentials;
+ CtxtHandle *context;
+ TCHAR *spn;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ size_t token_max;
+ BYTE *output_token;
+#else
+ gss_ctx_id_t context;
+ gss_name_t spn;
+#endif
+};
+#endif
+
+/* Struct used for NTLM challenge-response authentication */
+#if defined(USE_NTLM)
+struct ntlmdata {
+ curlntlm state;
+#ifdef USE_WINDOWS_SSPI
+ CredHandle *credentials;
+ CtxtHandle *context;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ size_t token_max;
+ BYTE *output_token;
+ BYTE *input_token;
+ size_t input_token_len;
+#else
+ unsigned int flags;
+ unsigned char nonce[8];
+ void* target_info; /* TargetInfo received in the ntlm type-2 message */
+ unsigned int target_info_len;
+#endif
+};
+#endif
+
+#ifdef USE_SPNEGO
+struct negotiatedata {
+ /* When doing Negotiate (SPNEGO) auth, we first need to send a token
+ and then validate the received one. */
+ enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state;
+#ifdef HAVE_GSSAPI
+ OM_uint32 status;
+ gss_ctx_id_t context;
+ gss_name_t server_name;
+ gss_buffer_desc output_token;
+#else
+#ifdef USE_WINDOWS_SSPI
+ DWORD status;
+ CredHandle *credentials;
+ CtxtHandle *context;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ TCHAR *server_name;
+ size_t token_max;
+ BYTE *output_token;
+ size_t output_token_length;
+#endif
+#endif
+};
+#endif
+
+
+/*
+ * Boolean values that concerns this connection.
+ */
+struct ConnectBits {
+ /* always modify bits.close with the connclose() and connkeep() macros! */
+ bool close; /* if set, we close the connection after this request */
+ bool reuse; /* if set, this is a re-used connection */
+ bool proxy; /* if set, this transfer is done through a proxy - any type */
+ bool httpproxy; /* if set, this transfer is done through a http proxy */
+ bool user_passwd; /* do we use user+password for this connection? */
+ bool proxy_user_passwd; /* user+password for the proxy? */
+ bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
+ IP address */
+ bool ipv6; /* we communicate with a site using an IPv6 address */
+
+ bool do_more; /* this is set TRUE if the ->curl_do_more() function is
+ supposed to be called, after ->curl_do() */
+ bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
+ the first time on the first connect function call */
+ bool protoconnstart;/* the protocol layer has STARTED its operation after
+ the TCP layer connect */
+
+ bool retry; /* this connection is about to get closed and then
+ re-attempted at another connection. */
+ bool tunnel_proxy; /* if CONNECT is used to "tunnel" through the proxy.
+ This is implicit when SSL-protocols are used through
+ proxies, but can also be enabled explicitly by
+ apps */
+ bool authneg; /* TRUE when the auth phase has started, which means
+ that we are creating a request with an auth header,
+ but it is not the final request in the auth
+ negotiation. */
+ bool rewindaftersend;/* TRUE when the sending couldn't be stopped even
+ though it will be discarded. When the whole send
+ operation is done, we must call the data rewind
+ callback. */
+ bool ftp_use_epsv; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out
+ EPSV doesn't work we disable it for the forthcoming
+ requests */
+
+ bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
+ EPRT doesn't work we disable it for the forthcoming
+ requests */
+ bool netrc; /* name+password provided by netrc */
+ bool userpwd_in_url; /* name+password found in url */
+
+ bool done; /* set to FALSE when Curl_do() is called and set to TRUE
+ when Curl_done() is called, to prevent Curl_done() to
+ get invoked twice when the multi interface is
+ used. */
+ bool stream_was_rewound; /* Indicates that the stream was rewound after a
+ request read past the end of its response byte
+ boundary */
+ bool proxy_connect_closed; /* set true if a proxy disconnected the
+ connection in a CONNECT request with auth, so
+ that libcurl should reconnect and continue. */
+ bool bound; /* set true if bind() has already been done on this socket/
+ connection */
+ bool type_set; /* type= was used in the URL */
+};
+
+struct hostname {
+ char *rawalloc; /* allocated "raw" version of the name */
+ char *encalloc; /* allocated IDN-encoded version of the name */
+ char *name; /* name to use internally, might be encoded, might be raw */
+ const char *dispname; /* name to display, as 'name' might be encoded */
+};
+
+/*
+ * Flags on the keepon member of the Curl_transfer_keeper
+ */
+
+#define KEEP_NONE 0
+#define KEEP_RECV (1<<0) /* there is or may be data to read */
+#define KEEP_SEND (1<<1) /* there is or may be data to write */
+#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there
+ might still be data to read */
+#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there
+ might still be data to write */
+#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */
+#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */
+
+#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
+#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
+
+
+#ifdef HAVE_LIBZ
+typedef enum {
+ ZLIB_UNINIT, /* uninitialized */
+ ZLIB_INIT, /* initialized */
+ ZLIB_GZIP_HEADER, /* reading gzip header */
+ ZLIB_GZIP_INFLATING, /* inflating gzip stream */
+ ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
+} zlibInitState;
+#endif
+
+#ifdef CURLRES_ASYNCH
+struct Curl_async {
+ char *hostname;
+ int port;
+ struct Curl_dns_entry *dns;
+ bool done; /* set TRUE when the lookup is complete */
+ int status; /* if done is TRUE, this is the status from the callback */
+ void *os_specific; /* 'struct thread_data' for Windows */
+};
+#endif
+
+#define FIRSTSOCKET 0
+#define SECONDARYSOCKET 1
+
+/* These function pointer types are here only to allow easier typecasting
+ within the source when we need to cast between data pointers (such as NULL)
+ and function pointers. */
+typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
+typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
+
+enum expect100 {
+ EXP100_SEND_DATA, /* enough waiting, just send the body now */
+ EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
+ EXP100_SENDING_REQUEST, /* still sending the request but will wait for
+ the 100 header once done with the request */
+ EXP100_FAILED /* used on 417 Expectation Failed */
+};
+
+enum upgrade101 {
+ UPGR101_INIT, /* default state */
+ UPGR101_REQUESTED, /* upgrade requested */
+ UPGR101_RECEIVED, /* response received */
+ UPGR101_WORKING /* talking upgraded protocol */
+};
+
+/*
+ * Request specific data in the easy handle (SessionHandle). Previously,
+ * these members were on the connectdata struct but since a conn struct may
+ * now be shared between different SessionHandles, we store connection-specific
+ * data here. This struct only keeps stuff that's interesting for *this*
+ * request, as it will be cleared between multiple ones
+ */
+struct SingleRequest {
+ curl_off_t size; /* -1 if unknown at this point */
+ curl_off_t *bytecountp; /* return number of bytes read or NULL */
+
+ curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
+ -1 means unlimited */
+ curl_off_t *writebytecountp; /* return number of bytes written or NULL */
+
+ curl_off_t bytecount; /* total number of bytes read */
+ curl_off_t writebytecount; /* number of bytes written */
+
+ long headerbytecount; /* only count received headers */
+ long deductheadercount; /* this amount of bytes doesn't count when we check
+ if anything has been transferred at the end of a
+ connection. We use this counter to make only a
+ 100 reply (without a following second response
+ code) result in a CURLE_GOT_NOTHING error code */
+
+ struct timeval start; /* transfer started at this time */
+ struct timeval now; /* current time */
+ bool header; /* incoming data has HTTP header */
+ enum {
+ HEADER_NORMAL, /* no bad header at all */
+ HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
+ is normal data */
+ HEADER_ALLBAD /* all was believed to be header */
+ } badheader; /* the header was deemed bad and will be
+ written as body */
+ int headerline; /* counts header lines to better track the
+ first one */
+ char *hbufp; /* points at *end* of header line */
+ size_t hbuflen;
+ char *str; /* within buf */
+ char *str_start; /* within buf */
+ char *end_ptr; /* within buf */
+ char *p; /* within headerbuff */
+ bool content_range; /* set TRUE if Content-Range: was found */
+ curl_off_t offset; /* possible resume offset read from the
+ Content-Range: header */
+ int httpcode; /* error code from the 'HTTP/1.? XXX' or
+ 'RTSP/1.? XXX' line */
+ struct timeval start100; /* time stamp to wait for the 100 code from */
+ enum expect100 exp100; /* expect 100 continue state */
+ enum upgrade101 upgr101; /* 101 upgrade state */
+
+ int auto_decoding; /* What content encoding. sec 3.5, RFC2616. */
+
+#define IDENTITY 0 /* No encoding */
+#define DEFLATE 1 /* zlib deflate [RFC 1950 & 1951] */
+#define GZIP 2 /* gzip algorithm [RFC 1952] */
+#define COMPRESS 3 /* Not handled, added for completeness */
+
+#ifdef HAVE_LIBZ
+ zlibInitState zlib_init; /* possible zlib init state;
+ undefined if Content-Encoding header. */
+ z_stream z; /* State structure for zlib. */
+#endif
+
+ time_t timeofdoc;
+ long bodywrites;
+
+ char *buf;
+ char *uploadbuf;
+ curl_socket_t maxfd;
+
+ int keepon;
+
+ bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload
+ and we're uploading the last chunk */
+
+ bool ignorebody; /* we read a response-body but we ignore it! */
+ bool ignorecl; /* This HTTP response has no body so we ignore the Content-
+ Length: header */
+
+ char *location; /* This points to an allocated version of the Location:
+ header data */
+ char *newurl; /* Set to the new URL to use when a redirect or a retry is
+ wanted */
+
+ /* 'upload_present' is used to keep a byte counter of how much data there is
+ still left in the buffer, aimed for upload. */
+ ssize_t upload_present;
+
+ /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
+ buffer, so the next read should read from where this pointer points to,
+ and the 'upload_present' contains the number of bytes available at this
+ position */
+ char *upload_fromhere;
+
+ bool chunk; /* if set, this is a chunked transfer-encoding */
+ bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding
+ on upload */
+ bool getheader; /* TRUE if header parsing is wanted */
+
+ bool forbidchunk; /* used only to explicitly forbid chunk-upload for
+ specific upload buffers. See readmoredata() in
+ http.c for details. */
+
+ void *protop; /* Allocated protocol-specific data. Each protocol
+ handler makes sure this points to data it needs. */
+};
+
+/*
+ * Specific protocol handler.
+ */
+
+struct Curl_handler {
+ const char * scheme; /* URL scheme name. */
+
+ /* Complement to setup_connection_internals(). */
+ CURLcode (*setup_connection)(struct connectdata *);
+
+ /* These two functions MUST be set to be protocol dependent */
+ CURLcode (*do_it)(struct connectdata *, bool *done);
+ Curl_done_func done;
+
+ /* If the curl_do() function is better made in two halves, this
+ * curl_do_more() function will be called afterwards, if set. For example
+ * for doing the FTP stuff after the PASV/PORT command.
+ */
+ Curl_do_more_func do_more;
+
+ /* This function *MAY* be set to a protocol-dependent function that is run
+ * after the connect() and everything is done, as a step in the connection.
+ * The 'done' pointer points to a bool that should be set to TRUE if the
+ * function completes before return. If it doesn't complete, the caller
+ * should call the curl_connecting() function until it is.
+ */
+ CURLcode (*connect_it)(struct connectdata *, bool *done);
+
+ /* See above. Currently only used for FTP. */
+ CURLcode (*connecting)(struct connectdata *, bool *done);
+ CURLcode (*doing)(struct connectdata *, bool *done);
+
+ /* Called from the multi interface during the PROTOCONNECT phase, and it
+ should then return a proper fd set */
+ int (*proto_getsock)(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* Called from the multi interface during the DOING phase, and it should
+ then return a proper fd set */
+ int (*doing_getsock)(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* Called from the multi interface during the DO_MORE phase, and it should
+ then return a proper fd set */
+ int (*domore_getsock)(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* Called from the multi interface during the DO_DONE, PERFORM and
+ WAITPERFORM phases, and it should then return a proper fd set. Not setting
+ this will make libcurl use the generic default one. */
+ int (*perform_getsock)(const struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* This function *MAY* be set to a protocol-dependent function that is run
+ * by the curl_disconnect(), as a step in the disconnection. If the handler
+ * is called because the connection has been considered dead, dead_connection
+ * is set to TRUE.
+ */
+ CURLcode (*disconnect)(struct connectdata *, bool dead_connection);
+
+ /* If used, this function gets called from transfer.c:readwrite_data() to
+ allow the protocol to do extra reads/writes */
+ CURLcode (*readwrite)(struct SessionHandle *data, struct connectdata *conn,
+ ssize_t *nread, bool *readmore);
+
+ long defport; /* Default port. */
+ unsigned int protocol; /* See CURLPROTO_* - this needs to be the single
+ specific protocol bit */
+ unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */
+};
+
+#define PROTOPT_NONE 0 /* nothing extra */
+#define PROTOPT_SSL (1<<0) /* uses SSL */
+#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */
+#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */
+/* some protocols will have to call the underlying functions without regard to
+ what exact state the socket signals. IE even if the socket says "readable",
+ the send function might need to be called while uploading, or vice versa.
+*/
+#define PROTOPT_DIRLOCK (1<<3)
+#define PROTOPT_NONETWORK (1<<4) /* protocol doesn't use the network! */
+#define PROTOPT_NEEDSPWD (1<<5) /* needs a password, and if none is set it
+ gets a default */
+#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle
+ url query strings (?foo=bar) ! */
+#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
+ request instead of per connection */
+
+
+/* return the count of bytes sent, or -1 on error */
+typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *buf, /* data to write */
+ size_t len, /* max amount to write */
+ CURLcode *err); /* error to return */
+
+/* return the count of bytes read, or -1 on error */
+typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ char *buf, /* store data here */
+ size_t len, /* max amount to read */
+ CURLcode *err); /* error to return */
+
+/*
+ * The connectdata struct contains all fields and variables that should be
+ * unique for an entire connection.
+ */
+struct connectdata {
+ /* 'data' is the CURRENT SessionHandle using this connection -- take great
+ caution that this might very well vary between different times this
+ connection is used! */
+ struct SessionHandle *data;
+
+ /* chunk is for HTTP chunked encoding, but is in the general connectdata
+ struct only because we can do just about any protocol through a HTTP proxy
+ and a HTTP proxy may in fact respond using chunked encoding */
+ struct Curl_chunker chunk;
+
+ curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
+ void *closesocket_client;
+
+ bool inuse; /* This is a marker for the connection cache logic. If this is
+ TRUE this handle is being used by an easy handle and cannot
+ be used by any other easy handle without careful
+ consideration (== only for pipelining). */
+
+ /**** Fields set when inited and not modified again */
+ long connection_id; /* Contains a unique number to make it easier to
+ track the connections in the log output */
+
+ /* 'dns_entry' is the particular host we use. This points to an entry in the
+ DNS cache and it will not get pruned while locked. It gets unlocked in
+ Curl_done(). This entry will be NULL if the connection is re-used as then
+ there is no name resolve done. */
+ struct Curl_dns_entry *dns_entry;
+
+ /* 'ip_addr' is the particular IP we connected to. It points to a struct
+ within the DNS cache, so this pointer is only valid as long as the DNS
+ cache entry remains locked. It gets unlocked in Curl_done() */
+ Curl_addrinfo *ip_addr;
+ Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
+
+ /* 'ip_addr_str' is the ip_addr data as a human readable string.
+ It remains available as long as the connection does, which is longer than
+ the ip_addr itself. */
+ char ip_addr_str[MAX_IPADR_LEN];
+
+ unsigned int scope_id; /* Scope id for IPv6 */
+
+ int socktype; /* SOCK_STREAM or SOCK_DGRAM */
+
+ struct hostname host;
+ struct hostname proxy;
+
+ long port; /* which port to use locally */
+ int remote_port; /* what remote port to connect to, not the proxy port! */
+
+ /* 'primary_ip' and 'primary_port' get filled with peer's numerical
+ ip address and port number whenever an outgoing connection is
+ *attempted* from the primary socket to a remote address. When more
+ than one address is tried for a connection these will hold data
+ for the last attempt. When the connection is actually established
+ these are updated with data which comes directly from the socket. */
+
+ char primary_ip[MAX_IPADR_LEN];
+ long primary_port;
+
+ /* 'local_ip' and 'local_port' get filled with local's numerical
+ ip address and port number whenever an outgoing connection is
+ **established** from the primary socket to a remote address. */
+
+ char local_ip[MAX_IPADR_LEN];
+ long local_port;
+
+ char *user; /* user name string, allocated */
+ char *passwd; /* password string, allocated */
+ char *options; /* options string, allocated */
+
+ char *xoauth2_bearer; /* bearer token for xoauth2, allocated */
+
+ char *proxyuser; /* proxy user name string, allocated */
+ char *proxypasswd; /* proxy password string, allocated */
+ curl_proxytype proxytype; /* what kind of proxy that is in use */
+
+ int httpversion; /* the HTTP version*10 reported by the server */
+ int rtspversion; /* the RTSP version*10 reported by the server */
+
+ struct timeval now; /* "current" time */
+ struct timeval created; /* creation time */
+ curl_socket_t sock[2]; /* two sockets, the second is used for the data
+ transfer when doing FTP */
+ curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */
+ bool sock_accepted[2]; /* TRUE if the socket on this index was created with
+ accept() */
+ Curl_recv *recv[2];
+ Curl_send *send[2];
+
+ struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
+ struct ssl_config_data ssl_config;
+
+ struct ConnectBits bits; /* various state-flags for this connection */
+
+ /* connecttime: when connect() is called on the current IP address. Used to
+ be able to track when to move on to try next IP - but only when the multi
+ interface is used. */
+ struct timeval connecttime;
+ /* The two fields below get set in Curl_connecthost */
+ int num_addr; /* number of addresses to try to connect to */
+ long timeoutms_per_addr; /* how long time in milliseconds to spend on
+ trying to connect to each IP address */
+
+ const struct Curl_handler *handler; /* Connection's protocol handler */
+ const struct Curl_handler *given; /* The protocol first given */
+
+ long ip_version; /* copied from the SessionHandle at creation time */
+
+ /**** curl_get() phase fields */
+
+ curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
+ curl_socket_t writesockfd; /* socket to write to, it may very
+ well be the same we read from.
+ CURL_SOCKET_BAD disables */
+
+ /** Dynamicly allocated strings, MUST be freed before this **/
+ /** struct is killed. **/
+ struct dynamically_allocated_data {
+ char *proxyuserpwd;
+ char *uagent;
+ char *accept_encoding;
+ char *userpwd;
+ char *rangeline;
+ char *ref;
+ char *host;
+ char *cookiehost;
+ char *rtsp_transport;
+ char *te; /* TE: request header */
+ } allocptr;
+
+#ifdef HAVE_GSSAPI
+ int sec_complete; /* if Kerberos is enabled for this connection */
+ enum protection_level command_prot;
+ enum protection_level data_prot;
+ enum protection_level request_data_prot;
+ size_t buffer_size;
+ struct krb5buffer in_buffer;
+ void *app_data;
+ const struct Curl_sec_client_mech *mech;
+ struct sockaddr_in local_addr;
+#endif
+
+#if defined(USE_KERBEROS5) /* Consider moving some of the above GSS-API */
+ struct kerberos5data krb5; /* variables into the structure definition, */
+#endif /* however, some of them are ftp specific. */
+
+ /* the two following *_inuse fields are only flags, not counters in any way.
+ If TRUE it means the channel is in use, and if FALSE it means the channel
+ is up for grabs by one. */
+
+ bool readchannel_inuse; /* whether the read channel is in use by an easy
+ handle */
+ bool writechannel_inuse; /* whether the write channel is in use by an easy
+ handle */
+ struct curl_llist *send_pipe; /* List of handles waiting to
+ send on this pipeline */
+ struct curl_llist *recv_pipe; /* List of handles waiting to read
+ their responses on this pipeline */
+ char* master_buffer; /* The master buffer allocated on-demand;
+ used for pipelining. */
+ size_t read_pos; /* Current read position in the master buffer */
+ size_t buf_len; /* Length of the buffer?? */
+
+
+ curl_seek_callback seek_func; /* function that seeks the input */
+ void *seek_client; /* pointer to pass to the seek() above */
+
+ /*************** Request - specific items ************/
+
+ /* previously this was in the urldata struct */
+ curl_read_callback fread_func; /* function that reads the input */
+ void *fread_in; /* pointer to pass to the fread() above */
+
+#if defined(USE_NTLM)
+ struct ntlmdata ntlm; /* NTLM differs from other authentication schemes
+ because it authenticates connections, not
+ single requests! */
+ struct ntlmdata proxyntlm; /* NTLM data for proxy */
+
+#if defined(NTLM_WB_ENABLED)
+ /* used for communication with Samba's winbind daemon helper ntlm_auth */
+ curl_socket_t ntlm_auth_hlpr_socket;
+ pid_t ntlm_auth_hlpr_pid;
+ char* challenge_header;
+ char* response_header;
+#endif
+#endif
+
+ char syserr_buf [256]; /* buffer for Curl_strerror() */
+
+#ifdef CURLRES_ASYNCH
+ /* data used for the asynch name resolve callback */
+ struct Curl_async async;
+#endif
+
+ /* These three are used for chunked-encoding trailer support */
+ char *trailer; /* allocated buffer to store trailer in */
+ int trlMax; /* allocated buffer size */
+ int trlPos; /* index of where to store data */
+
+ union {
+ struct ftp_conn ftpc;
+ struct http_conn httpc;
+ struct ssh_conn sshc;
+ struct tftp_state_data *tftpc;
+ struct imap_conn imapc;
+ struct pop3_conn pop3c;
+ struct smtp_conn smtpc;
+ struct rtsp_conn rtspc;
+ struct smb_conn smbc;
+ void *generic; /* RTMP and LDAP use this */
+ } proto;
+
+ int cselect_bits; /* bitmask of socket events */
+ int waitfor; /* current READ/WRITE bits to wait for */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ int socks5_gssapi_enctype;
+#endif
+
+ bool verifypeer;
+ bool verifyhost;
+
+ /* When this connection is created, store the conditions for the local end
+ bind. This is stored before the actual bind and before any connection is
+ made and will serve the purpose of being used for comparison reasons so
+ that subsequent bound-requested connections aren't accidentally re-using
+ wrong connections. */
+ char *localdev;
+ unsigned short localport;
+ int localportrange;
+
+ /* tunnel as in tunnel through a HTTP proxy with CONNECT */
+ enum {
+ TUNNEL_INIT, /* init/default/no tunnel state */
+ TUNNEL_CONNECT, /* CONNECT has been sent off */
+ TUNNEL_COMPLETE /* CONNECT response received completely */
+ } tunnel_state[2]; /* two separate ones to allow FTP */
+ struct connectbundle *bundle; /* The bundle we are member of */
+
+ int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
+};
+
+/* The end of connectdata. */
+
+/*
+ * Struct to keep statistical and informational data.
+ */
+struct PureInfo {
+ int httpcode; /* Recent HTTP, FTP, or RTSP response code */
+ int httpproxycode; /* response code from proxy when received separate */
+ int httpversion; /* the http version number X.Y = X*10+Y */
+ long filetime; /* If requested, this is might get set. Set to -1 if the time
+ was unretrievable. We cannot have this of type time_t,
+ since time_t is unsigned on several platforms such as
+ OpenVMS. */
+ bool timecond; /* set to TRUE if the time condition didn't match, which
+ thus made the document NOT get fetched */
+ long header_size; /* size of read header(s) in bytes */
+ long request_size; /* the amount of bytes sent in the request(s) */
+ unsigned long proxyauthavail; /* what proxy auth types were announced */
+ unsigned long httpauthavail; /* what host auth types were announced */
+ long numconnects; /* how many new connection did libcurl created */
+ char *contenttype; /* the content type of the object */
+ char *wouldredirect; /* URL this would've been redirected to if asked to */
+
+ /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip'
+ and, 'conn_local_port' are copied over from the connectdata struct in
+ order to allow curl_easy_getinfo() to return this information even when
+ the session handle is no longer associated with a connection, and also
+ allow curl_easy_reset() to clear this information from the session handle
+ without disturbing information which is still alive, and that might be
+ reused, in the connection cache. */
+
+ char conn_primary_ip[MAX_IPADR_LEN];
+ long conn_primary_port;
+
+ char conn_local_ip[MAX_IPADR_LEN];
+ long conn_local_port;
+
+ struct curl_certinfo certs; /* info about the certs, only populated in
+ OpenSSL builds. Asked for with
+ CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+};
+
+
+struct Progress {
+ long lastshow; /* time() of the last displayed progress meter or NULL to
+ force redraw at next call */
+ curl_off_t size_dl; /* total expected size */
+ curl_off_t size_ul; /* total expected size */
+ curl_off_t downloaded; /* transferred so far */
+ curl_off_t uploaded; /* transferred so far */
+
+ curl_off_t current_speed; /* uses the currently fastest transfer */
+
+ bool callback; /* set when progress callback is used */
+ int width; /* screen width at download start */
+ int flags; /* see progress.h */
+
+ double timespent;
+
+ curl_off_t dlspeed;
+ curl_off_t ulspeed;
+
+ double t_nslookup;
+ double t_connect;
+ double t_appconnect;
+ double t_pretransfer;
+ double t_starttransfer;
+ double t_redirect;
+
+ struct timeval start;
+ struct timeval t_startsingle;
+ struct timeval t_startop;
+ struct timeval t_acceptdata;
+#define CURR_TIME (5+1) /* 6 entries for 5 seconds */
+
+ curl_off_t speeder[ CURR_TIME ];
+ struct timeval speeder_time[ CURR_TIME ];
+ int speeder_c;
+};
+
+typedef enum {
+ HTTPREQ_NONE, /* first in list */
+ HTTPREQ_GET,
+ HTTPREQ_POST,
+ HTTPREQ_POST_FORM, /* we make a difference internally */
+ HTTPREQ_PUT,
+ HTTPREQ_HEAD,
+ HTTPREQ_CUSTOM,
+ HTTPREQ_LAST /* last in list */
+} Curl_HttpReq;
+
+typedef enum {
+ RTSPREQ_NONE, /* first in list */
+ RTSPREQ_OPTIONS,
+ RTSPREQ_DESCRIBE,
+ RTSPREQ_ANNOUNCE,
+ RTSPREQ_SETUP,
+ RTSPREQ_PLAY,
+ RTSPREQ_PAUSE,
+ RTSPREQ_TEARDOWN,
+ RTSPREQ_GET_PARAMETER,
+ RTSPREQ_SET_PARAMETER,
+ RTSPREQ_RECORD,
+ RTSPREQ_RECEIVE,
+ RTSPREQ_LAST /* last in list */
+} Curl_RtspReq;
+
+/*
+ * Values that are generated, temporary or calculated internally for a
+ * "session handle" must be defined within the 'struct UrlState'. This struct
+ * will be used within the SessionHandle struct. When the 'SessionHandle'
+ * struct is cloned, this data MUST NOT be copied.
+ *
+ * Remember that any "state" information goes globally for the curl handle.
+ * Session-data MUST be put in the connectdata struct and here. */
+#define MAX_CURL_USER_LENGTH 256
+#define MAX_CURL_PASSWORD_LENGTH 256
+
+struct auth {
+ unsigned long want; /* Bitmask set to the authentication methods wanted by
+ app (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */
+ unsigned long picked;
+ unsigned long avail; /* Bitmask for what the server reports to support for
+ this resource */
+ bool done; /* TRUE when the auth phase is done and ready to do the *actual*
+ request */
+ bool multi; /* TRUE if this is not yet authenticated but within the auth
+ multipass negotiation */
+ bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should
+ be RFC compliant */
+};
+
+struct UrlState {
+
+ /* Points to the connection cache */
+ struct conncache *conn_cache;
+
+ /* when curl_easy_perform() is called, the multi handle is "owned" by
+ the easy handle so curl_easy_cleanup() on such an easy handle will
+ also close the multi handle! */
+ bool multi_owned_by_easy;
+
+ /* buffers to store authentication data in, as parsed from input options */
+ struct timeval keeps_speed; /* for the progress meter really */
+
+ struct connectdata *lastconnect; /* The last connection, NULL if undefined */
+
+ char *headerbuff; /* allocated buffer to store headers in */
+ size_t headersize; /* size of the allocation */
+
+ char buffer[BUFSIZE+1]; /* download buffer */
+ char uploadbuffer[BUFSIZE+1]; /* upload buffer */
+ curl_off_t current_speed; /* the ProgressShow() funcion sets this,
+ bytes / second */
+ bool this_is_a_follow; /* this is a followed Location: request */
+
+ char *first_host; /* if set, this should be the host name that we will
+ sent authorization to, no else. Used to make Location:
+ following not keep sending user+password... This is
+ strdup() data.
+ */
+ struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
+ long sessionage; /* number of the most recent session */
+ char *tempwrite; /* allocated buffer to keep data in when a write
+ callback returns to make the connection paused */
+ size_t tempwritesize; /* size of the 'tempwrite' allocated buffer */
+ int tempwritetype; /* type of the 'tempwrite' buffer as a bitmask that is
+ used with Curl_client_write() */
+ char *scratch; /* huge buffer[BUFSIZE*2] when doing upload CRLF replacing */
+ bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
+ This must be set to FALSE every time _easy_perform() is
+ called. */
+ int os_errno; /* filled in with errno whenever an error occurs */
+#ifdef HAVE_SIGNAL
+ /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
+ void (*prev_signal)(int sig);
+#endif
+ bool allow_port; /* Is set.use_port allowed to take effect or not. This
+ is always set TRUE when curl_easy_perform() is called. */
+ struct digestdata digest; /* state data for host Digest auth */
+ struct digestdata proxydigest; /* state data for proxy Digest auth */
+
+#ifdef USE_SPNEGO
+ struct negotiatedata negotiate; /* state data for host Negotiate auth */
+ struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
+#endif
+
+ struct auth authhost; /* auth details for host */
+ struct auth authproxy; /* auth details for proxy */
+
+ bool authproblem; /* TRUE if there's some problem authenticating */
+
+ void *resolver; /* resolver state, if it is used in the URL state -
+ ares_channel f.e. */
+
+#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+ ENGINE *engine;
+#endif /* USE_OPENSSL */
+ struct timeval expiretime; /* set this with Curl_expire() only */
+ struct Curl_tree timenode; /* for the splay stuff */
+ struct curl_llist *timeoutlist; /* list of pending timeouts */
+
+ /* a place to store the most recently set FTP entrypath */
+ char *most_recent_ftp_entrypath;
+
+ /* set after initial USER failure, to prevent an authentication loop */
+ bool ftp_trying_alternative;
+
+ int httpversion; /* the lowest HTTP version*10 reported by any server
+ involved in this request */
+ bool expect100header; /* TRUE if we added Expect: 100-continue */
+
+ bool pipe_broke; /* TRUE if the connection we were pipelined on broke
+ and we need to restart from the beginning */
+
+#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
+ !defined(__SYMBIAN32__)
+/* do FTP line-end conversions on most platforms */
+#define CURL_DO_LINEEND_CONV
+ /* for FTP downloads: track CRLF sequences that span blocks */
+ bool prev_block_had_trailing_cr;
+ /* for FTP downloads: how many CRLFs did we converted to LFs? */
+ curl_off_t crlf_conversions;
+#endif
+ char *pathbuffer;/* allocated buffer to store the URL's path part in */
+ char *path; /* path to use, points to somewhere within the pathbuffer
+ area */
+ bool slash_removed; /* set TRUE if the 'path' points to a path where the
+ initial URL slash separator has been taken off */
+ bool use_range;
+ bool rangestringalloc; /* the range string is malloc()'ed */
+
+ char *range; /* range, if used. See README for detailed specification on
+ this syntax. */
+ curl_off_t resume_from; /* continue [ftp] transfer from here */
+
+ /* This RTSP state information survives requests and connections */
+ long rtsp_next_client_CSeq; /* the session's next client CSeq */
+ long rtsp_next_server_CSeq; /* the session's next server CSeq */
+ long rtsp_CSeq_recv; /* most recent CSeq received */
+
+ curl_off_t infilesize; /* size of file to upload, -1 means unknown.
+ Copied from set.filesize at start of operation */
+};
+
+
+/*
+ * This 'DynamicStatic' struct defines dynamic states that actually change
+ * values in the 'UserDefined' area, which MUST be taken into consideration
+ * if the UserDefined struct is cloned or similar. You can probably just
+ * copy these, but each one indicate a special action on other data.
+ */
+
+struct DynamicStatic {
+ char *url; /* work URL, copied from UserDefined */
+ bool url_alloc; /* URL string is malloc()'ed */
+ char *referer; /* referer string */
+ bool referer_alloc; /* referer sting is malloc()ed */
+ struct curl_slist *cookielist; /* list of cookie files set by
+ curl_easy_setopt(COOKIEFILE) calls */
+ struct curl_slist *resolve; /* set to point to the set.resolve list when
+ this should be dealt with in pretransfer */
+};
+
+/*
+ * This 'UserDefined' struct must only contain data that is set once to go
+ * for many (perhaps) independent connections. Values that are generated or
+ * calculated internally for the "session handle" MUST be defined within the
+ * 'struct UrlState' instead. The only exceptions MUST note the changes in
+ * the 'DynamicStatic' struct.
+ * Character pointer fields point to dynamic storage, unless otherwise stated.
+ */
+
+struct Curl_multi; /* declared and used only in multi.c */
+
+enum dupstring {
+ STRING_CERT, /* client certificate file name */
+ STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
+ STRING_COOKIE, /* HTTP cookie string to send */
+ STRING_COOKIEJAR, /* dump all cookies to this file */
+ STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */
+ STRING_DEVICE, /* local network interface/address to use */
+ STRING_ENCODING, /* Accept-Encoding string */
+ STRING_FTP_ACCOUNT, /* ftp account data */
+ STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
+ STRING_FTPPORT, /* port to send with the FTP PORT command */
+ STRING_KEY, /* private key file name */
+ STRING_KEY_PASSWD, /* plain text private key password */
+ STRING_KEY_TYPE, /* format for private key (default: PEM) */
+ STRING_KRB_LEVEL, /* krb security level */
+ STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
+ $HOME/.netrc */
+ STRING_PROXY, /* proxy to use */
+ STRING_SET_RANGE, /* range, if used */
+ STRING_SET_REFERER, /* custom string for the HTTP referer field */
+ STRING_SET_URL, /* what original URL to work on */
+ STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
+ STRING_SSL_CAFILE, /* certificate file to verify peer against */
+ STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
+ STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+ STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
+ STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
+ STRING_USERAGENT, /* User-Agent string */
+ STRING_SSL_CRLFILE, /* crl file to check certificate */
+ STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
+ STRING_USERNAME, /* <username>, if used */
+ STRING_PASSWORD, /* <password>, if used */
+ STRING_OPTIONS, /* <options>, if used */
+ STRING_PROXYUSERNAME, /* Proxy <username>, if used */
+ STRING_PROXYPASSWORD, /* Proxy <password>, if used */
+ STRING_NOPROXY, /* List of hosts which should not use the proxy, if
+ used */
+ STRING_RTSP_SESSION_ID, /* Session ID to use */
+ STRING_RTSP_STREAM_URI, /* Stream URI for this request */
+ STRING_RTSP_TRANSPORT, /* Transport for this session */
+#ifdef USE_LIBSSH2
+ STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
+ STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */
+ STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
+ STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
+#endif
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */
+#endif
+ STRING_MAIL_FROM,
+ STRING_MAIL_AUTH,
+
+#ifdef USE_TLS_SRP
+ STRING_TLSAUTH_USERNAME, /* TLS auth <username> */
+ STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
+#endif
+ STRING_BEARER, /* <bearer>, if used */
+#ifdef USE_UNIX_SOCKETS
+ STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
+#endif
+
+ /* -- end of zero-terminated strings -- */
+
+ STRING_LASTZEROTERMINATED,
+
+ /* -- below this are pointers to binary data that cannot be strdup'ed.
+ Each such pointer must be added manually to Curl_dupset() --- */
+
+ STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
+
+ STRING_LAST /* not used, just an end-of-list marker */
+};
+
+struct UserDefined {
+ FILE *err; /* the stderr user data goes here */
+ void *debugdata; /* the data that will be passed to fdebug */
+ char *errorbuffer; /* (Static) store failure messages in here */
+ long proxyport; /* If non-zero, use this port number by default. If the
+ proxy string features a ":[port]" that one will override
+ this. */
+ void *out; /* the fetched file goes here */
+ void *in; /* the uploaded file is read from here */
+ void *writeheader; /* write the header to this if non-NULL */
+ void *rtp_out; /* write RTP to this if non-NULL */
+ long use_port; /* which port to use (when not using default) */
+ unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */
+ unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */
+ long followlocation; /* as in HTTP Location: */
+ long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
+ for infinity */
+
+ int keep_post; /* keep POSTs as POSTs after a 30x request; each
+ bit represents a request, from 301 to 303 */
+ bool free_referer; /* set TRUE if 'referer' points to a string we
+ allocated */
+ void *postfields; /* if POST, set the fields' values here */
+ curl_seek_callback seek_func; /* function that seeks the input */
+ curl_off_t postfieldsize; /* if POST, this might have a size to use instead
+ of strlen(), and then the data *may* be binary
+ (contain zero bytes) */
+ unsigned short localport; /* local port number to bind to */
+ int localportrange; /* number of additional port numbers to test in case the
+ 'localport' one can't be bind()ed */
+ curl_write_callback fwrite_func; /* function that stores the output */
+ curl_write_callback fwrite_header; /* function that stores headers */
+ curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */
+ curl_read_callback fread_func; /* function that reads the input */
+ int is_fread_set; /* boolean, has read callback been set to non-NULL? */
+ int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */
+ curl_progress_callback fprogress; /* OLD and deprecated progress callback */
+ curl_xferinfo_callback fxferinfo; /* progress callback */
+ curl_debug_callback fdebug; /* function that write informational data */
+ curl_ioctl_callback ioctl_func; /* function for I/O control */
+ curl_sockopt_callback fsockopt; /* function for setting socket options */
+ void *sockopt_client; /* pointer to pass to the socket options callback */
+ curl_opensocket_callback fopensocket; /* function for checking/translating
+ the address and opening the
+ socket */
+ void* opensocket_client;
+ curl_closesocket_callback fclosesocket; /* function for closing the
+ socket */
+ void* closesocket_client;
+
+ void *seek_client; /* pointer to pass to the seek callback */
+ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */
+ /* function to convert from the network encoding: */
+ curl_conv_callback convfromnetwork;
+ /* function to convert to the network encoding: */
+ curl_conv_callback convtonetwork;
+ /* function to convert from UTF-8 encoding: */
+ curl_conv_callback convfromutf8;
+
+ void *progress_client; /* pointer to pass to the progress callback */
+ void *ioctl_client; /* pointer to pass to the ioctl callback */
+ long timeout; /* in milliseconds, 0 means no timeout */
+ long connecttimeout; /* in milliseconds, 0 means no timeout */
+ long accepttimeout; /* in milliseconds, 0 means no timeout */
+ long server_response_timeout; /* in milliseconds, 0 means no timeout */
+ long tftp_blksize ; /* in bytes, 0 means use default */
+ curl_off_t filesize; /* size of file to upload, -1 means unknown */
+ long low_speed_limit; /* bytes/second */
+ long low_speed_time; /* number of seconds */
+ curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */
+ curl_off_t max_recv_speed; /* high speed limit in bytes/second for
+ download */
+ curl_off_t set_resume_from; /* continue [ftp] transfer from here */
+ struct curl_slist *headers; /* linked list of extra headers */
+ struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
+ struct curl_httppost *httppost; /* linked list of POST data */
+ bool sep_headers; /* handle host and proxy headers separately */
+ bool cookiesession; /* new cookie session? */
+ bool crlf; /* convert crlf on ftp upload(?) */
+ struct curl_slist *quote; /* after connection is established */
+ struct curl_slist *postquote; /* after the transfer */
+ struct curl_slist *prequote; /* before the transfer, after type */
+ struct curl_slist *source_quote; /* 3rd party quote */
+ struct curl_slist *source_prequote; /* in 3rd party transfer mode - before
+ the transfer on source host */
+ struct curl_slist *source_postquote; /* in 3rd party transfer mode - after
+ the transfer on source host */
+ struct curl_slist *telnet_options; /* linked list of telnet options */
+ struct curl_slist *resolve; /* list of names to add/remove from
+ DNS cache */
+ curl_TimeCond timecondition; /* kind of time/date comparison */
+ time_t timevalue; /* what time to compare with */
+ Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
+ long httpversion; /* when non-zero, a specific HTTP version requested to
+ be used in the library's request(s) */
+ struct ssl_config_data ssl; /* user defined SSL stuff */
+ curl_proxytype proxytype; /* what kind of proxy that is in use */
+ long dns_cache_timeout; /* DNS cache timeout */
+ long buffer_size; /* size of receive buffer to use */
+ void *private_data; /* application-private data */
+
+ struct curl_slist *http200aliases; /* linked list of aliases for http200 */
+
+ long ipver; /* the CURL_IPRESOLVE_* defines in the public header file
+ 0 - whatever, 1 - v2, 2 - v6 */
+
+ curl_off_t max_filesize; /* Maximum file size to download */
+
+ curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
+
+ int ftp_create_missing_dirs; /* 1 - create directories that don't exist
+ 2 - the same but also allow MKD to fail once
+ */
+
+ curl_sshkeycallback ssh_keyfunc; /* key matching callback */
+ void *ssh_keyfunc_userp; /* custom pointer to callback */
+
+/* Here follows boolean settings that define how to behave during
+ this session. They are STATIC, set by libcurl users or at least initially
+ and they don't change during operations. */
+
+ bool printhost; /* printing host name in debug info */
+ bool get_filetime; /* get the time and get of the remote file */
+ bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */
+ bool prefer_ascii; /* ASCII rather than binary */
+ bool ftp_append; /* append, not overwrite, on upload */
+ bool ftp_list_only; /* switch FTP command for listing directories */
+ bool ftp_use_port; /* use the FTP PORT command */
+ bool hide_progress; /* don't use the progress meter */
+ bool http_fail_on_error; /* fail on HTTP error codes >= 400 */
+ bool http_follow_location; /* follow HTTP redirects */
+ bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */
+ bool http_disable_hostname_check_before_authentication;
+ bool include_header; /* include received protocol headers in data output */
+ bool http_set_referer; /* is a custom referer used */
+ bool http_auto_referer; /* set "correct" referer when following location: */
+ bool opt_no_body; /* as set with CURLOPT_NOBODY */
+ bool set_port; /* custom port number used */
+ bool upload; /* upload request */
+ enum CURL_NETRC_OPTION
+ use_netrc; /* defined in include/curl.h */
+ bool verbose; /* output verbosity */
+ bool krb; /* Kerberos connection requested */
+ bool reuse_forbid; /* forbidden to be reused, close after use */
+ bool reuse_fresh; /* do not re-use an existing connection */
+ bool ftp_use_epsv; /* if EPSV is to be attempted or not */
+ bool ftp_use_eprt; /* if EPRT is to be attempted or not */
+ bool ftp_use_pret; /* if PRET is to be used before PASV or not */
+
+ curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
+ IMAP or POP3 or others! */
+ curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
+ curl_ftpccc ftp_ccc; /* FTP CCC options */
+ bool no_signal; /* do not use any signal/alarm handler */
+ bool global_dns_cache; /* subject for future removal */
+ bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */
+ bool ignorecl; /* ignore content length */
+ bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
+ us */
+ bool connect_only; /* make connection, let application use the socket */
+ bool ssl_enable_beast; /* especially allow this flaw for interoperability's
+ sake*/
+ long ssh_auth_types; /* allowed SSH auth types */
+ bool http_te_skip; /* pass the raw body data to the user, even when
+ transfer-encoded (chunked, compressed) */
+ bool http_ce_skip; /* pass the raw body data to the user, even when
+ content-encoded (chunked, compressed) */
+ long new_file_perms; /* Permissions to use when creating remote files */
+ long new_directory_perms; /* Permissions to use when creating remote dirs */
+ bool proxy_transfer_mode; /* set transfer mode (;type=<a|i>) when doing FTP
+ via an HTTP proxy */
+ char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
+ unsigned int scope_id; /* Scope id for IPv6 */
+ long allowed_protocols;
+ long redir_protocols;
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ long socks5_gssapi_nec; /* flag to support nec socks5 server */
+#endif
+ struct curl_slist *mail_rcpt; /* linked list of mail recipients */
+ bool sasl_ir; /* Enable/disable SASL initial response */
+ /* Common RTSP header options */
+ Curl_RtspReq rtspreq; /* RTSP request type */
+ long rtspversion; /* like httpversion, for RTSP */
+ bool wildcardmatch; /* enable wildcard matching */
+ curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer
+ starts */
+ curl_chunk_end_callback chunk_end; /* called after part transferring
+ stopped */
+ curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds
+ to pattern (e.g. if WILDCARDMATCH is on) */
+ void *fnmatch_data;
+
+ long gssapi_delegation; /* GSS-API credential delegation, see the
+ documentation of CURLOPT_GSSAPI_DELEGATION */
+
+ bool tcp_keepalive; /* use TCP keepalives */
+ long tcp_keepidle; /* seconds in idle before sending keepalive probe */
+ long tcp_keepintvl; /* seconds between TCP keepalive probes */
+
+ size_t maxconnects; /* Max idle connections in the connection cache */
+
+ bool ssl_enable_npn; /* TLS NPN extension? */
+ bool ssl_enable_alpn; /* TLS ALPN extension? */
+ bool path_as_is; /* allow dotdots? */
+ long expect_100_timeout; /* in milliseconds */
+};
+
+struct Names {
+ struct curl_hash *hostcache;
+ enum {
+ HCACHE_NONE, /* not pointing to anything */
+ HCACHE_GLOBAL, /* points to the (shrug) global one */
+ HCACHE_MULTI, /* points to a shared one in the multi handle */
+ HCACHE_SHARED /* points to a shared one in a shared object */
+ } hostcachetype;
+};
+
+/*
+ * The 'connectdata' struct MUST have all the connection oriented stuff as we
+ * may have several simultaneous connections and connection structs in memory.
+ *
+ * The 'struct UserDefined' must only contain data that is set once to go for
+ * many (perhaps) independent connections. Values that are generated or
+ * calculated internally for the "session handle" must be defined within the
+ * 'struct UrlState' instead.
+ */
+
+struct SessionHandle {
+ /* first, two fields for the linked list of these */
+ struct SessionHandle *next;
+ struct SessionHandle *prev;
+
+ struct connectdata *easy_conn; /* the "unit's" connection */
+
+ CURLMstate mstate; /* the handle's state */
+ CURLcode result; /* previous result */
+
+ struct Curl_message msg; /* A single posted message. */
+
+ /* Array with the plain socket numbers this handle takes care of, in no
+ particular order. Note that all sockets are added to the sockhash, where
+ the state etc are also kept. This array is mostly used to detect when a
+ socket is to be removed from the hash. See singlesocket(). */
+ curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
+ int numsocks;
+
+ struct Names dns;
+ struct Curl_multi *multi; /* if non-NULL, points to the multi handle
+ struct to which this "belongs" when used by
+ the multi interface */
+ struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle
+ struct to which this "belongs" when used
+ by the easy interface */
+ struct Curl_share *share; /* Share, handles global variable mutexing */
+ struct SingleRequest req; /* Request-specific data */
+ struct UserDefined set; /* values set by the libcurl user */
+ struct DynamicStatic change; /* possibly modified userdefined data */
+ struct CookieInfo *cookies; /* the cookies, read from files and servers.
+ NOTE that the 'cookie' field in the
+ UserDefined struct defines if the "engine"
+ is to be used or not. */
+ struct Progress progress; /* for all the progress meter data */
+ struct UrlState state; /* struct for fields used for state info and
+ other dynamic purposes */
+ struct WildcardData wildcard; /* wildcard download state info */
+ struct PureInfo info; /* stats, reports and info data */
+ struct curl_tlssessioninfo tsi; /* Information about the TLS session, only
+ valid after a client has asked for it */
+#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
+ iconv_t outbound_cd; /* for translating to the network encoding */
+ iconv_t inbound_cd; /* for translating from the network encoding */
+ iconv_t utf8_cd; /* for translating to UTF8 */
+#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
+ unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */
+};
+
+#define LIBCURL_NAME "libcurl"
+
+#endif /* HEADER_CURL_URLDATA_H */
diff --git a/libcurl/src/lib/version.c b/libcurl/src/lib/version.c
new file mode 100644
index 0000000..34d2c02
--- /dev/null
+++ b/libcurl/src/lib/version.c
@@ -0,0 +1,362 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "vtls/vtls.h"
+#include "http2.h"
+#include "curl_printf.h"
+
+#ifdef USE_ARES
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+# define CARES_STATICLIB
+# endif
+# include <ares.h>
+#endif
+
+#ifdef USE_LIBIDN
+#include <stringprep.h>
+#endif
+
+#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
+#include <iconv.h>
+#endif
+
+#ifdef USE_LIBRTMP
+#include <librtmp/rtmp.h>
+#endif
+
+#ifdef USE_LIBSSH2
+#include <libssh2.h>
+#endif
+
+#ifdef HAVE_LIBSSH2_VERSION
+/* get it run-time if possible */
+#define CURL_LIBSSH2_VERSION libssh2_version(0)
+#else
+/* use build-time if run-time not possible */
+#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
+#endif
+
+char *curl_version(void)
+{
+ static char version[200];
+ char *ptr = version;
+ size_t len;
+ size_t left = sizeof(version);
+
+ strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION);
+ len = strlen(ptr);
+ left -= len;
+ ptr += len;
+
+ if(left > 1) {
+ len = Curl_ssl_version(ptr + 1, left - 1);
+
+ if(len > 0) {
+ *ptr = ' ';
+ left -= ++len;
+ ptr += len;
+ }
+ }
+
+#ifdef HAVE_LIBZ
+ len = snprintf(ptr, left, " zlib/%s", zlibVersion());
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_ARES
+ /* this function is only present in c-ares, not in the original ares */
+ len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL));
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_LIBIDN
+ if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
+ len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL));
+ left -= len;
+ ptr += len;
+ }
+#endif
+#ifdef USE_WIN32_IDN
+ len = snprintf(ptr, left, " WinIDN");
+ left -= len;
+ ptr += len;
+#endif
+#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
+#ifdef _LIBICONV_VERSION
+ len = snprintf(ptr, left, " iconv/%d.%d",
+ _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
+#else
+ /* version unknown */
+ len = snprintf(ptr, left, " iconv");
+#endif /* _LIBICONV_VERSION */
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_LIBSSH2
+ len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION);
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_NGHTTP2
+ len = Curl_http2_ver(ptr, left);
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_LIBRTMP
+ {
+ char suff[2];
+ if(RTMP_LIB_VERSION & 0xff) {
+ suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
+ suff[1] = '\0';
+ }
+ else
+ suff[0] = '\0';
+
+ snprintf(ptr, left, " librtmp/%d.%d%s",
+ RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
+ suff);
+/*
+ If another lib version is added below this one, this code would
+ also have to do:
+
+ len = what snprintf() returned
+
+ left -= len;
+ ptr += len;
+*/
+ }
+#endif
+
+ return version;
+}
+
+/* data for curl_version_info
+
+ Keep the list sorted alphabetically. It is also written so that each
+ protocol line has its own #if line to make things easier on the eye.
+ */
+
+static const char * const protocol_names[] = {
+#ifndef CURL_DISABLE_DICT
+ "dict",
+#endif
+#ifndef CURL_DISABLE_FILE
+ "file",
+#endif
+#ifndef CURL_DISABLE_FTP
+ "ftp",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+ "ftps",
+#endif
+#ifndef CURL_DISABLE_GOPHER
+ "gopher",
+#endif
+#ifndef CURL_DISABLE_HTTP
+ "http",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ "https",
+#endif
+#ifndef CURL_DISABLE_IMAP
+ "imap",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
+ "imaps",
+#endif
+#ifndef CURL_DISABLE_LDAP
+ "ldap",
+#if !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+ "ldaps",
+#endif
+#endif
+#ifndef CURL_DISABLE_POP3
+ "pop3",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
+ "pop3s",
+#endif
+#ifdef USE_LIBRTMP
+ "rtmp",
+#endif
+#ifndef CURL_DISABLE_RTSP
+ "rtsp",
+#endif
+#ifdef USE_LIBSSH2
+ "scp",
+#endif
+#ifdef USE_LIBSSH2
+ "sftp",
+#endif
+#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4) && \
+ (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
+ "smb",
+# ifdef USE_SSL
+ "smbs",
+# endif
+#endif
+#ifndef CURL_DISABLE_SMTP
+ "smtp",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
+ "smtps",
+#endif
+#ifndef CURL_DISABLE_TELNET
+ "telnet",
+#endif
+#ifndef CURL_DISABLE_TFTP
+ "tftp",
+#endif
+
+ NULL
+};
+
+static curl_version_info_data version_info = {
+ CURLVERSION_NOW,
+ LIBCURL_VERSION,
+ LIBCURL_VERSION_NUM,
+ OS, /* as found by configure or set by hand at build-time */
+ 0 /* features is 0 by default */
+#ifdef ENABLE_IPV6
+ | CURL_VERSION_IPV6
+#endif
+#ifdef USE_SSL
+ | CURL_VERSION_SSL
+#endif
+#ifdef USE_NTLM
+ | CURL_VERSION_NTLM
+#endif
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
+ defined(NTLM_WB_ENABLED)
+ | CURL_VERSION_NTLM_WB
+#endif
+#ifdef USE_SPNEGO
+ | CURL_VERSION_SPNEGO
+#endif
+#ifdef USE_KERBEROS5
+ | CURL_VERSION_KERBEROS5
+#endif
+#ifdef HAVE_GSSAPI
+ | CURL_VERSION_GSSAPI
+#endif
+#ifdef USE_WINDOWS_SSPI
+ | CURL_VERSION_SSPI
+#endif
+#ifdef HAVE_LIBZ
+ | CURL_VERSION_LIBZ
+#endif
+#ifdef DEBUGBUILD
+ | CURL_VERSION_DEBUG
+#endif
+#ifdef CURLDEBUG
+ | CURL_VERSION_CURLDEBUG
+#endif
+#ifdef CURLRES_ASYNCH
+ | CURL_VERSION_ASYNCHDNS
+#endif
+#if (CURL_SIZEOF_CURL_OFF_T > 4) && \
+ ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
+ | CURL_VERSION_LARGEFILE
+#endif
+#if defined(CURL_DOES_CONVERSIONS)
+ | CURL_VERSION_CONV
+#endif
+#if defined(USE_TLS_SRP)
+ | CURL_VERSION_TLSAUTH_SRP
+#endif
+#if defined(USE_NGHTTP2)
+ | CURL_VERSION_HTTP2
+#endif
+#if defined(USE_UNIX_SOCKETS)
+ | CURL_VERSION_UNIX_SOCKETS
+#endif
+ ,
+ NULL, /* ssl_version */
+ 0, /* ssl_version_num, this is kept at zero */
+ NULL, /* zlib_version */
+ protocol_names,
+ NULL, /* c-ares version */
+ 0, /* c-ares version numerical */
+ NULL, /* libidn version */
+ 0, /* iconv version */
+ NULL, /* ssh lib version */
+};
+
+curl_version_info_data *curl_version_info(CURLversion stamp)
+{
+#ifdef USE_LIBSSH2
+ static char ssh_buffer[80];
+#endif
+
+#ifdef USE_SSL
+ static char ssl_buffer[80];
+ Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
+ version_info.ssl_version = ssl_buffer;
+#endif
+
+#ifdef HAVE_LIBZ
+ version_info.libz_version = zlibVersion();
+ /* libz left NULL if non-existing */
+#endif
+#ifdef USE_ARES
+ {
+ int aresnum;
+ version_info.ares = ares_version(&aresnum);
+ version_info.ares_num = aresnum;
+ }
+#endif
+#ifdef USE_LIBIDN
+ /* This returns a version string if we use the given version or later,
+ otherwise it returns NULL */
+ version_info.libidn = stringprep_check_version(LIBIDN_REQUIRED_VERSION);
+ if(version_info.libidn)
+ version_info.features |= CURL_VERSION_IDN;
+#elif defined(USE_WIN32_IDN)
+ version_info.features |= CURL_VERSION_IDN;
+#endif
+
+#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
+#ifdef _LIBICONV_VERSION
+ version_info.iconv_ver_num = _LIBICONV_VERSION;
+#else
+ /* version unknown */
+ version_info.iconv_ver_num = -1;
+#endif /* _LIBICONV_VERSION */
+#endif
+
+#ifdef USE_LIBSSH2
+ snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
+ version_info.libssh_version = ssh_buffer;
+#endif
+
+ (void)stamp; /* avoid compiler warnings, we don't use this */
+
+ return &version_info;
+}
diff --git a/libcurl/src/lib/vtls/axtls.c b/libcurl/src/lib/vtls/axtls.c
new file mode 100644
index 0000000..8d7e0f9
--- /dev/null
+++ b/libcurl/src/lib/vtls/axtls.c
@@ -0,0 +1,696 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
+ * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all axTLS-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ */
+
+#include "../curl_setup.h"
+
+#ifdef USE_AXTLS
+#include <axTLS/config.h>
+#include <axTLS/ssl.h>
+#include "axtls.h"
+
+#include "../sendf.h"
+#include "../inet_pton.h"
+#include "vtls.h"
+#include "../parsedate.h"
+#include "../connect.h" /* for the connect timeout */
+#include "../select.h"
+#include "../curl_printf.h"
+#include "../hostcheck.h"
+#if !defined(_MSC_VER)
+#include <unistd.h>
+#endif
+
+/* The last #include files should be: */
+#include "../curl_memory.h"
+#include "../memdebug.h"
+
+
+/* Global axTLS init, called from Curl_ssl_init() */
+CURL_STATIC int Curl_axtls_init(void)
+{
+/* axTLS has no global init. Everything is done through SSL and SSL_CTX
+ * structs stored in connectdata structure. Perhaps can move to axtls.h.
+ */
+ return 1;
+}
+
+CURL_STATIC int Curl_axtls_cleanup(void)
+{
+ /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */
+ return 1;
+}
+
+static CURLcode map_error_to_curl(int axtls_err)
+{
+ switch (axtls_err) {
+ case SSL_ERROR_NOT_SUPPORTED:
+ case SSL_ERROR_INVALID_VERSION:
+ case -70: /* protocol version alert from server */
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ break;
+ case SSL_ERROR_NO_CIPHER:
+ return CURLE_SSL_CIPHER;
+ break;
+ case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
+ case SSL_ERROR_NO_CERT_DEFINED:
+ case -42: /* bad certificate alert from server */
+ case -43: /* unsupported cert alert from server */
+ case -44: /* cert revoked alert from server */
+ case -45: /* cert expired alert from server */
+ case -46: /* cert unknown alert from server */
+ return CURLE_SSL_CERTPROBLEM;
+ break;
+ case SSL_X509_ERROR(X509_NOT_OK):
+ case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
+ case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
+ case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
+ case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
+ case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
+ case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
+ case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
+ case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
+ return CURLE_PEER_FAILED_VERIFICATION;
+ break;
+ case -48: /* unknown ca alert from server */
+ return CURLE_SSL_CACERT;
+ break;
+ case -49: /* access denied alert from server */
+ return CURLE_REMOTE_ACCESS_DENIED;
+ break;
+ case SSL_ERROR_CONN_LOST:
+ case SSL_ERROR_SOCK_SETUP_FAILURE:
+ case SSL_ERROR_INVALID_HANDSHAKE:
+ case SSL_ERROR_INVALID_PROT_MSG:
+ case SSL_ERROR_INVALID_HMAC:
+ case SSL_ERROR_INVALID_SESSION:
+ case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */
+ case SSL_ERROR_FINISHED_INVALID:
+ case SSL_ERROR_NO_CLIENT_RENOG:
+ default:
+ return CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+}
+
+static Curl_recv axtls_recv;
+static Curl_send axtls_send;
+
+static void free_ssl_structs(struct ssl_connect_data *connssl)
+{
+ if(connssl->ssl) {
+ ssl_free (connssl->ssl);
+ connssl->ssl = NULL;
+ }
+ if(connssl->ssl_ctx) {
+ ssl_ctx_free(connssl->ssl_ctx);
+ connssl->ssl_ctx = NULL;
+ }
+}
+
+/*
+ * For both blocking and non-blocking connects, this function sets up the
+ * ssl context and state. This function is called after the TCP connect
+ * has completed.
+ */
+static CURLcode connect_prep(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ SSL_CTX *ssl_ctx;
+ SSL *ssl = NULL;
+ int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
+ int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
+ int i, ssl_fcn_return;
+ const uint8_t *ssl_sessionid;
+ size_t ssl_idsize;
+
+ /* Assuming users will not compile in custom key/cert to axTLS.
+ * Also, even for blocking connects, use axTLS non-blocking feature.
+ */
+ uint32_t client_option = SSL_NO_DEFAULT_KEY |
+ SSL_SERVER_VERIFY_LATER |
+ SSL_CONNECT_IN_PARTS;
+
+ if(conn->ssl[sockindex].state == ssl_connection_complete)
+ /* to make us tolerant against being called more than once for the
+ same connection */
+ return CURLE_OK;
+
+ /* axTLS only supports TLSv1 */
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ break;
+ default:
+ failf(data, "axTLS only supports TLS 1.0 and 1.1, "
+ "and it cannot be specified which one to use");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+#ifdef AXTLSDEBUG
+ client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
+#endif /* AXTLSDEBUG */
+
+ /* Allocate an SSL_CTX struct */
+ ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
+ if(ssl_ctx == NULL) {
+ failf(data, "unable to create client SSL context");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ conn->ssl[sockindex].ssl_ctx = ssl_ctx;
+ conn->ssl[sockindex].ssl = NULL;
+
+ /* Load the trusted CA cert bundle file */
+ if(data->set.ssl.CAfile) {
+ if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
+ != SSL_OK) {
+ infof(data, "error reading ca cert file %s \n",
+ data->set.ssl.CAfile);
+ if(data->set.ssl.verifypeer) {
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
+ }
+
+ /* gtls.c tasks we're skipping for now:
+ * 1) certificate revocation list checking
+ * 2) dns name assignment to host
+ * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore
+ * 4) set certificate priority. axTLS ignores type and sends certs in
+ * order added. can probably ignore this.
+ */
+
+ /* Load client certificate */
+ if(data->set.str[STRING_CERT]) {
+ i=0;
+ /* Instead of trying to analyze cert type here, let axTLS try them all. */
+ while(cert_types[i] != 0) {
+ ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
+ data->set.str[STRING_CERT], NULL);
+ if(ssl_fcn_return == SSL_OK) {
+ infof(data, "successfully read cert file %s \n",
+ data->set.str[STRING_CERT]);
+ break;
+ }
+ i++;
+ }
+ /* Tried all cert types, none worked. */
+ if(cert_types[i] == 0) {
+ failf(data, "%s is not x509 or pkcs12 format",
+ data->set.str[STRING_CERT]);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Load client key.
+ If a pkcs12 file successfully loaded a cert, then there's nothing to do
+ because the key has already been loaded. */
+ if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
+ i=0;
+ /* Instead of trying to analyze key type here, let axTLS try them all. */
+ while(key_types[i] != 0) {
+ ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
+ data->set.str[STRING_KEY], NULL);
+ if(ssl_fcn_return == SSL_OK) {
+ infof(data, "successfully read key file %s \n",
+ data->set.str[STRING_KEY]);
+ break;
+ }
+ i++;
+ }
+ /* Tried all key types, none worked. */
+ if(key_types[i] == 0) {
+ failf(data, "Failure: %s is not a supported key file",
+ data->set.str[STRING_KEY]);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* gtls.c does more here that is being left out for now
+ * 1) set session credentials. can probably ignore since axtls puts this
+ * info in the ssl_ctx struct
+ * 2) setting up callbacks. these seem gnutls specific
+ */
+
+ /* In axTLS, handshaking happens inside ssl_client_new. */
+ if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
+ /* we got a session id, use it! */
+ infof (data, "SSL re-using session ID\n");
+ ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
+ ssl_sessionid, (uint8_t)ssl_idsize);
+ }
+ else
+ ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
+
+ conn->ssl[sockindex].ssl = ssl;
+ return CURLE_OK;
+}
+
+/*
+ * For both blocking and non-blocking connects, this function finalizes the
+ * SSL connection.
+ */
+static CURLcode connect_finish(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ SSL *ssl = conn->ssl[sockindex].ssl;
+ const uint8_t *ssl_sessionid;
+ size_t ssl_idsize;
+ const char *peer_CN;
+ uint32_t dns_altname_index;
+ const char *dns_altname;
+ int8_t found_subject_alt_names = 0;
+ int8_t found_subject_alt_name_matching_conn = 0;
+
+ /* Here, gtls.c gets the peer certificates and fails out depending on
+ * settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
+ */
+
+ /* Verify server's certificate */
+ if(data->set.ssl.verifypeer) {
+ if(ssl_verify_cert(ssl) != SSL_OK) {
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "server cert verify failed");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ else
+ infof(data, "\t server certificate verification SKIPPED\n");
+
+ /* Here, gtls.c does issuer verification. axTLS has no straightforward
+ * equivalent, so omitting for now.*/
+
+ /* Here, gtls.c does the following
+ * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but
+ * it seems useful. This is now implemented, by Oscar Koeroo
+ * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert
+ * 3) displays a bunch of cert information. axTLS doesn't support most of
+ * this, but a couple fields are available.
+ */
+
+ /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
+ risk of an inifite loop */
+ for(dns_altname_index = 0; ; dns_altname_index++) {
+ dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
+ if(dns_altname == NULL) {
+ break;
+ }
+ found_subject_alt_names = 1;
+
+ infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
+ dns_altname, conn->host.name);
+ if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
+ found_subject_alt_name_matching_conn = 1;
+ break;
+ }
+ }
+
+ /* RFC2818 checks */
+ if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
+ if(data->set.ssl.verifyhost) {
+ /* Break connection ! */
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "\tsubjectAltName(s) do not match %s\n",
+ conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\tsubjectAltName(s) do not match %s\n",
+ conn->host.dispname);
+ }
+ else if(found_subject_alt_names == 0) {
+ /* Per RFC2818, when no Subject Alt Names were available, examine the peer
+ CN as a legacy fallback */
+ peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
+ if(peer_CN == NULL) {
+ if(data->set.ssl.verifyhost) {
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "unable to obtain common name from peer certificate");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "unable to obtain common name from peer certificate");
+ }
+ else {
+ if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+ if(data->set.ssl.verifyhost) {
+ /* Break connection ! */
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
+ peer_CN, conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
+ peer_CN, conn->host.dispname);
+ }
+ }
+ }
+
+ /* General housekeeping */
+ conn->ssl[sockindex].state = ssl_connection_complete;
+ conn->recv[sockindex] = axtls_recv;
+ conn->send[sockindex] = axtls_send;
+
+ /* Put our freshly minted SSL session in cache */
+ ssl_idsize = ssl_get_session_id_size(ssl);
+ ssl_sessionid = ssl_get_session_id(ssl);
+ if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
+ != CURLE_OK)
+ infof (data, "failed to add session to cache\n");
+
+ return CURLE_OK;
+}
+
+/*
+ * Use axTLS's non-blocking connection feature to open an SSL connection.
+ * This is called after a TCP connection is already established.
+ */
+CURL_STATIC CURLcode Curl_axtls_connect_nonblocking(
+ struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ CURLcode conn_step;
+ int ssl_fcn_return;
+ int i;
+
+ *done = FALSE;
+ /* connectdata is calloc'd and connecting_state is only changed in this
+ function, so this is safe, as the state is effectively initialized. */
+ if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
+ conn_step = connect_prep(conn, sockindex);
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+ conn->ssl[sockindex].connecting_state = ssl_connect_2;
+ }
+
+ if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
+ /* Check to make sure handshake was ok. */
+ if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
+ /* Loop to perform more work in between sleeps. This is work around the
+ fact that axtls does not expose any knowledge about when work needs
+ to be performed. This can save ~25% of time on SSL handshakes. */
+ for(i=0; i<5; i++) {
+ ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
+ if(ssl_fcn_return < 0) {
+ Curl_axtls_close(conn, sockindex);
+ ssl_display_error(ssl_fcn_return); /* goes to stdout. */
+ return map_error_to_curl(ssl_fcn_return);
+ }
+ return CURLE_OK;
+ }
+ }
+ infof (conn->data, "handshake completed successfully\n");
+ conn->ssl[sockindex].connecting_state = ssl_connect_3;
+ }
+
+ if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
+ conn_step = connect_finish(conn, sockindex);
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+
+ /* Reset connect state */
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Unrecognized state. Things are very bad. */
+ conn->ssl[sockindex].state = ssl_connection_none;
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ /* Return value perhaps not strictly correct, but distinguishes the issue.*/
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+}
+
+
+/*
+ * This function is called after the TCP connect has completed. Setup the TLS
+ * layer and do all necessary magic for a blocking connect.
+ */
+CURL_STATIC CURLcode
+Curl_axtls_connect(struct connectdata *conn,
+ int sockindex)
+
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode conn_step = connect_prep(conn, sockindex);
+ int ssl_fcn_return;
+ SSL *ssl = conn->ssl[sockindex].ssl;
+ long timeout_ms;
+
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+
+ /* Check to make sure handshake was ok. */
+ while(ssl_handshake_status(ssl) != SSL_OK) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ ssl_fcn_return = ssl_read(ssl, NULL);
+ if(ssl_fcn_return < 0) {
+ Curl_axtls_close(conn, sockindex);
+ ssl_display_error(ssl_fcn_return); /* goes to stdout. */
+ return map_error_to_curl(ssl_fcn_return);
+ }
+ /* TODO: avoid polling */
+#if !defined(_MSC_VER)
+ usleep(10000);
+#else
+ Sleep(10);
+#endif
+ }
+ infof (conn->data, "handshake completed successfully\n");
+
+ conn_step = connect_finish(conn, sockindex);
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+
+ return CURLE_OK;
+}
+
+/* return number of sent (non-SSL) bytes */
+static ssize_t axtls_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *err)
+{
+ /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
+ int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
+
+ infof(conn->data, " axtls_send\n");
+
+ if(rc < 0 ) {
+ *err = map_error_to_curl(rc);
+ rc = -1; /* generic error code for send failure */
+ }
+
+ *err = CURLE_OK;
+ return rc;
+}
+
+CURL_STATIC void Curl_axtls_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ infof(conn->data, " Curl_axtls_close\n");
+
+ /* line from openssl.c: (void)SSL_shutdown(connssl->ssl);
+ axTLS compat layer does nothing for SSL_shutdown */
+
+ /* The following line is from openssl.c. There seems to be no axTLS
+ equivalent. ssl_free and ssl_ctx_free close things.
+ SSL_set_connect_state(connssl->handle); */
+
+ free_ssl_structs(connssl);
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+CURL_STATIC int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
+{
+ /* Outline taken from openssl.c since functions are in axTLS compat layer.
+ axTLS's error set is much smaller, so a lot of error-handling was removed.
+ */
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ uint8_t *buf;
+ ssize_t nread;
+
+ infof(conn->data, " Curl_axtls_shutdown\n");
+
+ /* This has only been tested on the proftpd server, and the mod_tls code
+ sends a close notify alert without waiting for a close notify alert in
+ response. Thus we wait for a close notify alert from the server, but
+ we do not send one. Let's hope other servers do the same... */
+
+ /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ (void)SSL_shutdown(connssl->ssl);
+ */
+
+ if(connssl->ssl) {
+ int what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ if(what > 0) {
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server. buf is managed internally by
+ axTLS and will be released upon calling ssl_free via
+ free_ssl_structs. */
+ nread = (ssize_t)ssl_read(connssl->ssl, &buf);
+
+ if(nread < SSL_OK) {
+ failf(data, "close notify alert not received during shutdown");
+ retval = -1;
+ }
+ }
+ else if(0 == what) {
+ /* timeout */
+ failf(data, "SSL shutdown timeout");
+ }
+ else {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ retval = -1;
+ }
+
+ free_ssl_structs(connssl);
+ }
+ return retval;
+}
+
+static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *err)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
+ ssize_t ret = 0;
+ uint8_t *read_buf;
+
+ infof(conn->data, " axtls_recv\n");
+
+ *err = CURLE_OK;
+ if(connssl) {
+ ret = ssl_read(connssl->ssl, &read_buf);
+ if(ret > SSL_OK) {
+ /* ssl_read returns SSL_OK if there is more data to read, so if it is
+ larger, then all data has been read already. */
+ memcpy(buf, read_buf,
+ (size_t)ret > buffersize ? buffersize : (size_t)ret);
+ }
+ else if(ret == SSL_OK) {
+ /* more data to be read, signal caller to call again */
+ *err = CURLE_AGAIN;
+ ret = -1;
+ }
+ else if(ret == -3) {
+ /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
+ team approves proposed fix. */
+ Curl_axtls_close(conn, num);
+ }
+ else {
+ failf(conn->data, "axTLS recv error (%d)", ret);
+ *err = map_error_to_curl((int) ret);
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+CURL_STATIC int Curl_axtls_check_cxn(struct connectdata *conn)
+{
+ /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
+ axTLS compat layer always returns the last argument, so connection is
+ always alive? */
+
+ infof(conn->data, " Curl_axtls_check_cxn\n");
+ return 1; /* connection still in place */
+}
+
+CURL_STATIC void Curl_axtls_session_free(void *ptr)
+{
+ (void)ptr;
+ /* free the ID */
+ /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
+ compatibility layer does nothing, so we do nothing too. */
+}
+
+CURL_STATIC size_t Curl_axtls_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "axTLS/%s", ssl_version());
+}
+
+CURL_STATIC int Curl_axtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ static bool ssl_seeded = FALSE;
+ (void)data;
+ if(!ssl_seeded) {
+ ssl_seeded = TRUE;
+ /* Initialize the seed if not already done. This call is not exactly thread
+ * safe (and neither is the ssl_seeded check), but the worst effect of a
+ * race condition is that some global resources will leak. */
+ RNG_initialize();
+ }
+ get_random((int)length, entropy);
+ return 0;
+}
+
+#endif /* USE_AXTLS */
diff --git a/libcurl/src/lib/vtls/axtls.h b/libcurl/src/lib/vtls/axtls.h
new file mode 100644
index 0000000..e794fd9
--- /dev/null
+++ b/libcurl/src/lib/vtls/axtls.h
@@ -0,0 +1,71 @@
+#ifndef HEADER_CURL_AXTLS_H
+#define HEADER_CURL_AXTLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, DirecTV, Contact: Eric Hu <ehu@directv.com>
+ * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_AXTLS
+#include "curl/curl.h"
+#include "../urldata.h"
+
+CURL_STATIC int Curl_axtls_init(void);
+CURL_STATIC int Curl_axtls_cleanup(void);
+CURL_STATIC CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_axtls_connect_nonblocking(
+ struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+ /* close a SSL connection */
+CURL_STATIC void Curl_axtls_close(struct connectdata *conn, int sockindex);
+
+CURL_STATIC void Curl_axtls_session_free(void *ptr);
+CURL_STATIC size_t Curl_axtls_version(char *buffer, size_t size);
+CURL_STATIC int Curl_axtls_shutdown(struct connectdata *conn, int sockindex);
+CURL_STATIC int Curl_axtls_check_cxn(struct connectdata *conn);
+CURL_STATIC int Curl_axtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+
+/* Set the API backend definition to axTLS */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
+
+/* API setup for axTLS */
+#define curlssl_init Curl_axtls_init
+#define curlssl_cleanup Curl_axtls_cleanup
+#define curlssl_connect Curl_axtls_connect
+#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking
+#define curlssl_session_free(x) Curl_axtls_session_free(x)
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_axtls_close
+#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y)
+#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_axtls_version
+#define curlssl_check_cxn(x) Curl_axtls_check_cxn(x)
+#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_random(x,y,z) Curl_axtls_random(x,y,z)
+
+#endif /* USE_AXTLS */
+#endif /* HEADER_CURL_AXTLS_H */
+
diff --git a/libcurl/src/lib/vtls/cyassl.c b/libcurl/src/lib/vtls/cyassl.c
new file mode 100644
index 0000000..92ae083
--- /dev/null
+++ b/libcurl/src/lib/vtls/cyassl.c
@@ -0,0 +1,734 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+#include "../curl_setup.h"
+
+#ifdef USE_CYASSL
+
+#define WOLFSSL_OPTIONS_IGNORE_SYS
+/* CyaSSL's version.h, which should contain only the version, should come
+before all other CyaSSL includes and be immediately followed by build config
+aka options.h. http://curl.haxx.se/mail/lib-2015-04/0069.html */
+#include <cyassl/version.h>
+#if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008)
+#if defined(CYASSL_API) || defined(WOLFSSL_API)
+/* Safety measure. If either is defined some API include was already included
+and that's a problem since options.h hasn't been included yet. */
+#error "CyaSSL API was included before the CyaSSL build options."
+#endif
+#include <cyassl/options.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "cyassl.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "rawstr.h"
+#include "curl_printf.h"
+
+#include <cyassl/ssl.h>
+#ifdef HAVE_CYASSL_ERROR_SSL_H
+#include <cyassl/error-ssl.h>
+#else
+#include <cyassl/error.h>
+#endif
+#include <cyassl/ctaocrypt/random.h>
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#if LIBCYASSL_VERSION_HEX < 0x02007002 /* < 2.7.2 */
+#define CYASSL_MAX_ERROR_SZ 80
+#endif
+
+static Curl_recv cyassl_recv;
+static Curl_send cyassl_send;
+
+
+static int do_file_type(const char *type)
+{
+ if(!type || !type[0])
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "PEM"))
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "DER"))
+ return SSL_FILETYPE_ASN1;
+ return -1;
+}
+
+/*
+ * This function loads all the client/CA certificates and CRLs. Setup the TLS
+ * layer and do all necessary magic.
+ */
+static CURLcode
+cyassl_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ char error_buffer[CYASSL_MAX_ERROR_SZ];
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+ SSL_METHOD* req_method = NULL;
+ void* ssl_sessionid = NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+#ifdef HAVE_SNI
+ bool sni = FALSE;
+#define use_sni(x) sni = (x)
+#else
+#define use_sni(x) Curl_nop_stmt
+#endif
+
+ if(conssl->state == ssl_connection_complete)
+ return CURLE_OK;
+
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
+ /* minimum protocol version is set later after the CTX object is created */
+ req_method = SSLv23_client_method();
+#else
+ infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
+ "TLS 1.0 is used exclusively\n");
+ req_method = TLSv1_client_method();
+#endif
+ use_sni(TRUE);
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ req_method = TLSv1_client_method();
+ use_sni(TRUE);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ req_method = TLSv1_1_client_method();
+ use_sni(TRUE);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ req_method = TLSv1_2_client_method();
+ use_sni(TRUE);
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ req_method = SSLv3_client_method();
+ use_sni(FALSE);
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ failf(data, "CyaSSL does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(!req_method) {
+ failf(data, "SSL: couldn't create a method!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(conssl->ctx)
+ SSL_CTX_free(conssl->ctx);
+ conssl->ctx = SSL_CTX_new(req_method);
+
+ if(!conssl->ctx) {
+ failf(data, "SSL: couldn't create a context!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
+ /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever
+ minimum version of TLS was built in and at least TLS 1.0. For later library
+ versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so
+ we have this short circuit evaluation to find the minimum supported TLS
+ version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion
+ because only the former will work before the user's CTX callback is called.
+ */
+ if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) &&
+ (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) &&
+ (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) {
+ failf(data, "SSL: couldn't set the minimum protocol version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif
+ break;
+ }
+
+#ifndef NO_FILESYSTEM
+ /* load trusted cacert */
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
+ data->set.str[STRING_SSL_CAFILE],
+ data->set.str[STRING_SSL_CAPATH])) {
+ if(data->set.ssl.verifypeer) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:\n"
+ " CAfile: %s\n CApath: %s",
+ data->set.str[STRING_SSL_CAFILE]?
+ data->set.str[STRING_SSL_CAFILE]: "none",
+ data->set.str[STRING_SSL_CAPATH]?
+ data->set.str[STRING_SSL_CAPATH] : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Just continue with a warning if no strict certificate
+ verification is required. */
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway:\n");
+ }
+ }
+ else {
+ /* Everything is fine. */
+ infof(data, "successfully set certificate verify locations:\n");
+ }
+ infof(data,
+ " CAfile: %s\n"
+ " CApath: %s\n",
+ data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+ "none",
+ data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+ "none");
+ }
+
+ /* Load the client certificate, and private key */
+ if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
+ int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
+
+ if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
+ file_type) != 1) {
+ failf(data, "unable to use client certificate (no key or wrong pass"
+ " phrase?)");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
+ if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
+ file_type) != 1) {
+ failf(data, "unable to set private key");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+#endif /* !NO_FILESYSTEM */
+
+ /* SSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+ SSL_CTX_set_verify(conssl->ctx,
+ data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
+ NULL);
+
+#ifdef HAVE_SNI
+ if(sni) {
+ struct in_addr addr4;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+ size_t hostname_len = strlen(conn->host.name);
+ if((hostname_len < USHRT_MAX) &&
+ (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) &&
+#ifdef ENABLE_IPV6
+ (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) &&
+#endif
+ (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name,
+ (unsigned short)hostname_len) != 1)) {
+ infof(data, "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+ }
+ }
+#endif
+
+ /* give application a chance to interfere with SSL set up. */
+ if(data->set.ssl.fsslctx) {
+ CURLcode result = CURLE_OK;
+ result = (*data->set.ssl.fsslctx)(data, conssl->ctx,
+ data->set.ssl.fsslctxp);
+ if(result) {
+ failf(data, "error signaled by ssl ctx callback");
+ return result;
+ }
+ }
+#ifdef NO_FILESYSTEM
+ else if(data->set.ssl.verifypeer) {
+ failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
+ " with \"no filesystem\". Either disable peer verification"
+ " (insecure) or if you are building an application with libcurl you"
+ " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif
+
+ /* Let's make an SSL structure */
+ if(conssl->handle)
+ SSL_free(conssl->handle);
+ conssl->handle = SSL_new(conssl->ctx);
+ if(!conssl->handle) {
+ failf(data, "SSL: couldn't create a context (handle)!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Check if there's a cached ID we can/should use here! */
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
+ failf(data, "SSL: SSL_set_session failed: %s",
+ ERR_error_string(SSL_get_error(conssl->handle, 0), error_buffer));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof (data, "SSL re-using session ID\n");
+ }
+
+ /* pass the raw socket into the SSL layer */
+ if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
+ failf(data, "SSL: SSL_set_fd failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ conssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+}
+
+
+static CURLcode
+cyassl_connect_step2(struct connectdata *conn,
+ int sockindex)
+{
+ int ret = -1;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+
+ conn->recv[sockindex] = cyassl_recv;
+ conn->send[sockindex] = cyassl_send;
+
+ /* Enable RFC2818 checks */
+ if(data->set.ssl.verifyhost) {
+ ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
+ if(ret == SSL_FAILURE)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ ret = SSL_connect(conssl->handle);
+ if(ret != 1) {
+ char error_buffer[CYASSL_MAX_ERROR_SZ];
+ int detail = SSL_get_error(conssl->handle, ret);
+
+ if(SSL_ERROR_WANT_READ == detail) {
+ conssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+ else if(SSL_ERROR_WANT_WRITE == detail) {
+ conssl->connecting_state = ssl_connect_2_writing;
+ return CURLE_OK;
+ }
+ /* There is no easy way to override only the CN matching.
+ * This will enable the override of both mismatching SubjectAltNames
+ * as also mismatching CN fields */
+ else if(DOMAIN_NAME_MISMATCH == detail) {
+#if 1
+ failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
+ conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+#else
+ /* When the CyaSSL_check_domain_name() is used and you desire to continue
+ * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0',
+ * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
+ * way to do this is currently to switch the CyaSSL_check_domain_name()
+ * in and out based on the 'data->set.ssl.verifyhost' value. */
+ if(data->set.ssl.verifyhost) {
+ failf(data,
+ "\tsubject alt name(s) or common name do not match \"%s\"\n",
+ conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else {
+ infof(data,
+ "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
+ conn->host.dispname);
+ return CURLE_OK;
+ }
+#endif
+ }
+#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
+ else if(ASN_NO_SIGNER_E == detail) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "\tCA signer not available for verification\n");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Just continue with a warning if no strict certificate
+ verification is required. */
+ infof(data, "CA signer not available for verification, "
+ "continuing anyway\n");
+ }
+ }
+#endif
+ else {
+ failf(data, "SSL_connect failed with error %d: %s", detail,
+ ERR_error_string(detail, error_buffer));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ conssl->connecting_state = ssl_connect_3;
+ infof(data, "SSL connected\n");
+
+ return CURLE_OK;
+}
+
+
+static CURLcode
+cyassl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode result = CURLE_OK;
+ void *old_ssl_sessionid=NULL;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ bool incache;
+ SSL_SESSION *our_ssl_sessionid;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ our_ssl_sessionid = SSL_get_session(connssl->handle);
+
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+
+ if(!incache) {
+ result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ 0 /* unknown size */);
+ if(result) {
+ failf(data, "failed to store ssl session");
+ return result;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return result;
+}
+
+
+static ssize_t cyassl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ char error_buffer[CYASSL_MAX_ERROR_SZ];
+ int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
+ int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+
+ if(rc < 0) {
+ int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+
+ switch(err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_write() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data, "SSL write: %s, errno %d",
+ ERR_error_string(err, error_buffer),
+ SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ }
+ return rc;
+}
+
+CURL_STATIC void Curl_cyassl_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *conssl = &conn->ssl[sockindex];
+
+ if(conssl->handle) {
+ (void)SSL_shutdown(conssl->handle);
+ SSL_free (conssl->handle);
+ conssl->handle = NULL;
+ }
+ if(conssl->ctx) {
+ SSL_CTX_free (conssl->ctx);
+ conssl->ctx = NULL;
+ }
+}
+
+static ssize_t cyassl_recv(struct connectdata *conn,
+ int num,
+ char *buf,
+ size_t buffersize,
+ CURLcode *curlcode)
+{
+ char error_buffer[CYASSL_MAX_ERROR_SZ];
+ int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ int nread = SSL_read(conn->ssl[num].handle, buf, buffsize);
+
+ if(nread < 0) {
+ int err = SSL_get_error(conn->ssl[num].handle, nread);
+
+ switch(err) {
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_read() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(err, error_buffer),
+ SOCKERRNO);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ return nread;
+}
+
+
+CURL_STATIC void Curl_cyassl_session_free(void *ptr)
+{
+ (void)ptr;
+ /* CyaSSL reuses sessions on own, no free */
+}
+
+
+CURL_STATIC size_t Curl_cyassl_version(char *buffer, size_t size)
+{
+#ifdef WOLFSSL_VERSION
+ return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
+#elif defined(CYASSL_VERSION)
+ return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
+#else
+ return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
+#endif
+}
+
+
+CURL_STATIC int Curl_cyassl_init(void)
+{
+ return (CyaSSL_Init() == SSL_SUCCESS);
+}
+
+
+CURL_STATIC bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
+{
+ if(conn->ssl[connindex].handle) /* SSL is in use */
+ return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+CURL_STATIC int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
+{
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->handle) {
+ SSL_free (connssl->handle);
+ connssl->handle = NULL;
+ }
+ return retval;
+}
+
+
+static CURLcode
+cyassl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1==connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ result = cyassl_connect_step1(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ result = cyassl_connect_step2(conn, sockindex);
+ if(result || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return result;
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ result = cyassl_connect_step3(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = cyassl_recv;
+ conn->send[sockindex] = cyassl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+
+CURL_STATIC CURLcode
+Curl_cyassl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return cyassl_connect_common(conn, sockindex, TRUE, done);
+}
+
+
+CURL_STATIC CURLcode
+Curl_cyassl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = cyassl_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+CURL_STATIC int Curl_cyassl_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ RNG rng;
+ (void)data;
+ if(InitRng(&rng))
+ return 1;
+ if(length > UINT_MAX)
+ return 1;
+ if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
+ return 1;
+ return 0;
+}
+
+#endif
diff --git a/libcurl/src/lib/vtls/cyassl.h b/libcurl/src/lib/vtls/cyassl.h
new file mode 100644
index 0000000..0cc54a5
--- /dev/null
+++ b/libcurl/src/lib/vtls/cyassl.h
@@ -0,0 +1,70 @@
+#ifndef HEADER_CURL_CYASSL_H
+#define HEADER_CURL_CYASSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+#ifdef USE_CYASSL
+
+CURL_STATIC CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex);
+CURL_STATIC bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex);
+CURL_STATIC int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex);
+
+ /* close a SSL connection */
+CURL_STATIC void Curl_cyassl_close(struct connectdata *conn, int sockindex);
+
+CURL_STATIC void Curl_cyassl_session_free(void *ptr);
+CURL_STATIC size_t Curl_cyassl_version(char *buffer, size_t size);
+CURL_STATIC int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex);
+CURL_STATIC int Curl_cyassl_init(void);
+CURL_STATIC CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+CURL_STATIC int Curl_cyassl_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+
+/* Set the API backend definition to Schannel */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
+
+/* this backend supports CURLOPT_SSL_CTX_* */
+#define have_curlssl_ssl_ctx 1
+
+/* API setup for CyaSSL */
+#define curlssl_init Curl_cyassl_init
+#define curlssl_cleanup() Curl_nop_stmt
+#define curlssl_connect Curl_cyassl_connect
+#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking
+#define curlssl_session_free(x) Curl_cyassl_session_free(x)
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_cyassl_close
+#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y)
+#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_cyassl_version
+#define curlssl_check_cxn(x) ((void)x, -1)
+#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y)
+#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z)
+
+#endif /* USE_CYASSL */
+#endif /* HEADER_CURL_CYASSL_H */
diff --git a/libcurl/src/lib/vtls/darwinssl.c b/libcurl/src/lib/vtls/darwinssl.c
new file mode 100644
index 0000000..11f107f
--- /dev/null
+++ b/libcurl/src/lib/vtls/darwinssl.c
@@ -0,0 +1,2484 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all iOS and Mac OS X SecureTransport-specific code for the
+ * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
+ */
+
+#include "../curl_setup.h"
+
+#include "../urldata.h" /* for the SessionHandle definition */
+#include "../curl_base64.h"
+#include "../strtok.h"
+
+#ifdef USE_DARWINSSL
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <Security/Security.h>
+#include <Security/SecureTransport.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CommonCrypto/CommonDigest.h>
+
+/* The Security framework has changed greatly between iOS and different OS X
+ versions, and we will try to support as many of them as we can (back to
+ Leopard and iOS 5) by using macros and weak-linking.
+
+ IMPORTANT: If TLS 1.1 and 1.2 support are important for you on OS X, then
+ you must build this project against the 10.8 SDK or later. */
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
+#error "The darwinssl back-end requires Leopard or later."
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
+
+#define CURL_BUILD_IOS 0
+#define CURL_BUILD_IOS_7 0
+#define CURL_BUILD_MAC 1
+/* This is the maximum API level we are allowed to use when building: */
+#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
+/* These macros mean "the following code is present to allow runtime backward
+ compatibility with at least this cat or earlier":
+ (You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET
+ environmental variable.) */
+#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
+#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
+#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
+#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
+#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
+
+#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+#define CURL_BUILD_IOS 1
+#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
+#define CURL_BUILD_MAC 0
+#define CURL_BUILD_MAC_10_5 0
+#define CURL_BUILD_MAC_10_6 0
+#define CURL_BUILD_MAC_10_7 0
+#define CURL_BUILD_MAC_10_8 0
+#define CURL_SUPPORT_MAC_10_5 0
+#define CURL_SUPPORT_MAC_10_6 0
+#define CURL_SUPPORT_MAC_10_7 0
+#define CURL_SUPPORT_MAC_10_8 0
+#define CURL_SUPPORT_MAC_10_9 0
+
+#else
+#error "The darwinssl back-end requires iOS or OS X."
+#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
+
+#if CURL_BUILD_MAC
+#include <sys/sysctl.h>
+#endif /* CURL_BUILD_MAC */
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "connect.h"
+#include "select.h"
+#include "vtls.h"
+#include "darwinssl.h"
+#include "curl_printf.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* From MacTypes.h (which we can't include because it isn't present in iOS: */
+#define ioErr -36
+#define paramErr -50
+
+/* The following two functions were ripped from Apple sample code,
+ * with some modifications: */
+static OSStatus SocketRead(SSLConnectionRef connection,
+ void *data, /* owned by
+ * caller, data
+ * RETURNED */
+ size_t *dataLength) /* IN/OUT */
+{
+ size_t bytesToGo = *dataLength;
+ size_t initLen = bytesToGo;
+ UInt8 *currData = (UInt8 *)data;
+ /*int sock = *(int *)connection;*/
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
+ int sock = connssl->ssl_sockfd;
+ OSStatus rtn = noErr;
+ size_t bytesRead;
+ ssize_t rrtn;
+ int theErr;
+
+ *dataLength = 0;
+
+ for(;;) {
+ bytesRead = 0;
+ rrtn = read(sock, currData, bytesToGo);
+ if(rrtn <= 0) {
+ /* this is guesswork... */
+ theErr = errno;
+ if(rrtn == 0) { /* EOF = server hung up */
+ /* the framework will turn this into errSSLClosedNoNotify */
+ rtn = errSSLClosedGraceful;
+ }
+ else /* do the switch */
+ switch(theErr) {
+ case ENOENT:
+ /* connection closed */
+ rtn = errSSLClosedGraceful;
+ break;
+ case ECONNRESET:
+ rtn = errSSLClosedAbort;
+ break;
+ case EAGAIN:
+ rtn = errSSLWouldBlock;
+ connssl->ssl_direction = false;
+ break;
+ default:
+ rtn = ioErr;
+ break;
+ }
+ break;
+ }
+ else {
+ bytesRead = rrtn;
+ }
+ bytesToGo -= bytesRead;
+ currData += bytesRead;
+
+ if(bytesToGo == 0) {
+ /* filled buffer with incoming data, done */
+ break;
+ }
+ }
+ *dataLength = initLen - bytesToGo;
+
+ return rtn;
+}
+
+static OSStatus SocketWrite(SSLConnectionRef connection,
+ const void *data,
+ size_t *dataLength) /* IN/OUT */
+{
+ size_t bytesSent = 0;
+ /*int sock = *(int *)connection;*/
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
+ int sock = connssl->ssl_sockfd;
+ ssize_t length;
+ size_t dataLen = *dataLength;
+ const UInt8 *dataPtr = (UInt8 *)data;
+ OSStatus ortn;
+ int theErr;
+
+ *dataLength = 0;
+
+ do {
+ length = write(sock,
+ (char*)dataPtr + bytesSent,
+ dataLen - bytesSent);
+ } while((length > 0) &&
+ ( (bytesSent += length) < dataLen) );
+
+ if(length <= 0) {
+ theErr = errno;
+ if(theErr == EAGAIN) {
+ ortn = errSSLWouldBlock;
+ connssl->ssl_direction = true;
+ }
+ else {
+ ortn = ioErr;
+ }
+ }
+ else {
+ ortn = noErr;
+ }
+ *dataLength = bytesSent;
+ return ortn;
+}
+
+CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
+ switch (cipher) {
+ /* SSL version 3.0 */
+ case SSL_RSA_WITH_NULL_MD5:
+ return "SSL_RSA_WITH_NULL_MD5";
+ break;
+ case SSL_RSA_WITH_NULL_SHA:
+ return "SSL_RSA_WITH_NULL_SHA";
+ break;
+ case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
+ return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
+ break;
+ case SSL_RSA_WITH_RC4_128_MD5:
+ return "SSL_RSA_WITH_RC4_128_MD5";
+ break;
+ case SSL_RSA_WITH_RC4_128_SHA:
+ return "SSL_RSA_WITH_RC4_128_SHA";
+ break;
+ case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
+ break;
+ case SSL_RSA_WITH_IDEA_CBC_SHA:
+ return "SSL_RSA_WITH_IDEA_CBC_SHA";
+ break;
+ case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ return "SSL_RSA_WITH_DES_CBC_SHA";
+ break;
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DH_DSS_WITH_DES_CBC_SHA:
+ return "SSL_DH_DSS_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DH_RSA_WITH_DES_CBC_SHA:
+ return "SSL_DH_RSA_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
+ return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
+ break;
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ return "SSL_DH_anon_WITH_RC4_128_MD5";
+ break;
+ case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DH_anon_WITH_DES_CBC_SHA:
+ return "SSL_DH_anon_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
+ return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
+ break;
+ case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
+ return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
+ break;
+ /* TLS 1.0 with AES (RFC 3268)
+ (Apparently these are used in SSLv3 implementations as well.) */
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
+ break;
+ /* SSL version 2.0 */
+ case SSL_RSA_WITH_RC2_CBC_MD5:
+ return "SSL_RSA_WITH_RC2_CBC_MD5";
+ break;
+ case SSL_RSA_WITH_IDEA_CBC_MD5:
+ return "SSL_RSA_WITH_IDEA_CBC_MD5";
+ break;
+ case SSL_RSA_WITH_DES_CBC_MD5:
+ return "SSL_RSA_WITH_DES_CBC_MD5";
+ break;
+ case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
+ return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
+ break;
+ }
+ return "SSL_NULL_WITH_NULL_NULL";
+}
+
+CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
+ switch(cipher) {
+ /* TLS 1.0 with AES (RFC 3268) */
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
+ break;
+#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
+ /* TLS 1.0 with ECDSA (RFC 4492) */
+ case TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_NULL_SHA:
+ return "TLS_ECDH_RSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_NULL_SHA:
+ return "TLS_ECDHE_RSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_NULL_SHA:
+ return "TLS_ECDH_anon_WITH_NULL_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_RC4_128_SHA:
+ return "TLS_ECDH_anon_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
+ break;
+#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ /* TLS 1.2 (RFC 5246) */
+ case TLS_RSA_WITH_NULL_MD5:
+ return "TLS_RSA_WITH_NULL_MD5";
+ break;
+ case TLS_RSA_WITH_NULL_SHA:
+ return "TLS_RSA_WITH_NULL_SHA";
+ break;
+ case TLS_RSA_WITH_RC4_128_MD5:
+ return "TLS_RSA_WITH_RC4_128_MD5";
+ break;
+ case TLS_RSA_WITH_RC4_128_SHA:
+ return "TLS_RSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_RSA_WITH_NULL_SHA256:
+ return "TLS_RSA_WITH_NULL_SHA256";
+ break;
+ case TLS_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_RSA_WITH_AES_256_CBC_SHA256:
+ return "TLS_RSA_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+ return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+ return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+ return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+ return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+ return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DH_anon_WITH_RC4_128_MD5:
+ return "TLS_DH_anon_WITH_RC4_128_MD5";
+ break;
+ case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
+ return "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
+ return "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
+ break;
+ /* TLS 1.2 with AES GCM (RFC 5288) */
+ case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+ return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+ return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+ return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+ return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
+ return "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+ return "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
+ break;
+ /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_EMPTY_RENEGOTIATION_INFO_SCSV:
+ return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
+ break;
+#else
+ case SSL_RSA_WITH_NULL_MD5:
+ return "TLS_RSA_WITH_NULL_MD5";
+ break;
+ case SSL_RSA_WITH_NULL_SHA:
+ return "TLS_RSA_WITH_NULL_SHA";
+ break;
+ case SSL_RSA_WITH_RC4_128_MD5:
+ return "TLS_RSA_WITH_RC4_128_MD5";
+ break;
+ case SSL_RSA_WITH_RC4_128_SHA:
+ return "TLS_RSA_WITH_RC4_128_SHA";
+ break;
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ return "TLS_DH_anon_WITH_RC4_128_MD5";
+ break;
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ /* TLS PSK (RFC 4279): */
+ case TLS_PSK_WITH_RC4_128_SHA:
+ return "TLS_PSK_WITH_RC4_128_SHA";
+ break;
+ case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_PSK_WITH_AES_128_CBC_SHA:
+ return "TLS_PSK_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_PSK_WITH_AES_256_CBC_SHA:
+ return "TLS_PSK_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_RC4_128_SHA:
+ return "TLS_DHE_PSK_WITH_RC4_128_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_RC4_128_SHA:
+ return "TLS_RSA_PSK_WITH_RC4_128_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
+ break;
+ /* More TLS PSK (RFC 4785): */
+ case TLS_PSK_WITH_NULL_SHA:
+ return "TLS_PSK_WITH_NULL_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_NULL_SHA:
+ return "TLS_DHE_PSK_WITH_NULL_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_NULL_SHA:
+ return "TLS_RSA_PSK_WITH_NULL_SHA";
+ break;
+ /* Even more TLS PSK (RFC 5487): */
+ case TLS_PSK_WITH_AES_128_GCM_SHA256:
+ return "TLS_PSK_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_PSK_WITH_AES_256_GCM_SHA384:
+ return "TLS_PSK_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ return "TLS_PSK_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_PSK_WITH_AES_128_CBC_SHA256:
+ return "TLS_PSK_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_PSK_WITH_AES_256_CBC_SHA384:
+ return "TLS_PSK_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_PSK_WITH_NULL_SHA256:
+ return "TLS_PSK_WITH_NULL_SHA256";
+ break;
+ case TLS_PSK_WITH_NULL_SHA384:
+ return "TLS_PSK_WITH_NULL_SHA384";
+ break;
+ case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+ return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_DHE_PSK_WITH_NULL_SHA256:
+ return "TLS_DHE_PSK_WITH_NULL_SHA256";
+ break;
+ case TLS_DHE_PSK_WITH_NULL_SHA384:
+ return "TLS_RSA_PSK_WITH_NULL_SHA384";
+ break;
+ case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_RSA_PSK_WITH_NULL_SHA256:
+ return "TLS_RSA_PSK_WITH_NULL_SHA256";
+ break;
+ case TLS_RSA_PSK_WITH_NULL_SHA384:
+ return "TLS_RSA_PSK_WITH_NULL_SHA384";
+ break;
+#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+ }
+ return "TLS_NULL_WITH_NULL_NULL";
+}
+
+#if CURL_BUILD_MAC
+CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
+{
+ int mib[2];
+ char *os_version;
+ size_t os_version_len;
+ char *os_version_major, *os_version_minor/*, *os_version_point*/;
+ char *tok_buf;
+
+ /* Get the Darwin kernel version from the kernel using sysctl(): */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSRELEASE;
+ if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
+ return;
+ os_version = malloc(os_version_len*sizeof(char));
+ if(!os_version)
+ return;
+ if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
+ free(os_version);
+ return;
+ }
+
+ /* Parse the version: */
+ os_version_major = strtok_r(os_version, ".", &tok_buf);
+ os_version_minor = strtok_r(NULL, ".", &tok_buf);
+ /*os_version_point = strtok_r(NULL, ".", &tok_buf);*/
+ *major = atoi(os_version_major);
+ *minor = atoi(os_version_minor);
+ free(os_version);
+}
+#endif /* CURL_BUILD_MAC */
+
+/* Apple provides a myriad of ways of getting information about a certificate
+ into a string. Some aren't available under iOS or newer cats. So here's
+ a unified function for getting a string describing the certificate that
+ ought to work in all cats starting with Leopard. */
+CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
+{
+ CFStringRef server_cert_summary = CFSTR("(null)");
+
+#if CURL_BUILD_IOS
+ /* iOS: There's only one way to do this. */
+ server_cert_summary = SecCertificateCopySubjectSummary(cert);
+#else
+#if CURL_BUILD_MAC_10_7
+ /* Lion & later: Get the long description if we can. */
+ if(SecCertificateCopyLongDescription != NULL)
+ server_cert_summary =
+ SecCertificateCopyLongDescription(NULL, cert, NULL);
+ else
+#endif /* CURL_BUILD_MAC_10_7 */
+#if CURL_BUILD_MAC_10_6
+ /* Snow Leopard: Get the certificate summary. */
+ if(SecCertificateCopySubjectSummary != NULL)
+ server_cert_summary = SecCertificateCopySubjectSummary(cert);
+ else
+#endif /* CURL_BUILD_MAC_10_6 */
+ /* Leopard is as far back as we go... */
+ (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
+#endif /* CURL_BUILD_IOS */
+ return server_cert_summary;
+}
+
+#if CURL_SUPPORT_MAC_10_6
+/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
+ deprecation warnings, so let's not compile this unless it's necessary: */
+static OSStatus CopyIdentityWithLabelOldSchool(char *label,
+ SecIdentityRef *out_c_a_k)
+{
+ OSStatus status = errSecItemNotFound;
+ SecKeychainAttributeList attr_list;
+ SecKeychainAttribute attr;
+ SecKeychainSearchRef search = NULL;
+ SecCertificateRef cert = NULL;
+
+ /* Set up the attribute list: */
+ attr_list.count = 1L;
+ attr_list.attr = &attr;
+
+ /* Set up our lone search criterion: */
+ attr.tag = kSecLabelItemAttr;
+ attr.data = label;
+ attr.length = (UInt32)strlen(label);
+
+ /* Start searching: */
+ status = SecKeychainSearchCreateFromAttributes(NULL,
+ kSecCertificateItemClass,
+ &attr_list,
+ &search);
+ if(status == noErr) {
+ status = SecKeychainSearchCopyNext(search,
+ (SecKeychainItemRef *)&cert);
+ if(status == noErr && cert) {
+ /* If we found a certificate, does it have a private key? */
+ status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
+ CFRelease(cert);
+ }
+ }
+
+ if(search)
+ CFRelease(search);
+ return status;
+}
+#endif /* CURL_SUPPORT_MAC_10_6 */
+
+static OSStatus CopyIdentityWithLabel(char *label,
+ SecIdentityRef *out_cert_and_key)
+{
+ OSStatus status = errSecItemNotFound;
+
+#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
+ /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
+ kSecClassIdentity was introduced in Lion. If both exist, let's use them
+ to find the certificate. */
+ if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
+ CFTypeRef keys[4];
+ CFTypeRef values[4];
+ CFDictionaryRef query_dict;
+ CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
+ kCFStringEncodingUTF8);
+
+ /* Set up our search criteria and expected results: */
+ values[0] = kSecClassIdentity; /* we want a certificate and a key */
+ keys[0] = kSecClass;
+ values[1] = kCFBooleanTrue; /* we want a reference */
+ keys[1] = kSecReturnRef;
+ values[2] = kSecMatchLimitOne; /* one is enough, thanks */
+ keys[2] = kSecMatchLimit;
+ /* identity searches need a SecPolicyRef in order to work */
+ values[3] = SecPolicyCreateSSL(false, label_cf);
+ keys[3] = kSecMatchPolicy;
+ query_dict = CFDictionaryCreate(NULL, (const void **)keys,
+ (const void **)values, 4L,
+ &kCFCopyStringDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFRelease(values[3]);
+ CFRelease(label_cf);
+
+ /* Do we have a match? */
+ status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
+ CFRelease(query_dict);
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_6
+ /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
+ status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
+#endif /* CURL_SUPPORT_MAC_10_7 */
+ }
+#elif CURL_SUPPORT_MAC_10_6
+ /* For developers building on older cats, we have no choice but to fall back
+ to SecKeychainSearch. */
+ status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
+#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+ return status;
+}
+
+static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
+ const char *cPassword,
+ SecIdentityRef *out_cert_and_key)
+{
+ OSStatus status = errSecItemNotFound;
+ CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
+ (const UInt8 *)cPath, strlen(cPath), false);
+ CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
+ cPassword, kCFStringEncodingUTF8) : NULL;
+ CFDataRef pkcs_data = NULL;
+
+ /* We can import P12 files on iOS or OS X 10.7 or later: */
+ /* These constants are documented as having first appeared in 10.6 but they
+ raise linker errors when used on that cat for some reason. */
+#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
+ if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
+ NULL, NULL, &status)) {
+ const void *cKeys[] = {kSecImportExportPassphrase};
+ const void *cValues[] = {password};
+ CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
+ password ? 1L : 0L, NULL, NULL);
+ CFArrayRef items = NULL;
+
+ /* Here we go: */
+ status = SecPKCS12Import(pkcs_data, options, &items);
+ if(status == noErr && items && CFArrayGetCount(items)) {
+ CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
+ const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
+ kSecImportItemIdentity);
+
+ /* Retain the identity; we don't care about any other data... */
+ CFRetain(temp_identity);
+ *out_cert_and_key = (SecIdentityRef)temp_identity;
+ }
+
+ if(items)
+ CFRelease(items);
+ CFRelease(options);
+ CFRelease(pkcs_data);
+ }
+#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+ if(password)
+ CFRelease(password);
+ CFRelease(pkcs_url);
+ return status;
+}
+
+/* This code was borrowed from nss.c, with some modifications:
+ * Determine whether the nickname passed in is a filename that needs to
+ * be loaded as a PEM or a regular NSS nickname.
+ *
+ * returns 1 for a file
+ * returns 0 for not a file
+ */
+CF_INLINE bool is_file(const char *filename)
+{
+ struct_stat st;
+
+ if(filename == NULL)
+ return false;
+
+ if(stat(filename, &st) == 0)
+ return S_ISREG(st.st_mode);
+ return false;
+}
+
+static CURLcode darwinssl_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif /* ENABLE_IPV6 */
+ size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
+ SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
+ char *ssl_sessionid;
+ size_t ssl_sessionid_len;
+ OSStatus err = noErr;
+#if CURL_BUILD_MAC
+ int darwinver_maj = 0, darwinver_min = 0;
+
+ GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
+#endif /* CURL_BUILD_MAC */
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
+ if(connssl->ssl_ctx)
+ CFRelease(connssl->ssl_ctx);
+ connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
+ if(!connssl->ssl_ctx) {
+ failf(data, "SSL: couldn't create a context!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ /* The old ST API does not exist under iOS, so don't compile it: */
+#if CURL_SUPPORT_MAC_10_8
+ if(connssl->ssl_ctx)
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+ err = SSLNewContext(false, &(connssl->ssl_ctx));
+ if(err != noErr) {
+ failf(data, "SSL: couldn't create a context: OSStatus %d", err);
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#else
+ if(connssl->ssl_ctx)
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+ err = SSLNewContext(false, &(connssl->ssl_ctx));
+ if(err != noErr) {
+ failf(data, "SSL: couldn't create a context: OSStatus %d", err);
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+ connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */
+
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLSetProtocolVersionMax != NULL) {
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv3");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+ }
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocolAll,
+ false);
+ switch (data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol3,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv3");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol2,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#else
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ failf(data, "Your version of the OS does not support TLSv1.1");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_TLSv1_2:
+ failf(data, "Your version of the OS does not support TLSv1.2");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol2,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol3,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv3");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ }
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+
+ if(data->set.str[STRING_KEY]) {
+ infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
+ "Transport. The private key must be in the Keychain.\n");
+ }
+
+ if(data->set.str[STRING_CERT]) {
+ SecIdentityRef cert_and_key = NULL;
+ bool is_cert_file = is_file(data->set.str[STRING_CERT]);
+
+ /* User wants to authenticate with a client cert. Look for it:
+ If we detect that this is a file on disk, then let's load it.
+ Otherwise, assume that the user wants to use an identity loaded
+ from the Keychain. */
+ if(is_cert_file) {
+ if(!data->set.str[STRING_CERT_TYPE])
+ infof(data, "WARNING: SSL: Certificate type not set, assuming "
+ "PKCS#12 format.\n");
+ else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
+ strlen(data->set.str[STRING_CERT_TYPE])) != 0)
+ infof(data, "WARNING: SSL: The Security framework only supports "
+ "loading identities that are in PKCS#12 format.\n");
+
+ err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY_PASSWD], &cert_and_key);
+ }
+ else
+ err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
+
+ if(err == noErr) {
+ SecCertificateRef cert = NULL;
+ CFTypeRef certs_c[1];
+ CFArrayRef certs;
+
+ /* If we found one, print it out: */
+ err = SecIdentityCopyCertificate(cert_and_key, &cert);
+ if(err == noErr) {
+ CFStringRef cert_summary = CopyCertSubject(cert);
+ char cert_summary_c[128];
+
+ if(cert_summary) {
+ memset(cert_summary_c, 0, 128);
+ if(CFStringGetCString(cert_summary,
+ cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Client certificate: %s\n", cert_summary_c);
+ }
+ CFRelease(cert_summary);
+ CFRelease(cert);
+ }
+ }
+ certs_c[0] = cert_and_key;
+ certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
+ &kCFTypeArrayCallBacks);
+ err = SSLSetCertificate(connssl->ssl_ctx, certs);
+ if(certs)
+ CFRelease(certs);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ CFRelease(cert_and_key);
+ }
+ else {
+ switch(err) {
+ case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
+ failf(data, "SSL: Incorrect password for the certificate \"%s\" "
+ "and its private key.", data->set.str[STRING_CERT]);
+ break;
+ case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
+ failf(data, "SSL: Couldn't make sense of the data in the "
+ "certificate \"%s\" and its private key.",
+ data->set.str[STRING_CERT]);
+ break;
+ case -25260: /* errSecPassphraseRequired */
+ failf(data, "SSL The certificate \"%s\" requires a password.",
+ data->set.str[STRING_CERT]);
+ break;
+ case errSecItemNotFound:
+ failf(data, "SSL: Can't find the certificate \"%s\" and its private "
+ "key in the Keychain.", data->set.str[STRING_CERT]);
+ break;
+ default:
+ failf(data, "SSL: Can't load the certificate \"%s\" and its private "
+ "key: OSStatus %d", data->set.str[STRING_CERT], err);
+ break;
+ }
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* SSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
+ /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
+ a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
+ works, it doesn't work as expected under Snow Leopard or Lion.
+ So we need to call SSLSetEnableCertVerify() on those older cats in order
+ to disable certificate validation if the user turned that off.
+ (SecureTransport will always validate the certificate chain by
+ default.) */
+ /* (Note: Darwin 12.x.x is Mountain Lion.) */
+#if CURL_BUILD_MAC
+ if(SSLSetSessionOption != NULL && darwinver_maj >= 12) {
+#else
+ if(SSLSetSessionOption != NULL) {
+#endif /* CURL_BUILD_MAC */
+ bool break_on_auth = !data->set.ssl.verifypeer ||
+ data->set.str[STRING_SSL_CAFILE];
+ err = SSLSetSessionOption(connssl->ssl_ctx,
+ kSSLSessionOptionBreakOnServerAuth,
+ break_on_auth);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ data->set.ssl.verifypeer?true:false);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#else
+ err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ data->set.ssl.verifypeer?true:false);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
+
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]);
+
+ if(!is_cert_file) {
+ failf(data, "SSL: can't load CA certificate file %s",
+ data->set.str[STRING_SSL_CAFILE]);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ if(!data->set.ssl.verifypeer) {
+ failf(data, "SSL: CA certificate set, but certificate verification "
+ "is disabled");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* Configure hostname check. SNI is used if available.
+ * Both hostname check and SNI require SSLSetPeerDomainName().
+ * Also: the verifyhost setting influences SNI usage */
+ if(data->set.ssl.verifyhost) {
+ err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
+ strlen(conn->host.name));
+
+ if(err != noErr) {
+ infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
+ err);
+ }
+
+ if((Curl_inet_pton(AF_INET, conn->host.name, &addr))
+ #ifdef ENABLE_IPV6
+ || (Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+ #endif
+ ) {
+ infof(data, "WARNING: using IP address, SNI is being disabled by "
+ "the OS.\n");
+ }
+ }
+
+ /* Disable cipher suites that ST supports but are not safe. These ciphers
+ are unlikely to be used in any case since ST gives other ciphers a much
+ higher priority, but it's probably better that we not connect at all than
+ to give the user a false sense of security if the server only supports
+ insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
+ (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count);
+ all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ if(all_ciphers && allowed_ciphers &&
+ SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
+ &all_ciphers_count) == noErr) {
+ for(i = 0UL ; i < all_ciphers_count ; i++) {
+#if CURL_BUILD_MAC
+ /* There's a known bug in early versions of Mountain Lion where ST's ECC
+ ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
+ Work around the problem here by disabling those ciphers if we are
+ running in an affected version of OS X. */
+ if(darwinver_maj == 12 && darwinver_min <= 3 &&
+ all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
+ continue;
+ }
+#endif /* CURL_BUILD_MAC */
+ switch(all_ciphers[i]) {
+ /* Disable NULL ciphersuites: */
+ case SSL_NULL_WITH_NULL_NULL:
+ case SSL_RSA_WITH_NULL_MD5:
+ case SSL_RSA_WITH_NULL_SHA:
+ case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
+ case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
+ case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
+ case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
+ case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
+ case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
+ case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
+ case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
+ case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
+ case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
+ case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
+ case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
+ case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
+ case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
+ case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
+ /* Disable anonymous ciphersuites: */
+ case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_anon_WITH_DES_CBC_SHA:
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
+ case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
+ case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
+ case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+ case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
+ case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
+ case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
+ case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
+ case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
+ /* Disable weak key ciphersuites: */
+ case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
+ case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ case SSL_DH_DSS_WITH_DES_CBC_SHA:
+ case SSL_DH_RSA_WITH_DES_CBC_SHA:
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ /* Disable IDEA: */
+ case SSL_RSA_WITH_IDEA_CBC_SHA:
+ case SSL_RSA_WITH_IDEA_CBC_MD5:
+ break;
+ default: /* enable everything else */
+ allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
+ break;
+ }
+ }
+ err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
+ allowed_ciphers_count);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+ failf(data, "SSL: Failed to allocate memory for allowed ciphers");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ /* We want to enable 1/n-1 when using a CBC cipher unless the user
+ specifically doesn't want us doing that: */
+ if(SSLSetSessionOption != NULL) {
+ SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
+ !data->set.ssl_enable_beast);
+ SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
+ data->set.ssl.falsestart); /* false start support */
+ }
+#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+
+ /* Check if there's a cached ID we can/should use here! */
+ if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
+ &ssl_sessionid_len)) {
+ /* we got a session id, use it! */
+ err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof(data, "SSL re-using session ID\n");
+ }
+ /* If there isn't one, then let's make one up! This has to be done prior
+ to starting the handshake. */
+ else {
+ CURLcode result;
+ ssl_sessionid =
+ aprintf("%s:%d:%d:%s:%hu", data->set.str[STRING_SSL_CAFILE],
+ data->set.ssl.verifypeer, data->set.ssl.verifyhost,
+ conn->host.name, conn->remote_port);
+ ssl_sessionid_len = strlen(ssl_sessionid);
+
+ err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
+ if(result) {
+ failf(data, "failed to store ssl session");
+ return result;
+ }
+ }
+
+ err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* pass the raw socket into the SSL layers */
+ /* We need to store the FD in a constant memory address, because
+ * SSLSetConnection() will not copy that address. I've found that
+ * conn->sock[sockindex] may change on its own. */
+ connssl->ssl_sockfd = sockfd;
+ err = SSLSetConnection(connssl->ssl_ctx, connssl);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetConnection() failed: %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+}
+
+static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
+{
+ char *sep_start, *sep_end, *cert_start, *cert_end;
+ size_t i, j, err;
+ size_t len;
+ unsigned char *b64;
+
+ /* Jump through the separators at the beginning of the certificate. */
+ sep_start = strstr(in, "-----");
+ if(sep_start == NULL)
+ return 0;
+ cert_start = strstr(sep_start + 1, "-----");
+ if(cert_start == NULL)
+ return -1;
+
+ cert_start += 5;
+
+ /* Find separator after the end of the certificate. */
+ cert_end = strstr(cert_start, "-----");
+ if(cert_end == NULL)
+ return -1;
+
+ sep_end = strstr(cert_end + 1, "-----");
+ if(sep_end == NULL)
+ return -1;
+ sep_end += 5;
+
+ len = cert_end - cert_start;
+ b64 = malloc(len + 1);
+ if(!b64)
+ return -1;
+
+ /* Create base64 string without linefeeds. */
+ for(i = 0, j = 0; i < len; i++) {
+ if(cert_start[i] != '\r' && cert_start[i] != '\n')
+ b64[j++] = cert_start[i];
+ }
+ b64[j] = '\0';
+
+ err = Curl_base64_decode((const char *)b64, out, outlen);
+ free(b64);
+ if(err) {
+ free(*out);
+ return -1;
+ }
+
+ return sep_end - in;
+}
+
+static int read_cert(const char *file, unsigned char **out, size_t *outlen)
+{
+ int fd;
+ ssize_t n, len = 0, cap = 512;
+ unsigned char buf[cap], *data;
+
+ fd = open(file, 0);
+ if(fd < 0)
+ return -1;
+
+ data = malloc(cap);
+ if(!data) {
+ close(fd);
+ return -1;
+ }
+
+ for(;;) {
+ n = read(fd, buf, sizeof(buf));
+ if(n < 0) {
+ close(fd);
+ free(data);
+ return -1;
+ }
+ else if(n == 0) {
+ close(fd);
+ break;
+ }
+
+ if(len + n >= cap) {
+ cap *= 2;
+ data = realloc(data, cap);
+ if(!data) {
+ close(fd);
+ return -1;
+ }
+ }
+
+ memcpy(data + len, buf, n);
+ len += n;
+ }
+ data[len] = '\0';
+
+ *out = data;
+ *outlen = len;
+
+ return 0;
+}
+
+static int sslerr_to_curlerr(struct SessionHandle *data, int err)
+{
+ switch(err) {
+ case errSSLXCertChainInvalid:
+ failf(data, "SSL certificate problem: Invalid certificate chain");
+ return CURLE_SSL_CACERT;
+ case errSSLUnknownRootCert:
+ failf(data, "SSL certificate problem: Untrusted root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLNoRootCert:
+ failf(data, "SSL certificate problem: No root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLCertExpired:
+ failf(data, "SSL certificate problem: Certificate chain had an "
+ "expired certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLBadCert:
+ failf(data, "SSL certificate problem: Couldn't understand the server "
+ "certificate format");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLHostNameMismatch:
+ failf(data, "SSL certificate peer hostname mismatch");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ default:
+ failf(data, "SSL unexpected certificate error %d", err);
+ return CURLE_SSL_CACERT;
+ }
+}
+
+static int append_cert_to_array(struct SessionHandle *data,
+ unsigned char *buf, size_t buflen,
+ CFMutableArrayRef array)
+{
+ CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
+ if(!certdata) {
+ failf(data, "SSL: failed to allocate array for CA certificate");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ SecCertificateRef cacert =
+ SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
+ CFRelease(certdata);
+ if(!cacert) {
+ failf(data, "SSL: failed to create SecCertificate from CA certificate");
+ return CURLE_SSL_CACERT;
+ }
+
+ /* Check if cacert is valid. */
+ CFStringRef subject = CopyCertSubject(cacert);
+ if(subject) {
+ char subject_cbuf[128];
+ memset(subject_cbuf, 0, 128);
+ if(!CFStringGetCString(subject,
+ subject_cbuf,
+ 128,
+ kCFStringEncodingUTF8)) {
+ CFRelease(cacert);
+ failf(data, "SSL: invalid CA certificate subject");
+ return CURLE_SSL_CACERT;
+ }
+ CFRelease(subject);
+ }
+ else {
+ CFRelease(cacert);
+ failf(data, "SSL: invalid CA certificate");
+ return CURLE_SSL_CACERT;
+ }
+
+ CFArrayAppendValue(array, cacert);
+ CFRelease(cacert);
+
+ return CURLE_OK;
+}
+
+static int verify_cert(const char *cafile, struct SessionHandle *data,
+ SSLContextRef ctx)
+{
+ int n = 0, rc;
+ long res;
+ unsigned char *certbuf, *der;
+ size_t buflen, derlen, offset = 0;
+
+ if(read_cert(cafile, &certbuf, &buflen) < 0) {
+ failf(data, "SSL: failed to read or invalid CA certificate");
+ return CURLE_SSL_CACERT;
+ }
+
+ /*
+ * Certbuf now contains the contents of the certificate file, which can be
+ * - a single DER certificate,
+ * - a single PEM certificate or
+ * - a bunch of PEM certificates (certificate bundle).
+ *
+ * Go through certbuf, and convert any PEM certificate in it into DER
+ * format.
+ */
+ CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeArrayCallBacks);
+ if(array == NULL) {
+ free(certbuf);
+ failf(data, "SSL: out of memory creating CA certificate array");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ while(offset < buflen) {
+ n++;
+
+ /*
+ * Check if the certificate is in PEM format, and convert it to DER. If
+ * this fails, we assume the certificate is in DER format.
+ */
+ res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
+ if(res < 0) {
+ free(certbuf);
+ CFRelease(array);
+ failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle",
+ n, offset);
+ return CURLE_SSL_CACERT;
+ }
+ offset += res;
+
+ if(res == 0 && offset == 0) {
+ /* This is not a PEM file, probably a certificate in DER format. */
+ rc = append_cert_to_array(data, certbuf, buflen, array);
+ free(certbuf);
+ if(rc != CURLE_OK) {
+ CFRelease(array);
+ return rc;
+ }
+ break;
+ }
+ else if(res == 0) {
+ /* No more certificates in the bundle. */
+ free(certbuf);
+ break;
+ }
+
+ rc = append_cert_to_array(data, der, derlen, array);
+ free(der);
+ if(rc != CURLE_OK) {
+ free(certbuf);
+ CFRelease(array);
+ return rc;
+ }
+ }
+
+ SecTrustRef trust;
+ OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
+ if(trust == NULL) {
+ failf(data, "SSL: error getting certificate chain");
+ CFRelease(array);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else if(ret != noErr) {
+ CFRelease(array);
+ return sslerr_to_curlerr(data, ret);
+ }
+
+ ret = SecTrustSetAnchorCertificates(trust, array);
+ if(ret != noErr) {
+ CFRelease(trust);
+ return sslerr_to_curlerr(data, ret);
+ }
+ ret = SecTrustSetAnchorCertificatesOnly(trust, true);
+ if(ret != noErr) {
+ CFRelease(trust);
+ return sslerr_to_curlerr(data, ret);
+ }
+
+ SecTrustResultType trust_eval = 0;
+ ret = SecTrustEvaluate(trust, &trust_eval);
+ CFRelease(array);
+ CFRelease(trust);
+ if(ret != noErr) {
+ return sslerr_to_curlerr(data, ret);
+ }
+
+ switch (trust_eval) {
+ case kSecTrustResultUnspecified:
+ case kSecTrustResultProceed:
+ return CURLE_OK;
+
+ case kSecTrustResultRecoverableTrustFailure:
+ case kSecTrustResultDeny:
+ default:
+ failf(data, "SSL: certificate verification failed (result: %d)",
+ trust_eval);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+}
+
+static CURLcode
+darwinssl_connect_step2(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ OSStatus err;
+ SSLCipherSuite cipher;
+ SSLProtocol protocol = 0;
+
+ DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
+ || ssl_connect_2_reading == connssl->connecting_state
+ || ssl_connect_2_writing == connssl->connecting_state);
+
+ /* Here goes nothing: */
+ err = SSLHandshake(connssl->ssl_ctx);
+
+ if(err != noErr) {
+ switch (err) {
+ case errSSLWouldBlock: /* they're not done with us yet */
+ connssl->connecting_state = connssl->ssl_direction ?
+ ssl_connect_2_writing : ssl_connect_2_reading;
+ return CURLE_OK;
+
+ /* The below is errSSLServerAuthCompleted; it's not defined in
+ Leopard's headers */
+ case -9841:
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data,
+ connssl->ssl_ctx);
+ if(res != CURLE_OK)
+ return res;
+ }
+ /* the documentation says we need to call SSLHandshake() again */
+ return darwinssl_connect_step2(conn, sockindex);
+
+ /* These are all certificate problems with the server: */
+ case errSSLXCertChainInvalid:
+ failf(data, "SSL certificate problem: Invalid certificate chain");
+ return CURLE_SSL_CACERT;
+ case errSSLUnknownRootCert:
+ failf(data, "SSL certificate problem: Untrusted root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLNoRootCert:
+ failf(data, "SSL certificate problem: No root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLCertExpired:
+ failf(data, "SSL certificate problem: Certificate chain had an "
+ "expired certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLBadCert:
+ failf(data, "SSL certificate problem: Couldn't understand the server "
+ "certificate format");
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* These are all certificate problems with the client: */
+ case errSecAuthFailed:
+ failf(data, "SSL authentication failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLPeerHandshakeFail:
+ failf(data, "SSL peer handshake failed, the server most likely "
+ "requires a client certificate to connect");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLPeerUnknownCA:
+ failf(data, "SSL server rejected the client certificate due to "
+ "the certificate being signed by an unknown certificate "
+ "authority");
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* This error is raised if the server's cert didn't match the server's
+ host name: */
+ case errSSLHostNameMismatch:
+ failf(data, "SSL certificate peer verification failed, the "
+ "certificate did not match \"%s\"\n", conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ /* Generic handshake errors: */
+ case errSSLConnectionRefused:
+ failf(data, "Server dropped the connection during the SSL handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLClosedAbort:
+ failf(data, "Server aborted the SSL handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLNegotiation:
+ failf(data, "Could not negotiate an SSL cipher suite with the server");
+ return CURLE_SSL_CONNECT_ERROR;
+ /* Sometimes paramErr happens with buggy ciphers: */
+ case paramErr: case errSSLInternal:
+ failf(data, "Internal SSL engine error encountered during the "
+ "SSL handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLFatalAlert:
+ failf(data, "Fatal SSL engine error encountered during the SSL "
+ "handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unknown SSL protocol error in connection to %s:%d",
+ conn->host.name, err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+ /* we have been connected fine, we're not waiting for anything else. */
+ connssl->connecting_state = ssl_connect_3;
+
+ /* Informational message */
+ (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
+ (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
+ switch (protocol) {
+ case kSSLProtocol2:
+ infof(data, "SSL 2.0 connection using %s\n",
+ SSLCipherNameForNumber(cipher));
+ break;
+ case kSSLProtocol3:
+ infof(data, "SSL 3.0 connection using %s\n",
+ SSLCipherNameForNumber(cipher));
+ break;
+ case kTLSProtocol1:
+ infof(data, "TLS 1.0 connection using %s\n",
+ TLSCipherNameForNumber(cipher));
+ break;
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ case kTLSProtocol11:
+ infof(data, "TLS 1.1 connection using %s\n",
+ TLSCipherNameForNumber(cipher));
+ break;
+ case kTLSProtocol12:
+ infof(data, "TLS 1.2 connection using %s\n",
+ TLSCipherNameForNumber(cipher));
+ break;
+#endif
+ default:
+ infof(data, "Unknown protocol connection\n");
+ break;
+ }
+
+ return CURLE_OK;
+ }
+}
+
+static CURLcode
+darwinssl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CFStringRef server_cert_summary;
+ char server_cert_summary_c[128];
+ CFArrayRef server_certs = NULL;
+ SecCertificateRef server_cert;
+ OSStatus err;
+ CFIndex i, count;
+ SecTrustRef trust = NULL;
+
+ /* There is no step 3!
+ * Well, okay, if verbose mode is on, let's print the details of the
+ * server certificates. */
+#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
+#if CURL_BUILD_IOS
+#pragma unused(server_certs)
+ err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
+ a null trust, so be on guard for that: */
+ if(err == noErr && trust) {
+ count = SecTrustGetCertificateCount(trust);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = SecTrustGetCertificateAtIndex(trust, i);
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(trust);
+ }
+#else
+ /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
+ The function SecTrustGetCertificateAtIndex() is officially present
+ in Lion, but it is unfortunately also present in Snow Leopard as
+ private API and doesn't work as expected. So we have to look for
+ a different symbol to make sure this code is only executed under
+ Lion or later. */
+ if(SecTrustEvaluateAsync != NULL) {
+#pragma unused(server_certs)
+ err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
+ a null trust, so be on guard for that: */
+ if(err == noErr && trust) {
+ count = SecTrustGetCertificateCount(trust);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = SecTrustGetCertificateAtIndex(trust, i);
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(trust);
+ }
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ /* Just in case SSLCopyPeerCertificates() returns null too... */
+ if(err == noErr && server_certs) {
+ count = CFArrayGetCount(server_certs);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
+ i);
+
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(server_certs);
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#endif /* CURL_BUILD_IOS */
+#else
+#pragma unused(trust)
+ err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ if(err == noErr) {
+ count = CFArrayGetCount(server_certs);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(server_certs);
+ }
+#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+
+ connssl->connecting_state = ssl_connect_done;
+ return CURLE_OK;
+}
+
+static Curl_recv darwinssl_recv;
+static Curl_send darwinssl_send;
+
+static CURLcode
+darwinssl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1==connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ result = darwinssl_connect_step1(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading ||
+ connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing ==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading ==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if this
+ * connection is done nonblocking and this loop would execute again. This
+ * permits the owner of a multi handle to abort a connection attempt
+ * before step2 has completed while ensuring that a client using select()
+ * or epoll() will always have a valid fdset to wait on.
+ */
+ result = darwinssl_connect_step2(conn, sockindex);
+ if(result || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return result;
+
+ } /* repeat step2 until all transactions are done. */
+
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ result = darwinssl_connect_step3(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = darwinssl_recv;
+ conn->send[sockindex] = darwinssl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode
+Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return darwinssl_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURL_STATIC CURLcode
+Curl_darwinssl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = darwinssl_connect_common(conn, sockindex, FALSE, &done);
+
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->ssl_ctx) {
+ (void)SSLClose(connssl->ssl_ctx);
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLCreateContext != NULL)
+ CFRelease(connssl->ssl_ctx);
+#if CURL_SUPPORT_MAC_10_8
+ else
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+#endif /* CURL_SUPPORT_MAC_10_8 */
+#else
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+ connssl->ssl_ctx = NULL;
+ }
+ connssl->ssl_sockfd = 0;
+}
+
+CURL_STATIC int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ ssize_t nread;
+ int what;
+ int rc;
+ char buf[120];
+
+ if(!connssl->ssl_ctx)
+ return 0;
+
+ if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
+ return 0;
+
+ Curl_darwinssl_close(conn, sockindex);
+
+ rc = 0;
+
+ what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+
+ for(;;) {
+ if(what < 0) {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ rc = -1;
+ break;
+ }
+
+ if(!what) { /* timeout */
+ failf(data, "SSL shutdown timeout");
+ break;
+ }
+
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server. No way to SSL_Read now, so use read(). */
+
+ nread = read(conn->sock[sockindex], buf, sizeof(buf));
+
+ if(nread < 0) {
+ failf(data, "read: %s", strerror(errno));
+ rc = -1;
+ }
+
+ if(nread <= 0)
+ break;
+
+ what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ }
+
+ return rc;
+}
+
+CURL_STATIC void Curl_darwinssl_session_free(void *ptr)
+{
+ /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
+ cached session ID inside the Security framework. There is a private
+ function that does this, but I don't want to have to explain to you why I
+ got your application rejected from the App Store due to the use of a
+ private API, so the best we can do is free up our own char array that we
+ created way back in darwinssl_connect_step1... */
+ Curl_safefree(ptr);
+}
+
+CURL_STATIC size_t Curl_darwinssl_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "SecureTransport");
+}
+
+/*
+ * This function uses SSLGetSessionState to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+CURL_STATIC int Curl_darwinssl_check_cxn(struct connectdata *conn)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+ OSStatus err;
+ SSLSessionState state;
+
+ if(connssl->ssl_ctx) {
+ err = SSLGetSessionState(connssl->ssl_ctx, &state);
+ if(err == noErr)
+ return state == kSSLConnected || state == kSSLHandshake;
+ return -1;
+ }
+ return 0;
+}
+
+CURL_STATIC bool Curl_darwinssl_data_pending(const struct connectdata *conn,
+ int connindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+ OSStatus err;
+ size_t buffer;
+
+ if(connssl->ssl_ctx) { /* SSL is in use */
+ err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer);
+ if(err == noErr)
+ return buffer > 0UL;
+ return false;
+ }
+ else
+ return false;
+}
+
+CURL_STATIC int Curl_darwinssl_random(unsigned char *entropy,
+ size_t length)
+{
+ /* arc4random_buf() isn't available on cats older than Lion, so let's
+ do this manually for the benefit of the older cats. */
+ size_t i;
+ u_int32_t random_number = 0;
+
+ for(i = 0 ; i < length ; i++) {
+ if(i % sizeof(u_int32_t) == 0)
+ random_number = arc4random();
+ entropy[i] = random_number & 0xFF;
+ random_number >>= 8;
+ }
+ i = random_number = 0;
+ return 0;
+}
+
+CURL_STATIC void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+ (void)md5len;
+ (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
+}
+
+bool Curl_darwinssl_false_start(void) {
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ if(SSLSetSessionOption != NULL)
+ return TRUE;
+#endif
+ return FALSE;
+}
+
+static ssize_t darwinssl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ /*struct SessionHandle *data = conn->data;*/
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ size_t processed = 0UL;
+ OSStatus err;
+
+ /* The SSLWrite() function works a little differently than expected. The
+ fourth argument (processed) is currently documented in Apple's
+ documentation as: "On return, the length, in bytes, of the data actually
+ written."
+
+ Now, one could interpret that as "written to the socket," but actually,
+ it returns the amount of data that was written to a buffer internal to
+ the SSLContextRef instead. So it's possible for SSLWrite() to return
+ errSSLWouldBlock and a number of bytes "written" because those bytes were
+ encrypted and written to a buffer, not to the socket.
+
+ So if this happens, then we need to keep calling SSLWrite() over and
+ over again with no new data until it quits returning errSSLWouldBlock. */
+
+ /* Do we have buffered data to write from the last time we were called? */
+ if(connssl->ssl_write_buffered_length) {
+ /* Write the buffered data: */
+ err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
+ switch (err) {
+ case noErr:
+ /* processed is always going to be 0 because we didn't write to
+ the buffer, so return how much was written to the socket */
+ processed = connssl->ssl_write_buffered_length;
+ connssl->ssl_write_buffered_length = 0UL;
+ break;
+ case errSSLWouldBlock: /* argh, try again */
+ *curlcode = CURLE_AGAIN;
+ return -1L;
+ default:
+ failf(conn->data, "SSLWrite() returned error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1L;
+ }
+ }
+ else {
+ /* We've got new data to write: */
+ err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
+ if(err != noErr) {
+ switch (err) {
+ case errSSLWouldBlock:
+ /* Data was buffered but not sent, we have to tell the caller
+ to try sending again, and remember how much was buffered */
+ connssl->ssl_write_buffered_length = len;
+ *curlcode = CURLE_AGAIN;
+ return -1L;
+ default:
+ failf(conn->data, "SSLWrite() returned error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1L;
+ }
+ }
+ }
+ return (ssize_t)processed;
+}
+
+static ssize_t darwinssl_recv(struct connectdata *conn,
+ int num,
+ char *buf,
+ size_t buffersize,
+ CURLcode *curlcode)
+{
+ /*struct SessionHandle *data = conn->data;*/
+ struct ssl_connect_data *connssl = &conn->ssl[num];
+ size_t processed = 0UL;
+ OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
+
+ if(err != noErr) {
+ switch (err) {
+ case errSSLWouldBlock: /* return how much we read (if anything) */
+ if(processed)
+ return (ssize_t)processed;
+ *curlcode = CURLE_AGAIN;
+ return -1L;
+ break;
+
+ /* errSSLClosedGraceful - server gracefully shut down the SSL session
+ errSSLClosedNoNotify - server hung up on us instead of sending a
+ closure alert notice, read() is returning 0
+ Either way, inform the caller that the server disconnected. */
+ case errSSLClosedGraceful:
+ case errSSLClosedNoNotify:
+ *curlcode = CURLE_OK;
+ return -1L;
+ break;
+
+ default:
+ failf(conn->data, "SSLRead() return error %d", err);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1L;
+ break;
+ }
+ }
+ return (ssize_t)processed;
+}
+
+#endif /* USE_DARWINSSL */
diff --git a/libcurl/src/lib/vtls/darwinssl.h b/libcurl/src/lib/vtls/darwinssl.h
new file mode 100644
index 0000000..f287eca
--- /dev/null
+++ b/libcurl/src/lib/vtls/darwinssl.h
@@ -0,0 +1,76 @@
+#ifndef HEADER_CURL_DARWINSSL_H
+#define HEADER_CURL_DARWINSSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+#ifdef USE_DARWINSSL
+
+CURL_STATIC CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex);
+
+CURL_STATIC CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+/* close a SSL connection */
+CURL_STATIC void Curl_darwinssl_close(struct connectdata *conn, int sockindex);
+
+CURL_STATIC void Curl_darwinssl_session_free(void *ptr);
+CURL_STATIC size_t Curl_darwinssl_version(char *buffer, size_t size);
+CURL_STATIC int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
+CURL_STATIC int Curl_darwinssl_check_cxn(struct connectdata *conn);
+CURL_STATIC bool Curl_darwinssl_data_pending(const struct connectdata *conn,
+ int connindex);
+
+CURL_STATIC int Curl_darwinssl_random(unsigned char *entropy,
+ size_t length);
+CURL_STATIC void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+bool Curl_darwinssl_false_start(void);
+
+/* Set the API backend definition to SecureTransport */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
+
+/* API setup for SecureTransport */
+#define curlssl_init() (1)
+#define curlssl_cleanup() Curl_nop_stmt
+#define curlssl_connect Curl_darwinssl_connect
+#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking
+#define curlssl_session_free(x) Curl_darwinssl_session_free(x)
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_darwinssl_close
+#define curlssl_shutdown(x,y) 0
+#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_darwinssl_version
+#define curlssl_check_cxn Curl_darwinssl_check_cxn
+#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
+#define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z))
+#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
+#define curlssl_false_start() Curl_darwinssl_false_start()
+
+#endif /* USE_DARWINSSL */
+#endif /* HEADER_CURL_DARWINSSL_H */
diff --git a/libcurl/src/lib/vtls/gskit.c b/libcurl/src/lib/vtls/gskit.c
new file mode 100644
index 0000000..f683c76
--- /dev/null
+++ b/libcurl/src/lib/vtls/gskit.c
@@ -0,0 +1,1069 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "../curl_setup.h"
+
+#ifdef USE_GSKIT
+
+#include <gskssl.h>
+#include <qsoasync.h>
+
+/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
+#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
+#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
+#endif
+
+#ifndef GSK_TLSV10_CIPHER_SPECS
+#define GSK_TLSV10_CIPHER_SPECS 236
+#endif
+
+#ifndef GSK_TLSV11_CIPHER_SPECS
+#define GSK_TLSV11_CIPHER_SPECS 237
+#endif
+
+#ifndef GSK_TLSV12_CIPHER_SPECS
+#define GSK_TLSV12_CIPHER_SPECS 238
+#endif
+
+#ifndef GSK_PROTOCOL_TLSV11
+#define GSK_PROTOCOL_TLSV11 437
+#endif
+
+#ifndef GSK_PROTOCOL_TLSV12
+#define GSK_PROTOCOL_TLSV12 438
+#endif
+
+#ifndef GSK_FALSE
+#define GSK_FALSE 0
+#endif
+
+#ifndef GSK_TRUE
+#define GSK_TRUE 1
+#endif
+
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "gskit.h"
+#include "vtls.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "strequal.h"
+#include "x509asn1.h"
+#include "curl_printf.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+/* SSL version flags. */
+#define CURL_GSKPROTO_SSLV2 0
+#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
+#define CURL_GSKPROTO_SSLV3 1
+#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
+#define CURL_GSKPROTO_TLSV10 2
+#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
+#define CURL_GSKPROTO_TLSV11 3
+#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
+#define CURL_GSKPROTO_TLSV12 4
+#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
+#define CURL_GSKPROTO_LAST 5
+
+
+/* Supported ciphers. */
+typedef struct {
+ const char *name; /* Cipher name. */
+ const char *gsktoken; /* Corresponding token for GSKit String. */
+ unsigned int versions; /* SSL version flags. */
+} gskit_cipher;
+
+static const gskit_cipher ciphertable[] = {
+ { "null-md5", "01",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "null-sha", "02",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "exp-rc4-md5", "03",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
+ { "rc4-md5", "04",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "rc4-sha", "05",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "exp-rc2-cbc-md5", "06",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
+ { "exp-des-cbc-sha", "09",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK },
+ { "des-cbc3-sha", "0A",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "aes128-sha", "2F",
+ CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
+ CURL_GSKPROTO_TLSV12_MASK },
+ { "aes256-sha", "35",
+ CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
+ CURL_GSKPROTO_TLSV12_MASK },
+ { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
+ { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
+ { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
+ { "aes128-gcm-sha256",
+ "9C", CURL_GSKPROTO_TLSV12_MASK },
+ { "aes256-gcm-sha384",
+ "9D", CURL_GSKPROTO_TLSV12_MASK },
+ { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
+ { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
+ { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
+ { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
+ { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
+ { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
+ { (const char *) NULL, (const char *) NULL, 0 }
+};
+
+
+static bool is_separator(char c)
+{
+ /* Return whether character is a cipher list separator. */
+ switch (c) {
+ case ' ':
+ case '\t':
+ case ':':
+ case ',':
+ case ';':
+ return true;
+ }
+ return false;
+}
+
+
+static CURLcode gskit_status(struct SessionHandle *data, int rc,
+ const char *procname, CURLcode defcode)
+{
+ /* Process GSKit status and map it to a CURLcode. */
+ switch (rc) {
+ case GSK_OK:
+ case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
+ return CURLE_OK;
+ case GSK_KEYRING_OPEN_ERROR:
+ case GSK_OS400_ERROR_NO_ACCESS:
+ return CURLE_SSL_CACERT_BADFILE;
+ case GSK_INSUFFICIENT_STORAGE:
+ return CURLE_OUT_OF_MEMORY;
+ case GSK_ERROR_BAD_V2_CIPHER:
+ case GSK_ERROR_BAD_V3_CIPHER:
+ case GSK_ERROR_NO_CIPHERS:
+ return CURLE_SSL_CIPHER;
+ case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
+ case GSK_ERROR_CERT_VALIDATION:
+ return CURLE_PEER_FAILED_VERIFICATION;
+ case GSK_OS400_ERROR_TIMED_OUT:
+ return CURLE_OPERATION_TIMEDOUT;
+ case GSK_WOULD_BLOCK:
+ return CURLE_AGAIN;
+ case GSK_OS400_ERROR_NOT_REGISTERED:
+ break;
+ case GSK_ERROR_IO:
+ switch (errno) {
+ case ENOMEM:
+ return CURLE_OUT_OF_MEMORY;
+ default:
+ failf(data, "%s I/O error: %s", procname, strerror(errno));
+ break;
+ }
+ break;
+ default:
+ failf(data, "%s: %s", procname, gsk_strerror(rc));
+ break;
+ }
+ return defcode;
+}
+
+
+static CURLcode set_enum(struct SessionHandle *data, gsk_handle h,
+ GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
+{
+ int rc = gsk_attribute_set_enum(h, id, value);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
+ break;
+ case GSK_ATTRIBUTE_INVALID_ID:
+ if(unsupported_ok)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ default:
+ failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_buffer(struct SessionHandle *data, gsk_handle h,
+ GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
+{
+ int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
+ break;
+ case GSK_ATTRIBUTE_INVALID_ID:
+ if(unsupported_ok)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ default:
+ failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_numeric(struct SessionHandle *data,
+ gsk_handle h, GSK_NUM_ID id, int value)
+{
+ int rc = gsk_attribute_set_numeric_value(h, id, value);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
+ strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_callback(struct SessionHandle *data,
+ gsk_handle h, GSK_CALLBACK_ID id, void *info)
+{
+ int rc = gsk_attribute_set_callback(h, id, info);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_ciphers(struct SessionHandle *data,
+ gsk_handle h, unsigned int *protoflags)
+{
+ const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
+ const char *clp;
+ const gskit_cipher *ctp;
+ int i;
+ int l;
+ bool unsupported;
+ CURLcode result;
+ struct {
+ char *buf;
+ char *ptr;
+ } ciphers[CURL_GSKPROTO_LAST];
+
+ /* Compile cipher list into GSKit-compatible cipher lists. */
+
+ if(!cipherlist)
+ return CURLE_OK;
+ while(is_separator(*cipherlist)) /* Skip initial separators. */
+ cipherlist++;
+ if(!*cipherlist)
+ return CURLE_OK;
+
+ /* We allocate GSKit buffers of the same size as the input string: since
+ GSKit tokens are always shorter than their cipher names, allocated buffers
+ will always be large enough to accomodate the result. */
+ l = strlen(cipherlist) + 1;
+ memset((char *) ciphers, 0, sizeof ciphers);
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
+ ciphers[i].buf = malloc(l);
+ if(!ciphers[i].buf) {
+ while(i--)
+ free(ciphers[i].buf);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ciphers[i].ptr = ciphers[i].buf;
+ *ciphers[i].ptr = '\0';
+ }
+
+ /* Process each cipher in input string. */
+ unsupported = FALSE;
+ result = CURLE_OK;
+ for(;;) {
+ for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
+ cipherlist++;
+ l = cipherlist - clp;
+ if(!l)
+ break;
+ /* Search the cipher in our table. */
+ for(ctp = ciphertable; ctp->name; ctp++)
+ if(strnequal(ctp->name, clp, l) && !ctp->name[l])
+ break;
+ if(!ctp->name) {
+ failf(data, "Unknown cipher %.*s", l, clp);
+ result = CURLE_SSL_CIPHER;
+ }
+ else {
+ unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
+ if(ctp->versions & (1 << i)) {
+ strcpy(ciphers[i].ptr, ctp->gsktoken);
+ ciphers[i].ptr += strlen(ctp->gsktoken);
+ }
+ }
+ }
+
+ /* Advance to next cipher name or end of string. */
+ while(is_separator(*cipherlist))
+ cipherlist++;
+ }
+
+ /* Disable protocols with empty cipher lists. */
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
+ if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
+ *protoflags &= ~(1 << i);
+ ciphers[i].buf[0] = '\0';
+ }
+ }
+
+ /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
+ if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
+ result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ result = CURLE_OK;
+ if(unsupported) {
+ failf(data, "TLSv1.1-only ciphers are not yet supported");
+ result = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+ if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
+ result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ result = CURLE_OK;
+ if(unsupported) {
+ failf(data, "TLSv1.2-only ciphers are not yet supported");
+ result = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+
+ /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
+ the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
+ if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
+ result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ result = CURLE_OK;
+ strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
+ ciphers[CURL_GSKPROTO_TLSV10].ptr);
+ }
+ }
+
+ /* Set-up other ciphers. */
+ if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
+ result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
+ if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
+ result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
+
+ /* Clean-up. */
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++)
+ free(ciphers[i].buf);
+
+ return result;
+}
+
+
+CURL_STATIC int Curl_gskit_init(void)
+{
+ /* No initialisation needed. */
+
+ return 1;
+}
+
+
+CURL_STATIC void Curl_gskit_cleanup(void)
+{
+ /* Nothing to do. */
+}
+
+
+static CURLcode init_environment(struct SessionHandle *data,
+ gsk_handle *envir, const char *appid,
+ const char *file, const char *label,
+ const char *password)
+{
+ int rc;
+ CURLcode result;
+ gsk_handle h;
+
+ /* Creates the GSKit environment. */
+
+ rc = gsk_environment_open(&h);
+ switch (rc) {
+ case GSK_OK:
+ break;
+ case GSK_INSUFFICIENT_STORAGE:
+ return CURLE_OUT_OF_MEMORY;
+ default:
+ failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
+ if(!result && appid)
+ result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
+ if(!result && file)
+ result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
+ if(!result && label)
+ result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
+ if(!result && password)
+ result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
+
+ if(!result) {
+ /* Locate CAs, Client certificate and key according to our settings.
+ Note: this call may be blocking for some tenths of seconds. */
+ result = gskit_status(data, gsk_environment_init(h),
+ "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
+ if(!result) {
+ *envir = h;
+ return result;
+ }
+ }
+ /* Error: rollback. */
+ gsk_environment_close(&h);
+ return result;
+}
+
+
+static void cancel_async_handshake(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ Qso_OverlappedIO_t cstat;
+
+ if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
+ QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
+}
+
+
+static void close_async_handshake(struct ssl_connect_data *connssl)
+{
+ QsoDestroyIOCompletionPort(connssl->iocport);
+ connssl->iocport = -1;
+}
+
+
+static void close_one(struct ssl_connect_data *conn,
+ struct SessionHandle *data)
+{
+ if(conn->handle) {
+ gskit_status(data, gsk_secure_soc_close(&conn->handle),
+ "gsk_secure_soc_close()", 0);
+ conn->handle = (gsk_handle) NULL;
+ }
+ if(conn->iocport >= 0)
+ close_async_handshake(conn);
+}
+
+
+static ssize_t gskit_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *curlcode)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode cc;
+ int written;
+
+ cc = gskit_status(data,
+ gsk_secure_soc_write(conn->ssl[sockindex].handle,
+ (char *) mem, (int) len, &written),
+ "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+ if(cc != CURLE_OK) {
+ *curlcode = cc;
+ written = -1;
+ }
+ return (ssize_t) written; /* number of bytes */
+}
+
+
+static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
+ size_t buffersize, CURLcode *curlcode)
+{
+ struct SessionHandle *data = conn->data;
+ int buffsize;
+ int nread;
+ CURLcode cc;
+
+ buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
+ cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+ buf, buffsize, &nread),
+ "gsk_secure_soc_read()", CURLE_RECV_ERROR);
+ if(cc != CURLE_OK) {
+ *curlcode = cc;
+ nread = -1;
+ }
+ return (ssize_t) nread;
+}
+
+
+static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ gsk_handle envir;
+ CURLcode result;
+ int rc;
+ char *keyringfile;
+ char *keyringpwd;
+ char *keyringlabel;
+ char *sni;
+ unsigned int protoflags;
+ long timeout;
+ Qso_OverlappedIO_t commarea;
+
+ /* Create SSL environment, start (preferably asynchronous) handshake. */
+
+ connssl->handle = (gsk_handle) NULL;
+ connssl->iocport = -1;
+
+ /* GSKit supports two ways of specifying an SSL context: either by
+ * application identifier (that should have been defined at the system
+ * level) or by keyring file, password and certificate label.
+ * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
+ * application identifier of the certificate label.
+ * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
+ * It is not possible to have different keyrings for the CAs and the
+ * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
+ * the keyring file.
+ * If no key password is given and the keyring is the system keyring,
+ * application identifier mode is tried first, as recommended in IBM doc.
+ */
+
+ keyringfile = data->set.str[STRING_SSL_CAFILE];
+ keyringpwd = data->set.str[STRING_KEY_PASSWD];
+ keyringlabel = data->set.str[STRING_CERT];
+ envir = (gsk_handle) NULL;
+
+ if(keyringlabel && *keyringlabel && !keyringpwd &&
+ !strcmp(keyringfile, CURL_CA_BUNDLE)) {
+ /* Try application identifier mode. */
+ init_environment(data, &envir, keyringlabel, (const char *) NULL,
+ (const char *) NULL, (const char *) NULL);
+ }
+
+ if(!envir) {
+ /* Use keyring mode. */
+ result = init_environment(data, &envir, (const char *) NULL,
+ keyringfile, keyringlabel, keyringpwd);
+ if(result)
+ return result;
+ }
+
+ /* Create secure session. */
+ result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
+ "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
+ gsk_environment_close(&envir);
+ if(result)
+ return result;
+
+ /* Determine which SSL/TLS version should be enabled. */
+ protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
+ CURL_GSKPROTO_TLSV12_MASK;
+ sni = conn->host.name;
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv2:
+ protoflags = CURL_GSKPROTO_SSLV2_MASK;
+ sni = (char *) NULL;
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ protoflags = CURL_GSKPROTO_SSLV3_MASK;
+ sni = (char *) NULL;
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ protoflags = CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ protoflags = CURL_GSKPROTO_TLSV10_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ protoflags = CURL_GSKPROTO_TLSV11_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ protoflags = CURL_GSKPROTO_TLSV12_MASK;
+ break;
+ }
+
+ /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
+ if(sni) {
+ result = set_buffer(data, connssl->handle,
+ GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
+ if(result == CURLE_UNSUPPORTED_PROTOCOL)
+ result = CURLE_OK;
+ }
+
+ /* Set session parameters. */
+ if(!result) {
+ /* Compute the handshake timeout. Since GSKit granularity is 1 second,
+ we round up the required value. */
+ timeout = Curl_timeleft(data, NULL, TRUE);
+ if(timeout < 0)
+ result = CURLE_OPERATION_TIMEDOUT;
+ else
+ result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
+ (timeout + 999) / 1000);
+ }
+ if(!result)
+ result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
+ if(!result)
+ result = set_ciphers(data, connssl->handle, &protoflags);
+ if(!protoflags) {
+ failf(data, "No SSL protocol/cipher combination enabled");
+ result = CURLE_SSL_CIPHER;
+ }
+ if(!result)
+ result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
+ (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
+ GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
+ if(!result)
+ result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
+ (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
+ GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
+ if(!result)
+ result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
+ (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
+ GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
+ if(!result) {
+ result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
+ (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
+ GSK_TRUE: GSK_FALSE, TRUE);
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ result = CURLE_OK;
+ if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
+ failf(data, "TLS 1.1 not yet supported");
+ result = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+ if(!result) {
+ result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
+ (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
+ GSK_TRUE: GSK_FALSE, TRUE);
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ result = CURLE_OK;
+ if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
+ failf(data, "TLS 1.2 not yet supported");
+ result = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+ if(!result)
+ result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
+ data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
+ GSK_SERVER_AUTH_PASSTHRU, FALSE);
+
+ if(!result) {
+ /* Start handshake. Try asynchronous first. */
+ memset(&commarea, 0, sizeof commarea);
+ connssl->iocport = QsoCreateIOCompletionPort();
+ if(connssl->iocport != -1) {
+ result = gskit_status(data,
+ gsk_secure_soc_startInit(connssl->handle,
+ connssl->iocport,
+ &commarea),
+ "gsk_secure_soc_startInit()",
+ CURLE_SSL_CONNECT_ERROR);
+ if(!result) {
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+ }
+ else
+ close_async_handshake(connssl);
+ }
+ else if(errno != ENOBUFS)
+ result = gskit_status(data, GSK_ERROR_IO,
+ "QsoCreateIOCompletionPort()", 0);
+ else {
+ /* No more completion port available. Use synchronous IO. */
+ result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
+ "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
+ if(!result) {
+ connssl->connecting_state = ssl_connect_3;
+ return CURLE_OK;
+ }
+ }
+ }
+
+ /* Error: rollback. */
+ close_one(connssl, data);
+ return result;
+}
+
+
+static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
+ bool nonblocking)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ Qso_OverlappedIO_t cstat;
+ long timeout_ms;
+ struct timeval stmv;
+ CURLcode result;
+
+ /* Poll or wait for end of SSL asynchronous handshake. */
+
+ for(;;) {
+ timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
+ if(timeout_ms < 0)
+ timeout_ms = 0;
+ stmv.tv_sec = timeout_ms / 1000;
+ stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
+ switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+ case 1: /* Operation complete. */
+ break;
+ case -1: /* An error occurred: handshake still in progress. */
+ if(errno == EINTR) {
+ if(nonblocking)
+ return CURLE_OK;
+ continue; /* Retry. */
+ }
+ if(errno != ETIME) {
+ failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
+ cancel_async_handshake(conn, sockindex);
+ close_async_handshake(connssl);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* FALL INTO... */
+ case 0: /* Handshake in progress, timeout occurred. */
+ if(nonblocking)
+ return CURLE_OK;
+ cancel_async_handshake(conn, sockindex);
+ close_async_handshake(connssl);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ break;
+ }
+ result = gskit_status(data, cstat.returnValue, "SSL handshake",
+ CURLE_SSL_CONNECT_ERROR);
+ if(!result)
+ connssl->connecting_state = ssl_connect_3;
+ close_async_handshake(connssl);
+ return result;
+}
+
+
+static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ const gsk_cert_data_elem *cdev;
+ int cdec;
+ const gsk_cert_data_elem *p;
+ const char *cert = (const char *) NULL;
+ const char *certend;
+ const char *ptr;
+ int i;
+ CURLcode result;
+
+ /* SSL handshake done: gather certificate info and verify host. */
+
+ if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
+ GSK_PARTNER_CERT_INFO,
+ &cdev, &cdec),
+ "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
+ CURLE_OK) {
+ infof(data, "Server certificate:\n");
+ p = cdev;
+ for(i = 0; i++ < cdec; p++)
+ switch (p->cert_data_id) {
+ case CERT_BODY_DER:
+ cert = p->cert_data_p;
+ certend = cert + cdev->cert_data_l;
+ break;
+ case CERT_DN_PRINTABLE:
+ infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_ISSUER_DN_PRINTABLE:
+ infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_VALID_FROM:
+ infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_VALID_TO:
+ infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ }
+ }
+
+ /* Verify host. */
+ result = Curl_verifyhost(conn, cert, certend);
+ if(result)
+ return result;
+
+ /* The only place GSKit can get the whole CA chain is a validation
+ callback where no user data pointer is available. Therefore it's not
+ possible to copy this chain into our structures for CAINFO.
+ However the server certificate may be available, thus we can return
+ info about it. */
+ if(data->set.ssl.certinfo) {
+ result = Curl_ssl_init_certinfo(data, 1);
+ if(result)
+ return result;
+
+ if(cert) {
+ result = Curl_extract_certinfo(conn, 0, cert, certend);
+ if(result)
+ return result;
+ }
+ }
+
+ /* Check pinned public key. */
+ ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ if(!result && ptr) {
+ curl_X509certificate x509;
+ curl_asn1Element *p;
+
+ if(!cert)
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ Curl_parseX509(&x509, cert, certend);
+ p = &x509.subjectPublicKeyInfo;
+ result = Curl_pin_peer_pubkey(ptr, p->header, p->end - p->header);
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ return result;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+ return CURLE_OK;
+}
+
+
+static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
+ bool nonblocking, bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ long timeout_ms;
+ Qso_OverlappedIO_t cstat;
+ CURLcode result = CURLE_OK;
+
+ *done = connssl->state == ssl_connection_complete;
+ if(*done)
+ return CURLE_OK;
+
+ /* Step 1: create session, start handshake. */
+ if(connssl->connecting_state == ssl_connect_1) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ result = CURLE_OPERATION_TIMEDOUT;
+ }
+ else
+ result = gskit_connect_step1(conn, sockindex);
+ }
+
+ /* Step 2: check if handshake is over. */
+ if(!result && connssl->connecting_state == ssl_connect_2) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ result = CURLE_OPERATION_TIMEDOUT;
+ }
+ else
+ result = gskit_connect_step2(conn, sockindex, nonblocking);
+ }
+
+ /* Step 3: gather certificate info, verify host. */
+ if(!result && connssl->connecting_state == ssl_connect_3)
+ result = gskit_connect_step3(conn, sockindex);
+
+ if(result)
+ close_one(connssl, data);
+ else if(connssl->connecting_state == ssl_connect_done) {
+ connssl->state = ssl_connection_complete;
+ connssl->connecting_state = ssl_connect_1;
+ conn->recv[sockindex] = gskit_recv;
+ conn->send[sockindex] = gskit_send;
+ *done = TRUE;
+ }
+
+ return result;
+}
+
+
+CURL_STATIC CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ CURLcode result;
+
+ result = gskit_connect_common(conn, sockindex, TRUE, done);
+ if(*done || result)
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ return result;
+}
+
+
+CURL_STATIC CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode result;
+ bool done;
+
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ result = gskit_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+
+CURL_STATIC void Curl_gskit_close(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->use)
+ close_one(connssl, data);
+}
+
+
+CURL_STATIC int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ ssize_t nread;
+ int what;
+ int rc;
+ char buf[120];
+
+ if(!connssl->handle)
+ return 0;
+
+ if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
+ return 0;
+
+ close_one(connssl, data);
+ rc = 0;
+ what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+
+ for(;;) {
+ if(what < 0) {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ rc = -1;
+ break;
+ }
+
+ if(!what) { /* timeout */
+ failf(data, "SSL shutdown timeout");
+ break;
+ }
+
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server. No way to gsk_secure_soc_read() now, so
+ use read(). */
+
+ nread = read(conn->sock[sockindex], buf, sizeof(buf));
+
+ if(nread < 0) {
+ failf(data, "read: %s", strerror(errno));
+ rc = -1;
+ }
+
+ if(nread <= 0)
+ break;
+
+ what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ }
+
+ return rc;
+}
+
+
+CURL_STATIC size_t Curl_gskit_version(char *buffer, size_t size)
+{
+ strncpy(buffer, "GSKit", size);
+ return strlen(buffer);
+}
+
+
+CURL_STATIC int Curl_gskit_check_cxn(struct connectdata *cxn)
+{
+ int err;
+ int errlen;
+
+ /* The only thing that can be tested here is at the socket level. */
+
+ if(!cxn->ssl[FIRSTSOCKET].handle)
+ return 0; /* connection has been closed */
+
+ err = 0;
+ errlen = sizeof err;
+
+ if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
+ (unsigned char *) &err, &errlen) ||
+ errlen != sizeof err || err)
+ return 0; /* connection has been closed */
+
+ return -1; /* connection status unknown */
+}
+
+#endif /* USE_GSKIT */
diff --git a/libcurl/src/lib/vtls/gskit.h b/libcurl/src/lib/vtls/gskit.h
new file mode 100644
index 0000000..58e15b6
--- /dev/null
+++ b/libcurl/src/lib/vtls/gskit.h
@@ -0,0 +1,71 @@
+#ifndef HEADER_CURL_GSKIT_H
+#define HEADER_CURL_GSKIT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+/*
+ * This header should only be needed to get included by vtls.c and gskit.c
+ */
+
+#include "../urldata.h"
+
+#ifdef USE_GSKIT
+CURL_STATIC int Curl_gskit_init(void);
+CURL_STATIC void Curl_gskit_cleanup(void);
+CURL_STATIC CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done);
+CURL_STATIC void Curl_gskit_close(struct connectdata *conn, int sockindex);
+CURL_STATIC int Curl_gskit_shutdown(struct connectdata *conn, int sockindex);
+
+CURL_STATIC size_t Curl_gskit_version(char *buffer, size_t size);
+CURL_STATIC int Curl_gskit_check_cxn(struct connectdata *cxn);
+
+/* Set the API backend definition to GSKit */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
+
+/* this backend supports CURLOPT_CERTINFO */
+#define have_curlssl_certinfo 1
+
+/* API setup for GSKit */
+#define curlssl_init Curl_gskit_init
+#define curlssl_cleanup Curl_gskit_cleanup
+#define curlssl_connect Curl_gskit_connect
+#define curlssl_connect_nonblocking Curl_gskit_connect_nonblocking
+
+/* No session handling for GSKit */
+#define curlssl_session_free(x) Curl_nop_stmt
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_gskit_close
+#define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y)
+#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN
+#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN
+#define curlssl_engines_list(x) NULL
+#define curlssl_version Curl_gskit_version
+#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
+#define curlssl_data_pending(x,y) 0
+#define curlssl_random(x,y,z) -1
+
+#endif /* USE_GSKIT */
+
+#endif /* HEADER_CURL_GSKIT_H */
diff --git a/libcurl/src/lib/vtls/gtls.c b/libcurl/src/lib/vtls/gtls.c
new file mode 100644
index 0000000..483c837
--- /dev/null
+++ b/libcurl/src/lib/vtls/gtls.c
@@ -0,0 +1,1480 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ * Note: don't use the GnuTLS' *_t variable type names in this source code,
+ * since they were not present in 1.0.X.
+ */
+
+#include "../curl_setup.h"
+
+#ifdef USE_GNUTLS
+
+#include <gnutls/abstract.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#ifdef USE_GNUTLS_NETTLE
+#include <gnutls/crypto.h>
+#include <nettle/md5.h>
+#else
+#include <gcrypt.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "gtls.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "rawstr.h"
+#include "warnless.h"
+#include "x509asn1.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ Some hackish cast macros based on:
+ http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html
+*/
+#ifndef GNUTLS_POINTER_TO_INT_CAST
+#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
+#endif
+#ifndef GNUTLS_INT_TO_POINTER_CAST
+#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
+#endif
+
+/* Enable GnuTLS debugging by defining GTLSDEBUG */
+/*#define GTLSDEBUG */
+
+#ifdef GTLSDEBUG
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+#endif
+static bool gtls_inited = FALSE;
+
+#if defined(GNUTLS_VERSION_NUMBER)
+# if (GNUTLS_VERSION_NUMBER >= 0x020c00)
+# undef gnutls_transport_set_lowat
+# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
+# define USE_GNUTLS_PRIORITY_SET_DIRECT 1
+# endif
+# if (GNUTLS_VERSION_NUMBER >= 0x020c03)
+# define GNUTLS_MAPS_WINSOCK_ERRORS 1
+# endif
+
+# if (GNUTLS_VERSION_NUMBER >= 0x030200)
+# define HAS_ALPN
+# endif
+
+# if (GNUTLS_VERSION_NUMBER >= 0x03020d)
+# define HAS_OCSP
+# endif
+
+# if (GNUTLS_VERSION_NUMBER >= 0x030306)
+# define HAS_CAPATH
+# endif
+#endif
+
+#ifdef HAS_OCSP
+# include <gnutls/ocsp.h>
+#endif
+
+/*
+ * Custom push and pull callback functions used by GNU TLS to read and write
+ * to the socket. These functions are simple wrappers to send() and recv()
+ * (although here using the sread/swrite macros as defined by
+ * curl_setup_once.h).
+ * We use custom functions rather than the GNU TLS defaults because it allows
+ * us to get specific about the fourth "flags" argument, and to use arbitrary
+ * private data with gnutls_transport_set_ptr if we wish.
+ *
+ * When these custom push and pull callbacks fail, GNU TLS checks its own
+ * session-specific error variable, and when not set also its own global
+ * errno variable, in order to take appropriate action. GNU TLS does not
+ * require that the transport is actually a socket. This implies that for
+ * Windows builds these callbacks should ideally set the session-specific
+ * error variable using function gnutls_transport_set_errno or as a last
+ * resort global errno variable using gnutls_transport_set_global_errno,
+ * with a transport agnostic error value. This implies that some winsock
+ * error translation must take place in these callbacks.
+ *
+ * Paragraph above applies to GNU TLS versions older than 2.12.3, since
+ * this version GNU TLS does its own internal winsock error translation
+ * using system_errno() function.
+ */
+
+#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
+# define gtls_EINTR 4
+# define gtls_EIO 5
+# define gtls_EAGAIN 11
+static int gtls_mapped_sockerrno(void)
+{
+ switch(SOCKERRNO) {
+ case WSAEWOULDBLOCK:
+ return gtls_EAGAIN;
+ case WSAEINTR:
+ return gtls_EINTR;
+ default:
+ break;
+ }
+ return gtls_EIO;
+}
+#endif
+
+static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
+{
+ ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
+ if(ret < 0)
+ gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
+#endif
+ return ret;
+}
+
+static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
+{
+ ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
+ if(ret < 0)
+ gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
+#endif
+ return ret;
+}
+
+/* Curl_gtls_init()
+ *
+ * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
+ * are not thread-safe and thus this function itself is not thread-safe and
+ * must only be called from within curl_global_init() to keep the thread
+ * situation under control!
+ */
+CURL_STATIC int Curl_gtls_init(void)
+{
+ int ret = 1;
+ if(!gtls_inited) {
+ ret = gnutls_global_init()?0:1;
+#ifdef GTLSDEBUG
+ gnutls_global_set_log_function(tls_log_func);
+ gnutls_global_set_log_level(2);
+#endif
+ gtls_inited = TRUE;
+ }
+ return ret;
+}
+
+CURL_STATIC int Curl_gtls_cleanup(void)
+{
+ if(gtls_inited) {
+ gnutls_global_deinit();
+ gtls_inited = FALSE;
+ }
+ return 1;
+}
+
+static void showtime(struct SessionHandle *data,
+ const char *text,
+ time_t stamp)
+{
+ struct tm buffer;
+ const struct tm *tm = &buffer;
+ CURLcode result = Curl_gmtime(stamp, &buffer);
+ if(result)
+ return;
+
+ snprintf(data->state.buffer,
+ BUFSIZE,
+ "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
+ text,
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ infof(data, "%s\n", data->state.buffer);
+}
+
+static gnutls_datum_t load_file (const char *file)
+{
+ FILE *f;
+ gnutls_datum_t loaded_file = { NULL, 0 };
+ long filelen;
+ void *ptr;
+
+ if(!(f = fopen(file, "r")))
+ return loaded_file;
+ if(fseek(f, 0, SEEK_END) != 0
+ || (filelen = ftell(f)) < 0
+ || fseek(f, 0, SEEK_SET) != 0
+ || !(ptr = malloc((size_t)filelen)))
+ goto out;
+ if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
+ free(ptr);
+ goto out;
+ }
+
+ loaded_file.data = ptr;
+ loaded_file.size = (unsigned int)filelen;
+out:
+ fclose(f);
+ return loaded_file;
+}
+
+static void unload_file(gnutls_datum_t data) {
+ free(data.data);
+}
+
+
+/* this function does a SSL/TLS (re-)handshake */
+static CURLcode handshake(struct connectdata *conn,
+ int sockindex,
+ bool duringconnect,
+ bool nonblocking)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ gnutls_session_t session = conn->ssl[sockindex].session;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int rc;
+ int what;
+
+ for(;;) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, duringconnect);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd,
+ nonblocking?0:
+ timeout_ms?timeout_ms:1000);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking)
+ return CURLE_OK;
+ else if(timeout_ms) {
+ /* timeout */
+ failf(data, "SSL connection timeout at %ld", timeout_ms);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ rc = gnutls_handshake(session);
+
+ if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
+ connssl->connecting_state =
+ gnutls_record_get_direction(session)?
+ ssl_connect_2_writing:ssl_connect_2_reading;
+ continue;
+ }
+ else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
+ const char *strerr = NULL;
+
+ if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
+ int alert = gnutls_alert_get(session);
+ strerr = gnutls_alert_get_name(alert);
+ }
+
+ if(strerr == NULL)
+ strerr = gnutls_strerror(rc);
+
+ failf(data, "gnutls_handshake() warning: %s", strerr);
+ }
+ else if(rc < 0) {
+ const char *strerr = NULL;
+
+ if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
+ int alert = gnutls_alert_get(session);
+ strerr = gnutls_alert_get_name(alert);
+ }
+
+ if(strerr == NULL)
+ strerr = gnutls_strerror(rc);
+
+ failf(data, "gnutls_handshake() failed: %s", strerr);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+ return CURLE_OK;
+ }
+}
+
+static gnutls_x509_crt_fmt_t do_file_type(const char *type)
+{
+ if(!type || !type[0])
+ return GNUTLS_X509_FMT_PEM;
+ if(Curl_raw_equal(type, "PEM"))
+ return GNUTLS_X509_FMT_PEM;
+ if(Curl_raw_equal(type, "DER"))
+ return GNUTLS_X509_FMT_DER;
+ return -1;
+}
+
+static CURLcode
+gtls_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ gnutls_session_t session;
+ int rc;
+ void *ssl_sessionid;
+ size_t ssl_idsize;
+ bool sni = TRUE; /* default is SNI enabled */
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
+ static const int cipher_priority[] = {
+ /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
+ but this code path is only ever used for ver. < 2.12.0.
+ GNUTLS_CIPHER_AES_128_GCM,
+ GNUTLS_CIPHER_AES_256_GCM,
+ */
+ GNUTLS_CIPHER_AES_128_CBC,
+ GNUTLS_CIPHER_AES_256_CBC,
+ GNUTLS_CIPHER_CAMELLIA_128_CBC,
+ GNUTLS_CIPHER_CAMELLIA_256_CBC,
+ GNUTLS_CIPHER_3DES_CBC,
+ };
+ static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
+ static int protocol_priority[] = { 0, 0, 0, 0 };
+#else
+#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
+/* If GnuTLS was compiled without support for SRP it will error out if SRP is
+ requested in the priority string, so treat it specially
+ */
+#define GNUTLS_SRP "+SRP"
+ const char* prioritylist;
+ const char *err = NULL;
+#endif
+
+ if(conn->ssl[sockindex].state == ssl_connection_complete)
+ /* to make us tolerant against being called more than once for the
+ same connection */
+ return CURLE_OK;
+
+ if(!gtls_inited)
+ Curl_gtls_init();
+
+ /* GnuTLS only supports SSLv3 and TLSv1 */
+ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ failf(data, "GnuTLS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
+ sni = FALSE; /* SSLv3 has no SNI */
+
+ /* allocate a cred struct */
+ rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+
+ rc = gnutls_srp_allocate_client_credentials(
+ &conn->ssl[sockindex].srp_client_cred);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
+ gnutls_strerror(rc));
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
+ srp_client_cred,
+ data->set.ssl.username,
+ data->set.ssl.password);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_srp_set_client_cred() failed: %s",
+ gnutls_strerror(rc));
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+#endif
+
+ if(data->set.ssl.CAfile) {
+ /* set the trusted CA cert bundle file */
+ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+
+ rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
+ data->set.ssl.CAfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)\n",
+ data->set.ssl.CAfile, gnutls_strerror(rc));
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else
+ infof(data, "found %d certificates in %s\n",
+ rc, data->set.ssl.CAfile);
+ }
+
+#ifdef HAS_CAPATH
+ if(data->set.ssl.CApath) {
+ /* set the trusted CA cert directory */
+ rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
+ data->set.ssl.CApath,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)\n",
+ data->set.ssl.CAfile, gnutls_strerror(rc));
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else
+ infof(data, "found %d certificates in %s\n",
+ rc, data->set.ssl.CApath);
+ }
+#endif
+
+ if(data->set.ssl.CRLfile) {
+ /* set the CRL list file */
+ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
+ data->set.ssl.CRLfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ failf(data, "error reading crl file %s (%s)",
+ data->set.ssl.CRLfile, gnutls_strerror(rc));
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ else
+ infof(data, "found %d CRL in %s\n",
+ rc, data->set.ssl.CRLfile);
+ }
+
+ /* Initialize TLS session as a client */
+ rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_init() failed: %d", rc);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* convenient assign */
+ session = conn->ssl[sockindex].session;
+
+ if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+#ifdef ENABLE_IPV6
+ (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+#endif
+ sni &&
+ (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
+ strlen(conn->host.name)) < 0))
+ infof(data, "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+
+ /* Use default priorities */
+ rc = gnutls_set_default_priority(session);
+ if(rc != GNUTLS_E_SUCCESS)
+ return CURLE_SSL_CONNECT_ERROR;
+
+#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
+ rc = gnutls_cipher_set_priority(session, cipher_priority);
+ if(rc != GNUTLS_E_SUCCESS)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* Sets the priority on the certificate types supported by gnutls. Priority
+ is higher for types specified before others. After specifying the types
+ you want, you must append a 0. */
+ rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
+ if(rc != GNUTLS_E_SUCCESS)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ if(data->set.ssl.cipher_list != NULL) {
+ failf(data, "can't pass a custom cipher list to older GnuTLS"
+ " versions");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv3:
+ protocol_priority[0] = GNUTLS_SSL3;
+ break;
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ protocol_priority[0] = GNUTLS_TLS1_0;
+ protocol_priority[1] = GNUTLS_TLS1_1;
+ protocol_priority[2] = GNUTLS_TLS1_2;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ protocol_priority[0] = GNUTLS_TLS1_0;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ protocol_priority[0] = GNUTLS_TLS1_1;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ protocol_priority[0] = GNUTLS_TLS1_2;
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ default:
+ failf(data, "GnuTLS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+ rc = gnutls_protocol_set_priority(session, protocol_priority);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "Did you pass a valid GnuTLS cipher list?");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+#else
+ /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
+ * removed if a run-time error indicates that SRP is not supported by this
+ * GnuTLS version */
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv3:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
+ sni = false;
+ break;
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ default:
+ failf(data, "GnuTLS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+ rc = gnutls_priority_set_direct(session, prioritylist, &err);
+ if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
+ if(!strcmp(err, GNUTLS_SRP)) {
+ /* This GnuTLS was probably compiled without support for SRP.
+ * Note that fact and try again without it. */
+ int validprioritylen = curlx_uztosi(err - prioritylist);
+ char *prioritycopy = strdup(prioritylist);
+ if(!prioritycopy)
+ return CURLE_OUT_OF_MEMORY;
+
+ infof(data, "This GnuTLS does not support SRP\n");
+ if(validprioritylen)
+ /* Remove the :+SRP */
+ prioritycopy[validprioritylen - 1] = 0;
+ rc = gnutls_priority_set_direct(session, prioritycopy, &err);
+ free(prioritycopy);
+ }
+ }
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "Error %d setting GnuTLS cipher list starting with %s",
+ rc, err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ int cur = 0;
+ gnutls_datum_t protocols[2];
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+ protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
+ protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
+ cur++;
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
+ protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
+ cur++;
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ gnutls_alpn_set_protocols(session, protocols, cur, 0);
+ }
+#endif
+
+ if(data->set.str[STRING_CERT]) {
+ if(gnutls_certificate_set_x509_key_file(
+ conn->ssl[sockindex].cred,
+ data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY] ?
+ data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
+ do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
+ GNUTLS_E_SUCCESS) {
+ failf(data, "error reading X.509 key or certificate file");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+#ifdef USE_TLS_SRP
+ /* put the credentials to the current session */
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
+ conn->ssl[sockindex].srp_client_cred);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else
+#endif
+ {
+ rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
+ conn->ssl[sockindex].cred);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* set the connection handle (file descriptor for the socket) */
+ gnutls_transport_set_ptr(session,
+ GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
+
+ /* register callback functions to send and receive data. */
+ gnutls_transport_set_push_function(session, Curl_gtls_push);
+ gnutls_transport_set_pull_function(session, Curl_gtls_pull);
+
+ /* lowat must be set to zero when using custom push and pull functions. */
+ gnutls_transport_set_lowat(session, 0);
+
+#ifdef HAS_OCSP
+ if(data->set.ssl.verifystatus) {
+ rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+#endif
+
+ /* This might be a reconnect, so we check for a session ID in the cache
+ to speed up things */
+
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
+ /* we got a session id, use it! */
+ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
+
+ /* Informational message */
+ infof (data, "SSL re-using session ID\n");
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode pkp_pin_peer_pubkey(gnutls_x509_crt_t cert,
+ const char *pinnedpubkey)
+{
+ /* Scratch */
+ size_t len1 = 0, len2 = 0;
+ unsigned char *buff1 = NULL;
+
+ gnutls_pubkey_t key = NULL;
+
+ /* Result is returned to caller */
+ int ret = 0;
+ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+
+ /* if a path wasn't specified, don't pin */
+ if(NULL == pinnedpubkey)
+ return CURLE_OK;
+
+ if(NULL == cert)
+ return result;
+
+ do {
+ /* Begin Gyrations to get the public key */
+ gnutls_pubkey_init(&key);
+
+ ret = gnutls_pubkey_import_x509(key, cert, 0);
+ if(ret < 0)
+ break; /* failed */
+
+ ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
+ if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
+ break; /* failed */
+
+ buff1 = malloc(len1);
+ if(NULL == buff1)
+ break; /* failed */
+
+ len2 = len1;
+
+ ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
+ if(ret < 0 || len1 != len2)
+ break; /* failed */
+
+ /* End Gyrations */
+
+ /* The one good exit point */
+ result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1);
+ } while(0);
+
+ if(NULL != key)
+ gnutls_pubkey_deinit(key);
+
+ Curl_safefree(buff1);
+
+ return result;
+}
+
+static Curl_recv gtls_recv;
+static Curl_send gtls_send;
+
+static CURLcode
+gtls_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ unsigned int cert_list_size;
+ const gnutls_datum_t *chainp;
+ unsigned int verify_status = 0;
+ gnutls_x509_crt_t x509_cert, x509_issuer;
+ gnutls_datum_t issuerp;
+ char certbuf[256] = ""; /* big enough? */
+ size_t size;
+ unsigned int algo;
+ unsigned int bits;
+ time_t certclock;
+ const char *ptr;
+ struct SessionHandle *data = conn->data;
+ gnutls_session_t session = conn->ssl[sockindex].session;
+ int rc;
+ bool incache;
+ void *ssl_sessionid;
+#ifdef HAS_ALPN
+ gnutls_datum_t proto;
+#endif
+ CURLcode result = CURLE_OK;
+
+ gnutls_protocol_t version = gnutls_protocol_get_version(session);
+
+ /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
+ ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
+ gnutls_cipher_get(session),
+ gnutls_mac_get(session));
+
+ infof(data, "SSL connection using %s / %s\n",
+ gnutls_protocol_get_name(version), ptr);
+
+ /* This function will return the peer's raw certificate (chain) as sent by
+ the peer. These certificates are in raw format (DER encoded for
+ X.509). In case of a X.509 then a certificate list may be present. The
+ first certificate in the list is the peer's certificate, following the
+ issuer's certificate, then the issuer's issuer etc. */
+
+ chainp = gnutls_certificate_get_peers(session, &cert_list_size);
+ if(!chainp) {
+ if(data->set.ssl.verifypeer ||
+ data->set.ssl.verifyhost ||
+ data->set.ssl.issuercert) {
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
+ && data->set.ssl.username != NULL
+ && !data->set.ssl.verifypeer
+ && gnutls_cipher_get(session)) {
+ /* no peer cert, but auth is ok if we have SRP user and cipher and no
+ peer verify */
+ }
+ else {
+#endif
+ failf(data, "failed to get server cert");
+ return CURLE_PEER_FAILED_VERIFICATION;
+#ifdef USE_TLS_SRP
+ }
+#endif
+ }
+ infof(data, "\t common name: WARNING couldn't obtain\n");
+ }
+
+ if(data->set.ssl.certinfo && chainp) {
+ unsigned int i;
+
+ result = Curl_ssl_init_certinfo(data, cert_list_size);
+ if(result)
+ return result;
+
+ for(i = 0; i < cert_list_size; i++) {
+ const char *beg = (const char *) chainp[i].data;
+ const char *end = beg + chainp[i].size;
+
+ result = Curl_extract_certinfo(conn, i, beg, end);
+ if(result)
+ return result;
+ }
+ }
+
+ if(data->set.ssl.verifypeer) {
+ /* This function will try to verify the peer's certificate and return its
+ status (trusted, invalid etc.). The value of status should be one or
+ more of the gnutls_certificate_status_t enumerated elements bitwise
+ or'd. To avoid denial of service attacks some default upper limits
+ regarding the certificate key size and chain size are set. To override
+ them use gnutls_certificate_set_verify_limits(). */
+
+ rc = gnutls_certificate_verify_peers2(session, &verify_status);
+ if(rc < 0) {
+ failf(data, "server cert verify failed: %d", rc);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* verify_status is a bitmask of gnutls_certificate_status bits */
+ if(verify_status & GNUTLS_CERT_INVALID) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server certificate verification failed. CAfile: %s "
+ "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
+ data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
+ return CURLE_SSL_CACERT;
+ }
+ else
+ infof(data, "\t server certificate verification FAILED\n");
+ }
+ else
+ infof(data, "\t server certificate verification OK\n");
+ }
+ else
+ infof(data, "\t server certificate verification SKIPPED\n");
+
+#ifdef HAS_OCSP
+ if(data->set.ssl.verifystatus) {
+ if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
+ if(verify_status & GNUTLS_CERT_REVOKED)
+ infof(data, "\t server certificate was REVOKED\n");
+ else
+ infof(data, "\t server certificate status verification FAILED\n");
+
+ return CURLE_SSL_INVALIDCERTSTATUS;
+ }
+ else
+ infof(data, "\t server certificate status verification OK\n");
+ }
+ else
+ infof(data, "\t server certificate status verification SKIPPED\n");
+#endif
+
+ /* initialize an X.509 certificate structure. */
+ gnutls_x509_crt_init(&x509_cert);
+
+ if(chainp)
+ /* convert the given DER or PEM encoded Certificate to the native
+ gnutls_x509_crt_t format */
+ gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
+
+ if(data->set.ssl.issuercert) {
+ gnutls_x509_crt_init(&x509_issuer);
+ issuerp = load_file(data->set.ssl.issuercert);
+ gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
+ rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
+ gnutls_x509_crt_deinit(x509_issuer);
+ unload_file(issuerp);
+ if(rc <= 0) {
+ failf(data, "server certificate issuer check failed (IssuerCert: %s)",
+ data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ gnutls_x509_crt_deinit(x509_cert);
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+ infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
+ data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ }
+
+ size=sizeof(certbuf);
+ rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
+ 0, /* the first and only one */
+ FALSE,
+ certbuf,
+ &size);
+ if(rc) {
+ infof(data, "error fetching CN from cert:%s\n",
+ gnutls_strerror(rc));
+ }
+
+ /* This function will check if the given certificate's subject matches the
+ given hostname. This is a basic implementation of the matching described
+ in RFC2818 (HTTPS), which takes into account wildcards, and the subject
+ alternative name PKIX extension. Returns non zero on success, and zero on
+ failure. */
+ rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
+#if GNUTLS_VERSION_NUMBER < 0x030306
+ /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
+ addresses. */
+ if(!rc) {
+#ifdef ENABLE_IPV6
+ #define use_addr in6_addr
+#else
+ #define use_addr in_addr
+#endif
+ unsigned char addrbuf[sizeof(struct use_addr)];
+ unsigned char certaddr[sizeof(struct use_addr)];
+ size_t addrlen = 0, certaddrlen;
+ int i;
+ int ret = 0;
+
+ if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
+ addrlen = 4;
+#ifdef ENABLE_IPV6
+ else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
+ addrlen = 16;
+#endif
+
+ if(addrlen) {
+ for(i=0; ; i++) {
+ certaddrlen = sizeof(certaddr);
+ ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
+ &certaddrlen, NULL);
+ /* If this happens, it wasn't an IP address. */
+ if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ continue;
+ if(ret < 0)
+ break;
+ if(ret != GNUTLS_SAN_IPADDRESS)
+ continue;
+ if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
+ rc = 1;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ if(!rc) {
+ if(data->set.ssl.verifyhost) {
+ failf(data, "SSL: certificate subject name (%s) does not match "
+ "target host name '%s'", certbuf, conn->host.dispname);
+ gnutls_x509_crt_deinit(x509_cert);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t common name: %s (does not match '%s')\n",
+ certbuf, conn->host.dispname);
+ }
+ else
+ infof(data, "\t common name: %s (matched)\n", certbuf);
+
+ /* Check for time-based validity */
+ certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
+
+ if(certclock == (time_t)-1) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server cert expiration date verify failed");
+ gnutls_x509_crt_deinit(x509_cert);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else
+ infof(data, "\t server certificate expiration date verify FAILED\n");
+ }
+ else {
+ if(certclock < time(NULL)) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server certificate expiration date has passed.");
+ gnutls_x509_crt_deinit(x509_cert);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t server certificate expiration date FAILED\n");
+ }
+ else
+ infof(data, "\t server certificate expiration date OK\n");
+ }
+
+ certclock = gnutls_x509_crt_get_activation_time(x509_cert);
+
+ if(certclock == (time_t)-1) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server cert activation date verify failed");
+ gnutls_x509_crt_deinit(x509_cert);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else
+ infof(data, "\t server certificate activation date verify FAILED\n");
+ }
+ else {
+ if(certclock > time(NULL)) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server certificate not activated yet.");
+ gnutls_x509_crt_deinit(x509_cert);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t server certificate activation date FAILED\n");
+ }
+ else
+ infof(data, "\t server certificate activation date OK\n");
+ }
+
+ ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ if(ptr) {
+ result = pkp_pin_peer_pubkey(x509_cert, ptr);
+ if(result != CURLE_OK) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ gnutls_x509_crt_deinit(x509_cert);
+ return result;
+ }
+ }
+
+ /* Show:
+
+ - subject
+ - start date
+ - expire date
+ - common name
+ - issuer
+
+ */
+
+ /* public key algorithm's parameters */
+ algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
+ infof(data, "\t certificate public key: %s\n",
+ gnutls_pk_algorithm_get_name(algo));
+
+ /* version of the X.509 certificate. */
+ infof(data, "\t certificate version: #%d\n",
+ gnutls_x509_crt_get_version(x509_cert));
+
+
+ size = sizeof(certbuf);
+ gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
+ infof(data, "\t subject: %s\n", certbuf);
+
+ certclock = gnutls_x509_crt_get_activation_time(x509_cert);
+ showtime(data, "start date", certclock);
+
+ certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
+ showtime(data, "expire date", certclock);
+
+ size = sizeof(certbuf);
+ gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
+ infof(data, "\t issuer: %s\n", certbuf);
+
+ gnutls_x509_crt_deinit(x509_cert);
+
+ /* compression algorithm (if any) */
+ ptr = gnutls_compression_get_name(gnutls_compression_get(session));
+ /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
+ infof(data, "\t compression: %s\n", ptr);
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ rc = gnutls_alpn_get_selected_protocol(session, &proto);
+ if(rc == 0) {
+ infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
+ proto.data);
+
+#ifdef USE_NGHTTP2
+ if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
+ NGHTTP2_PROTO_VERSION_ID_LEN)) {
+ conn->negnpn = CURL_HTTP_VERSION_2_0;
+ }
+ else
+#endif
+ if(proto.size == ALPN_HTTP_1_1_LENGTH &&
+ !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ }
+ else
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+#endif
+
+ conn->ssl[sockindex].state = ssl_connection_complete;
+ conn->recv[sockindex] = gtls_recv;
+ conn->send[sockindex] = gtls_send;
+
+ {
+ /* we always unconditionally get the session id here, as even if we
+ already got it from the cache and asked to use it in the connection, it
+ might've been rejected and then a new one is in use now and we need to
+ detect that. */
+ void *connect_sessionid;
+ size_t connect_idsize = 0;
+
+ /* get the session ID data size */
+ gnutls_session_get_data(session, NULL, &connect_idsize);
+ connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
+
+ if(connect_sessionid) {
+ /* extract session ID to the allocated buffer */
+ gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
+
+ incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
+ if(incache) {
+ /* there was one before in the cache, so instead of risking that the
+ previous one was rejected, we just kill that and store the new */
+ Curl_ssl_delsessionid(conn, ssl_sessionid);
+ }
+
+ /* store this session id */
+ result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
+ if(result) {
+ free(connect_sessionid);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ return result;
+}
+
+
+/*
+ * This function is called after the TCP connect has completed. Setup the TLS
+ * layer and do all necessary magic.
+ */
+/* We use connssl->connecting_state to keep track of the connection status;
+ there are three states: 'ssl_connect_1' (not started yet or complete),
+ 'ssl_connect_2_reading' (waiting for data from server), and
+ 'ssl_connect_2_writing' (waiting to be able to write).
+ */
+static CURLcode
+gtls_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ int rc;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ /* Initiate the connection, if not already done */
+ if(ssl_connect_1==connssl->connecting_state) {
+ rc = gtls_connect_step1 (conn, sockindex);
+ if(rc)
+ return rc;
+ }
+
+ rc = handshake(conn, sockindex, TRUE, nonblocking);
+ if(rc)
+ /* handshake() sets its own error message with failf() */
+ return rc;
+
+ /* Finish connecting once the handshake is done */
+ if(ssl_connect_1==connssl->connecting_state) {
+ rc = gtls_connect_step3(conn, sockindex);
+ if(rc)
+ return rc;
+ }
+
+ *done = ssl_connect_1==connssl->connecting_state;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode
+Curl_gtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return gtls_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURL_STATIC CURLcode
+Curl_gtls_connect(struct connectdata *conn,
+ int sockindex)
+
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = gtls_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+static ssize_t gtls_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
+
+ if(rc < 0 ) {
+ *curlcode = (rc == GNUTLS_E_AGAIN)
+ ? CURLE_AGAIN
+ : CURLE_SEND_ERROR;
+
+ rc = -1;
+ }
+
+ return rc;
+}
+
+static void close_one(struct connectdata *conn,
+ int idx)
+{
+ if(conn->ssl[idx].session) {
+ gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
+ gnutls_deinit(conn->ssl[idx].session);
+ conn->ssl[idx].session = NULL;
+ }
+ if(conn->ssl[idx].cred) {
+ gnutls_certificate_free_credentials(conn->ssl[idx].cred);
+ conn->ssl[idx].cred = NULL;
+ }
+#ifdef USE_TLS_SRP
+ if(conn->ssl[idx].srp_client_cred) {
+ gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
+ conn->ssl[idx].srp_client_cred = NULL;
+ }
+#endif
+}
+
+CURL_STATIC void Curl_gtls_close(struct connectdata *conn, int sockindex)
+{
+ close_one(conn, sockindex);
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+CURL_STATIC int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
+{
+ ssize_t result;
+ int retval = 0;
+ struct SessionHandle *data = conn->data;
+ int done = 0;
+ char buf[120];
+
+ /* This has only been tested on the proftpd server, and the mod_tls code
+ sends a close notify alert without waiting for a close notify alert in
+ response. Thus we wait for a close notify alert from the server, but
+ we do not send one. Let's hope other servers do the same... */
+
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
+
+ if(conn->ssl[sockindex].session) {
+ while(!done) {
+ int what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ if(what > 0) {
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server */
+ result = gnutls_record_recv(conn->ssl[sockindex].session,
+ buf, sizeof(buf));
+ switch(result) {
+ case 0:
+ /* This is the expected response. There was no data but only
+ the close notify alert */
+ done = 1;
+ break;
+ case GNUTLS_E_AGAIN:
+ case GNUTLS_E_INTERRUPTED:
+ infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
+ break;
+ default:
+ retval = -1;
+ done = 1;
+ break;
+ }
+ }
+ else if(0 == what) {
+ /* timeout */
+ failf(data, "SSL shutdown timeout");
+ done = 1;
+ break;
+ }
+ else {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ retval = -1;
+ done = 1;
+ }
+ }
+ gnutls_deinit(conn->ssl[sockindex].session);
+ }
+ gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
+
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
+ && data->set.ssl.username != NULL)
+ gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
+#endif
+
+ conn->ssl[sockindex].cred = NULL;
+ conn->ssl[sockindex].session = NULL;
+
+ return retval;
+}
+
+static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *curlcode)
+{
+ ssize_t ret;
+
+ ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
+ if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ }
+
+ if(ret == GNUTLS_E_REHANDSHAKE) {
+ /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
+ proper way" takes a whole lot of work. */
+ CURLcode result = handshake(conn, num, FALSE, FALSE);
+ if(result)
+ /* handshake() writes error message on its own */
+ *curlcode = result;
+ else
+ *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
+ return -1;
+ }
+
+ if(ret < 0) {
+ failf(conn->data, "GnuTLS recv error (%d): %s",
+ (int)ret, gnutls_strerror((int)ret));
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ return ret;
+}
+
+CURL_STATIC void Curl_gtls_session_free(void *ptr)
+{
+ free(ptr);
+}
+
+CURL_STATIC size_t Curl_gtls_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
+}
+
+#ifndef USE_GNUTLS_NETTLE
+static int Curl_gtls_seed(struct SessionHandle *data)
+{
+ /* we have the "SSL is seeded" boolean static to prevent multiple
+ time-consuming seedings in vain */
+ static bool ssl_seeded = FALSE;
+
+ /* Quickly add a bit of entropy */
+ gcry_fast_random_poll();
+
+ if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
+ data->set.str[STRING_SSL_EGDSOCKET]) {
+
+ /* TODO: to a good job seeding the RNG
+ This may involve the gcry_control function and these options:
+ GCRYCTL_SET_RANDOM_SEED_FILE
+ GCRYCTL_SET_RNDEGD_SOCKET
+ */
+ ssl_seeded = TRUE;
+ }
+ return 0;
+}
+#endif
+
+/* data might be NULL! */
+CURL_STATIC int Curl_gtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+#if defined(USE_GNUTLS_NETTLE)
+ (void)data;
+ gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
+#elif defined(USE_GNUTLS)
+ if(data)
+ Curl_gtls_seed(data); /* Initiate the seed if not already done */
+ gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
+#endif
+ return 0;
+}
+
+CURL_STATIC void Curl_gtls_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+#if defined(USE_GNUTLS_NETTLE)
+ struct md5_ctx MD5pw;
+ md5_init(&MD5pw);
+ md5_update(&MD5pw, (unsigned int)tmplen, tmp);
+ md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
+#elif defined(USE_GNUTLS)
+ gcry_md_hd_t MD5pw;
+ gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
+ gcry_md_write(MD5pw, tmp, tmplen);
+ memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
+ gcry_md_close(MD5pw);
+#endif
+}
+
+bool Curl_gtls_cert_status_request(void)
+{
+#ifdef HAS_OCSP
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+#endif /* USE_GNUTLS */
diff --git a/libcurl/src/lib/vtls/gtls.h b/libcurl/src/lib/vtls/gtls.h
new file mode 100644
index 0000000..dc98f79
--- /dev/null
+++ b/libcurl/src/lib/vtls/gtls.h
@@ -0,0 +1,83 @@
+#ifndef HEADER_CURL_GTLS_H
+#define HEADER_CURL_GTLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "../curl_setup.h"
+
+#ifdef USE_GNUTLS
+
+#include "urldata.h"
+
+CURL_STATIC int Curl_gtls_init(void);
+CURL_STATIC int Curl_gtls_cleanup(void);
+CURL_STATIC CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+ /* close a SSL connection */
+CURL_STATIC void Curl_gtls_close(struct connectdata *conn, int sockindex);
+
+CURL_STATIC void Curl_gtls_session_free(void *ptr);
+CURL_STATIC size_t Curl_gtls_version(char *buffer, size_t size);
+CURL_STATIC int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
+CURL_STATIC int Curl_gtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+CURL_STATIC void Curl_gtls_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+
+bool Curl_gtls_cert_status_request(void);
+
+/* Set the API backend definition to GnuTLS */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
+
+/* this backend supports the CAPATH option */
+#define have_curlssl_ca_path 1
+
+/* this backend supports CURLOPT_CERTINFO */
+#define have_curlssl_certinfo 1
+
+/* API setup for GnuTLS */
+#define curlssl_init Curl_gtls_init
+#define curlssl_cleanup Curl_gtls_cleanup
+#define curlssl_connect Curl_gtls_connect
+#define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking
+#define curlssl_session_free(x) Curl_gtls_session_free(x)
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_gtls_close
+#define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y)
+#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_gtls_version
+#define curlssl_check_cxn(x) ((void)x, -1)
+#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
+#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
+#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
+
+#endif /* USE_GNUTLS */
+#endif /* HEADER_CURL_GTLS_H */
diff --git a/libcurl/src/lib/vtls/nss.c b/libcurl/src/lib/vtls/nss.c
new file mode 100644
index 0000000..1c17612
--- /dev/null
+++ b/libcurl/src/lib/vtls/nss.c
@@ -0,0 +1,2006 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all NSS-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ */
+
+#include "../curl_setup.h"
+
+#ifdef USE_NSS
+
+#include "urldata.h"
+#include "sendf.h"
+#include "formdata.h" /* for the boundary function */
+#include "url.h" /* for the ssl config check function */
+#include "connect.h"
+#include "strequal.h"
+#include "select.h"
+#include "vtls.h"
+#include "llist.h"
+#include "curl_printf.h"
+#include "nssg.h"
+#include <nspr.h>
+#include <nss.h>
+#include <ssl.h>
+#include <sslerr.h>
+#include <secerr.h>
+#include <secmod.h>
+#include <sslproto.h>
+#include <prtypes.h>
+#include <pk11pub.h>
+#include <prio.h>
+#include <secitem.h>
+#include <secport.h>
+#include <certdb.h>
+#include <base64.h>
+#include <cert.h>
+#include <prerror.h>
+
+#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH)
+
+#if NSSVERNUM >= 0x030f00 /* 3.15.0 */
+#include <ocsp.h>
+#endif
+
+#include "rawstr.h"
+#include "warnless.h"
+#include "x509asn1.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define SSL_DIR "/etc/pki/nssdb"
+
+/* enough to fit the string "PEM Token #[0|1]" */
+#define SLOTSIZE 13
+
+PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
+
+PRLock * nss_initlock = NULL;
+PRLock * nss_crllock = NULL;
+struct curl_llist *nss_crl_list = NULL;
+NSSInitContext * nss_context = NULL;
+
+volatile int initialized = 0;
+
+typedef struct {
+ const char *name;
+ int num;
+} cipher_s;
+
+#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \
+ CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \
+ ptr->type = (_type); \
+ ptr->pValue = (_val); \
+ ptr->ulValueLen = (_len); \
+} WHILE_FALSE
+
+#define CERT_NewTempCertificate __CERT_NewTempCertificate
+
+#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
+static const cipher_s cipherlist[] = {
+ /* SSL2 cipher suites */
+ {"rc4", SSL_EN_RC4_128_WITH_MD5},
+ {"rc4-md5", SSL_EN_RC4_128_WITH_MD5},
+ {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
+ {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5},
+ {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
+ {"des", SSL_EN_DES_64_CBC_WITH_MD5},
+ {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
+ /* SSL3/TLS cipher suites */
+ {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
+ {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA},
+ {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
+ {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
+ {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
+ {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
+ {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
+ {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
+ {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
+ {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
+ {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
+ {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA},
+ /* TLS 1.0: Exportable 56-bit Cipher Suites. */
+ {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
+ {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
+ /* AES ciphers. */
+ {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
+ {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
+ {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
+ {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
+ {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
+ {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
+ /* ECC ciphers. */
+ {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA},
+ {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
+ {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
+ {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
+ {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA},
+ {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
+ {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
+ {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
+ {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA},
+ {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA},
+ {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
+ {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
+ {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
+ {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
+ {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA},
+ {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA},
+ {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
+ {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
+ {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
+#ifdef TLS_RSA_WITH_NULL_SHA256
+ /* new HMAC-SHA256 cipher suites specified in RFC */
+ {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256},
+ {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256},
+ {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256},
+ {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
+ {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
+ {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
+ {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
+#endif
+#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256
+ /* AES GCM cipher suites in RFC 5288 and RFC 5289 */
+ {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256},
+ {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+ {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
+ {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256},
+ {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
+#endif
+};
+
+static const char* pem_library = "libnsspem.so";
+SECMODModule* mod = NULL;
+
+/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
+static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
+static PRIOMethods nspr_io_methods;
+
+static const char* nss_error_to_name(PRErrorCode code)
+{
+ const char *name = PR_ErrorToName(code);
+ if(name)
+ return name;
+
+ return "unknown error";
+}
+
+static void nss_print_error_message(struct SessionHandle *data, PRUint32 err)
+{
+ failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
+}
+
+static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
+ char *cipher_list)
+{
+ unsigned int i;
+ PRBool cipher_state[NUM_OF_CIPHERS];
+ PRBool found;
+ char *cipher;
+
+ /* First disable all ciphers. This uses a different max value in case
+ * NSS adds more ciphers later we don't want them available by
+ * accident
+ */
+ for(i=0; i<SSL_NumImplementedCiphers; i++) {
+ SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], PR_FALSE);
+ }
+
+ /* Set every entry in our list to false */
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ cipher_state[i] = PR_FALSE;
+ }
+
+ cipher = cipher_list;
+
+ while(cipher_list && (cipher_list[0])) {
+ while((*cipher) && (ISSPACE(*cipher)))
+ ++cipher;
+
+ if((cipher_list = strchr(cipher, ','))) {
+ *cipher_list++ = '\0';
+ }
+
+ found = PR_FALSE;
+
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ if(Curl_raw_equal(cipher, cipherlist[i].name)) {
+ cipher_state[i] = PR_TRUE;
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if(found == PR_FALSE) {
+ failf(data, "Unknown cipher in list: %s", cipher);
+ return SECFailure;
+ }
+
+ if(cipher_list) {
+ cipher = cipher_list;
+ }
+ }
+
+ /* Finally actually enable the selected ciphers */
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ if(!cipher_state[i])
+ continue;
+
+ if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != SECSuccess) {
+ failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name);
+ return SECFailure;
+ }
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * Get the number of ciphers that are enabled. We use this to determine
+ * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
+ */
+static int num_enabled_ciphers(void)
+{
+ PRInt32 policy = 0;
+ int count = 0;
+ unsigned int i;
+
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ SSL_CipherPolicyGet(cipherlist[i].num, &policy);
+ if(policy)
+ count++;
+ }
+ return count;
+}
+
+/*
+ * Determine whether the nickname passed in is a filename that needs to
+ * be loaded as a PEM or a regular NSS nickname.
+ *
+ * returns 1 for a file
+ * returns 0 for not a file (NSS nickname)
+ */
+static int is_file(const char *filename)
+{
+ struct_stat st;
+
+ if(filename == NULL)
+ return 0;
+
+ if(stat(filename, &st) == 0)
+ if(S_ISREG(st.st_mode))
+ return 1;
+
+ return 0;
+}
+
+/* Check if the given string is filename or nickname of a certificate. If the
+ * given string is recognized as filename, return NULL. If the given string is
+ * recognized as nickname, return a duplicated string. The returned string
+ * should be later deallocated using free(). If the OOM failure occurs, we
+ * return NULL, too.
+ */
+static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
+{
+ const char *str = data->set.str[cert_kind];
+ const char *n;
+
+ if(!is_file(str))
+ /* no such file exists, use the string as nickname */
+ return strdup(str);
+
+ /* search the last slash; we require at least one slash in a file name */
+ n = strrchr(str, '/');
+ if(!n) {
+ infof(data, "warning: certificate file name \"%s\" handled as nickname; "
+ "please use \"./%s\" to force file name\n", str, str);
+ return strdup(str);
+ }
+
+ /* we'll use the PEM reader to read the certificate from file */
+ return NULL;
+}
+
+/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
+ * the call succeeds, append the object handle to the list of objects so that
+ * the object can be destroyed in Curl_nss_close(). */
+static CURLcode nss_create_object(struct ssl_connect_data *ssl,
+ CK_OBJECT_CLASS obj_class,
+ const char *filename, bool cacert)
+{
+ PK11SlotInfo *slot;
+ PK11GenericObject *obj;
+ CK_BBOOL cktrue = CK_TRUE;
+ CK_BBOOL ckfalse = CK_FALSE;
+ CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
+ int attr_cnt = 0;
+ CURLcode result = (cacert)
+ ? CURLE_SSL_CACERT_BADFILE
+ : CURLE_SSL_CERTPROBLEM;
+
+ const int slot_id = (cacert) ? 0 : 1;
+ char *slot_name = aprintf("PEM Token #%d", slot_id);
+ if(!slot_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ slot = PK11_FindSlotByName(slot_name);
+ free(slot_name);
+ if(!slot)
+ return result;
+
+ PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
+ PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
+ PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
+ strlen(filename) + 1);
+
+ if(CKO_CERTIFICATE == obj_class) {
+ CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
+ PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
+ }
+
+ obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
+ PK11_FreeSlot(slot);
+ if(!obj)
+ return result;
+
+ if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
+ PK11_DestroyGenericObject(obj);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!cacert && CKO_CERTIFICATE == obj_class)
+ /* store reference to a client certificate */
+ ssl->obj_clicert = obj;
+
+ return CURLE_OK;
+}
+
+/* Destroy the NSS object whose handle is given by ptr. This function is
+ * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
+ * NSS objects in Curl_nss_close() */
+static void nss_destroy_object(void *user, void *ptr)
+{
+ PK11GenericObject *obj = (PK11GenericObject *)ptr;
+ (void) user;
+ PK11_DestroyGenericObject(obj);
+}
+
+/* same as nss_destroy_object() but for CRL items */
+static void nss_destroy_crl_item(void *user, void *ptr)
+{
+ SECItem *crl_der = (SECItem *)ptr;
+ (void) user;
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+}
+
+static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
+ const char *filename, PRBool cacert)
+{
+ CURLcode result = (cacert)
+ ? CURLE_SSL_CACERT_BADFILE
+ : CURLE_SSL_CERTPROBLEM;
+
+ /* libnsspem.so leaks memory if the requested file does not exist. For more
+ * details, go to <https://bugzilla.redhat.com/734760>. */
+ if(is_file(filename))
+ result = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
+
+ if(!result && !cacert) {
+ /* we have successfully loaded a client certificate */
+ CERTCertificate *cert;
+ char *nickname = NULL;
+ char *n = strrchr(filename, '/');
+ if(n)
+ n++;
+
+ /* The following undocumented magic helps to avoid a SIGSEGV on call
+ * of PK11_ReadRawAttribute() from SelectClientCert() when using an
+ * immature version of libnsspem.so. For more details, go to
+ * <https://bugzilla.redhat.com/733685>. */
+ nickname = aprintf("PEM Token #1:%s", n);
+ if(nickname) {
+ cert = PK11_FindCertFromNickname(nickname, NULL);
+ if(cert)
+ CERT_DestroyCertificate(cert);
+
+ free(nickname);
+ }
+ }
+
+ return result;
+}
+
+/* add given CRL to cache if it is not already there */
+static CURLcode nss_cache_crl(SECItem *crl_der)
+{
+ CERTCertDBHandle *db = CERT_GetDefaultCertDB();
+ CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0);
+ if(crl) {
+ /* CRL already cached */
+ SEC_DestroyCrl(crl);
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+ return CURLE_OK;
+ }
+
+ /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */
+ PR_Lock(nss_crllock);
+
+ /* store the CRL item so that we can free it in Curl_nss_cleanup() */
+ if(!Curl_llist_insert_next(nss_crl_list, nss_crl_list->tail, crl_der)) {
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+ PR_Unlock(nss_crllock);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
+ /* unable to cache CRL */
+ PR_Unlock(nss_crllock);
+ return CURLE_SSL_CRL_BADFILE;
+ }
+
+ /* we need to clear session cache, so that the CRL could take effect */
+ SSL_ClearSessionCache();
+ PR_Unlock(nss_crllock);
+ return CURLE_OK;
+}
+
+static CURLcode nss_load_crl(const char* crlfilename)
+{
+ PRFileDesc *infile;
+ PRFileInfo info;
+ SECItem filedata = { 0, NULL, 0 };
+ SECItem *crl_der = NULL;
+ char *body;
+
+ infile = PR_Open(crlfilename, PR_RDONLY, 0);
+ if(!infile)
+ return CURLE_SSL_CRL_BADFILE;
+
+ if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
+ goto fail;
+
+ if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
+ goto fail;
+
+ if(info.size != PR_Read(infile, filedata.data, info.size))
+ goto fail;
+
+ crl_der = SECITEM_AllocItem(NULL, NULL, 0U);
+ if(!crl_der)
+ goto fail;
+
+ /* place a trailing zero right after the visible data */
+ body = (char*)filedata.data;
+ body[--filedata.len] = '\0';
+
+ body = strstr(body, "-----BEGIN");
+ if(body) {
+ /* assume ASCII */
+ char *trailer;
+ char *begin = PORT_Strchr(body, '\n');
+ if(!begin)
+ begin = PORT_Strchr(body, '\r');
+ if(!begin)
+ goto fail;
+
+ trailer = strstr(++begin, "-----END");
+ if(!trailer)
+ goto fail;
+
+ /* retrieve DER from ASCII */
+ *trailer = '\0';
+ if(ATOB_ConvertAsciiToItem(crl_der, begin))
+ goto fail;
+
+ SECITEM_FreeItem(&filedata, PR_FALSE);
+ }
+ else
+ /* assume DER */
+ *crl_der = filedata;
+
+ PR_Close(infile);
+ return nss_cache_crl(crl_der);
+
+fail:
+ PR_Close(infile);
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+ SECITEM_FreeItem(&filedata, PR_FALSE);
+ return CURLE_SSL_CRL_BADFILE;
+}
+
+static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
+ char *key_file)
+{
+ PK11SlotInfo *slot;
+ SECStatus status;
+ CURLcode result;
+ struct ssl_connect_data *ssl = conn->ssl;
+
+ (void)sockindex; /* unused */
+
+ result = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
+ if(result) {
+ PR_SetError(SEC_ERROR_BAD_KEY, 0);
+ return result;
+ }
+
+ slot = PK11_FindSlotByName("PEM Token #1");
+ if(!slot)
+ return CURLE_SSL_CERTPROBLEM;
+
+ /* This will force the token to be seen as re-inserted */
+ SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
+ PK11_IsPresent(slot);
+
+ status = PK11_Authenticate(slot, PR_TRUE,
+ conn->data->set.str[STRING_KEY_PASSWD]);
+ PK11_FreeSlot(slot);
+
+ return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
+}
+
+static int display_error(struct connectdata *conn, PRInt32 err,
+ const char *filename)
+{
+ switch(err) {
+ case SEC_ERROR_BAD_PASSWORD:
+ failf(conn->data, "Unable to load client key: Incorrect password");
+ return 1;
+ case SEC_ERROR_UNKNOWN_CERT:
+ failf(conn->data, "Unable to load certificate %s", filename);
+ return 1;
+ default:
+ break;
+ }
+ return 0; /* The caller will print a generic error */
+}
+
+static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
+ char *cert_file, char *key_file)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode result;
+
+ if(cert_file) {
+ result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
+ if(result) {
+ const PRErrorCode err = PR_GetError();
+ if(!display_error(conn, err, cert_file)) {
+ const char *err_name = nss_error_to_name(err);
+ failf(data, "unable to load client cert: %d (%s)", err, err_name);
+ }
+
+ return result;
+ }
+ }
+
+ if(key_file || (is_file(cert_file))) {
+ if(key_file)
+ result = nss_load_key(conn, sockindex, key_file);
+ else
+ /* In case the cert file also has the key */
+ result = nss_load_key(conn, sockindex, cert_file);
+ if(result) {
+ const PRErrorCode err = PR_GetError();
+ if(!display_error(conn, err, key_file)) {
+ const char *err_name = nss_error_to_name(err);
+ failf(data, "unable to load client key: %d (%s)", err, err_name);
+ }
+
+ return result;
+ }
+ }
+
+ return CURLE_OK;
+}
+
+static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
+{
+ (void)slot; /* unused */
+
+ if(retry || NULL == arg)
+ return NULL;
+ else
+ return (char *)PORT_Strdup((char *)arg);
+}
+
+/* bypass the default SSL_AuthCertificate() hook in case we do not want to
+ * verify peer */
+static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
+ PRBool isServer)
+{
+ struct connectdata *conn = (struct connectdata *)arg;
+
+#ifdef SSL_ENABLE_OCSP_STAPLING
+ if(conn->data->set.ssl.verifystatus) {
+ SECStatus cacheResult;
+
+ const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
+ if(!csa) {
+ failf(conn->data, "Invalid OCSP response");
+ return SECFailure;
+ }
+
+ if(csa->len == 0) {
+ failf(conn->data, "No OCSP response received");
+ return SECFailure;
+ }
+
+ cacheResult = CERT_CacheOCSPResponseFromSideChannel(
+ CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd),
+ PR_Now(), &csa->items[0], arg
+ );
+
+ if(cacheResult != SECSuccess) {
+ failf(conn->data, "Invalid OCSP response");
+ return cacheResult;
+ }
+ }
+#endif
+
+ if(!conn->data->set.ssl.verifypeer) {
+ infof(conn->data, "skipping SSL peer certificate verification\n");
+ return SECSuccess;
+ }
+
+ return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
+}
+
+/**
+ * Inform the application that the handshake is complete.
+ */
+static void HandshakeCallback(PRFileDesc *sock, void *arg)
+{
+ struct connectdata *conn = (struct connectdata*) arg;
+ unsigned int buflenmax = 50;
+ unsigned char buf[50];
+ unsigned int buflen;
+ SSLNextProtoState state;
+
+ if(!conn->data->set.ssl_enable_npn && !conn->data->set.ssl_enable_alpn) {
+ return;
+ }
+
+ if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
+
+ switch(state) {
+ case SSL_NEXT_PROTO_NO_SUPPORT:
+ case SSL_NEXT_PROTO_NO_OVERLAP:
+ infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n");
+ return;
+#ifdef SSL_ENABLE_ALPN
+ case SSL_NEXT_PROTO_SELECTED:
+ infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf);
+ break;
+#endif
+ case SSL_NEXT_PROTO_NEGOTIATED:
+ infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf);
+ break;
+ }
+
+#ifdef USE_NGHTTP2
+ if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) {
+ conn->negnpn = CURL_HTTP_VERSION_2_0;
+ }
+ else
+#endif
+ if(buflen == ALPN_HTTP_1_1_LENGTH &&
+ !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ }
+}
+
+static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
+ PRBool *canFalseStart)
+{
+ struct connectdata *conn = client_data;
+ struct SessionHandle *data = conn->data;
+
+ SSLChannelInfo channelInfo;
+ SSLCipherSuiteInfo cipherInfo;
+
+ SECStatus rv;
+ PRBool negotiatedExtension;
+
+ *canFalseStart = PR_FALSE;
+
+ if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess)
+ return SECFailure;
+
+ if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
+ sizeof(cipherInfo)) != SECSuccess)
+ return SECFailure;
+
+ /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for
+ * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310
+ */
+ if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2)
+ goto end;
+
+ /* Only allow ECDHE key exchange algorithm.
+ * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */
+ if(cipherInfo.keaType != ssl_kea_ecdh)
+ goto end;
+
+ /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC
+ * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt
+ * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */
+ if(cipherInfo.symCipher != ssl_calg_aes_gcm)
+ goto end;
+
+ /* Enforce ALPN or NPN to do False Start, as an indicator of server
+ * compatibility. */
+ rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn,
+ &negotiatedExtension);
+ if(rv != SECSuccess || !negotiatedExtension) {
+ rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn,
+ &negotiatedExtension);
+ }
+
+ if(rv != SECSuccess || !negotiatedExtension)
+ goto end;
+
+ *canFalseStart = PR_TRUE;
+
+ infof(data, "Trying TLS False Start\n");
+
+end:
+ return SECSuccess;
+}
+
+static void display_cert_info(struct SessionHandle *data,
+ CERTCertificate *cert)
+{
+ char *subject, *issuer, *common_name;
+ PRExplodedTime printableTime;
+ char timeString[256];
+ PRTime notBefore, notAfter;
+
+ subject = CERT_NameToAscii(&cert->subject);
+ issuer = CERT_NameToAscii(&cert->issuer);
+ common_name = CERT_GetCommonName(&cert->subject);
+ infof(data, "\tsubject: %s\n", subject);
+
+ CERT_GetCertTimes(cert, &notBefore, &notAfter);
+ PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
+ PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
+ infof(data, "\tstart date: %s\n", timeString);
+ PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
+ PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
+ infof(data, "\texpire date: %s\n", timeString);
+ infof(data, "\tcommon name: %s\n", common_name);
+ infof(data, "\tissuer: %s\n", issuer);
+
+ PR_Free(subject);
+ PR_Free(issuer);
+ PR_Free(common_name);
+}
+
+static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
+{
+ CURLcode result = CURLE_OK;
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+ CERTCertificate *cert;
+ CERTCertificate *cert2;
+ CERTCertificate *cert3;
+ PRTime now;
+ int i;
+
+ if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
+ SECSuccess && channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite) == SECSuccess) {
+ infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
+ }
+ }
+
+ cert = SSL_PeerCertificate(sock);
+ if(cert) {
+ infof(conn->data, "Server certificate:\n");
+
+ if(!conn->data->set.ssl.certinfo) {
+ display_cert_info(conn->data, cert);
+ CERT_DestroyCertificate(cert);
+ }
+ else {
+ /* Count certificates in chain. */
+ now = PR_Now();
+ i = 1;
+ if(!cert->isRoot) {
+ cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
+ while(cert2) {
+ i++;
+ if(cert2->isRoot) {
+ CERT_DestroyCertificate(cert2);
+ break;
+ }
+ cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
+ CERT_DestroyCertificate(cert2);
+ cert2 = cert3;
+ }
+ }
+
+ result = Curl_ssl_init_certinfo(conn->data, i);
+ if(!result) {
+ for(i = 0; cert; cert = cert2) {
+ result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
+ (char *)cert->derCert.data +
+ cert->derCert.len);
+ if(result)
+ break;
+
+ if(cert->isRoot) {
+ CERT_DestroyCertificate(cert);
+ break;
+ }
+
+ cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
+{
+ struct connectdata *conn = (struct connectdata *)arg;
+ struct SessionHandle *data = conn->data;
+ PRErrorCode err = PR_GetError();
+ CERTCertificate *cert;
+
+ /* remember the cert verification result */
+ data->set.ssl.certverifyresult = err;
+
+ if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
+ /* we are asked not to verify the host name */
+ return SECSuccess;
+
+ /* print only info about the cert, the error is printed off the callback */
+ cert = SSL_PeerCertificate(sock);
+ if(cert) {
+ infof(data, "Server certificate:\n");
+ display_cert_info(data, cert);
+ CERT_DestroyCertificate(cert);
+ }
+
+ return SECFailure;
+}
+
+/**
+ *
+ * Check that the Peer certificate's issuer certificate matches the one found
+ * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the
+ * issuer check, so we provide comments that mimic the OpenSSL
+ * X509_check_issued function (in x509v3/v3_purp.c)
+ */
+static SECStatus check_issuer_cert(PRFileDesc *sock,
+ char *issuer_nickname)
+{
+ CERTCertificate *cert, *cert_issuer, *issuer;
+ SECStatus res=SECSuccess;
+ void *proto_win = NULL;
+
+ /*
+ PRArenaPool *tmpArena = NULL;
+ CERTAuthKeyID *authorityKeyID = NULL;
+ SECITEM *caname = NULL;
+ */
+
+ cert = SSL_PeerCertificate(sock);
+ cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner);
+
+ proto_win = SSL_RevealPinArg(sock);
+ issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
+
+ if((!cert_issuer) || (!issuer))
+ res = SECFailure;
+ else if(SECITEM_CompareItem(&cert_issuer->derCert,
+ &issuer->derCert)!=SECEqual)
+ res = SECFailure;
+
+ CERT_DestroyCertificate(cert);
+ CERT_DestroyCertificate(issuer);
+ CERT_DestroyCertificate(cert_issuer);
+ return res;
+}
+
+/**
+ *
+ * Callback to pick the SSL client certificate.
+ */
+static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
+ struct SessionHandle *data = connssl->data;
+ const char *nickname = connssl->client_nickname;
+
+ if(connssl->obj_clicert) {
+ /* use the cert/key provided by PEM reader */
+ static const char pem_slotname[] = "PEM Token #1";
+ SECItem cert_der = { 0, NULL, 0 };
+ void *proto_win = SSL_RevealPinArg(sock);
+ struct CERTCertificateStr *cert;
+ struct SECKEYPrivateKeyStr *key;
+
+ PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
+ if(NULL == slot) {
+ failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
+ return SECFailure;
+ }
+
+ if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
+ &cert_der) != SECSuccess) {
+ failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
+ PK11_FreeSlot(slot);
+ return SECFailure;
+ }
+
+ cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
+ SECITEM_FreeItem(&cert_der, PR_FALSE);
+ if(NULL == cert) {
+ failf(data, "NSS: client certificate from file not found");
+ PK11_FreeSlot(slot);
+ return SECFailure;
+ }
+
+ key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
+ PK11_FreeSlot(slot);
+ if(NULL == key) {
+ failf(data, "NSS: private key from file not found");
+ CERT_DestroyCertificate(cert);
+ return SECFailure;
+ }
+
+ infof(data, "NSS: client certificate from file\n");
+ display_cert_info(data, cert);
+
+ *pRetCert = cert;
+ *pRetKey = key;
+ return SECSuccess;
+ }
+
+ /* use the default NSS hook */
+ if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
+ pRetCert, pRetKey)
+ || NULL == *pRetCert) {
+
+ if(NULL == nickname)
+ failf(data, "NSS: client certificate not found (nickname not "
+ "specified)");
+ else
+ failf(data, "NSS: client certificate not found: %s", nickname);
+
+ return SECFailure;
+ }
+
+ /* get certificate nickname if any */
+ nickname = (*pRetCert)->nickname;
+ if(NULL == nickname)
+ nickname = "[unknown]";
+
+ if(NULL == *pRetKey) {
+ failf(data, "NSS: private key not found for certificate: %s", nickname);
+ return SECFailure;
+ }
+
+ infof(data, "NSS: using client certificate: %s\n", nickname);
+ display_cert_info(data, *pRetCert);
+ return SECSuccess;
+}
+
+/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */
+static void nss_update_connecting_state(ssl_connect_state state, void *secret)
+{
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret;
+ if(PR_GetError() != PR_WOULD_BLOCK_ERROR)
+ /* an unrelated error is passing by */
+ return;
+
+ switch(connssl->connecting_state) {
+ case ssl_connect_2:
+ case ssl_connect_2_reading:
+ case ssl_connect_2_writing:
+ break;
+ default:
+ /* we are not called from an SSL handshake */
+ return;
+ }
+
+ /* update the state accordingly */
+ connssl->connecting_state = state;
+}
+
+/* recv() wrapper we use to detect blocking direction during SSL handshake */
+static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ const PRRecvFN recv_fn = fd->lower->methods->recv;
+ const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout);
+ if(rv < 0)
+ /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
+ nss_update_connecting_state(ssl_connect_2_reading, fd->secret);
+ return rv;
+}
+
+/* send() wrapper we use to detect blocking direction during SSL handshake */
+static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ const PRSendFN send_fn = fd->lower->methods->send;
+ const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout);
+ if(rv < 0)
+ /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
+ nss_update_connecting_state(ssl_connect_2_writing, fd->secret);
+ return rv;
+}
+
+/* close() wrapper to avoid assertion failure due to fd->secret != NULL */
+static PRStatus nspr_io_close(PRFileDesc *fd)
+{
+ const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close;
+ fd->secret = NULL;
+ return close_fn(fd);
+}
+
+/* data might be NULL */
+static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
+{
+ NSSInitParameters initparams;
+
+ if(nss_context != NULL)
+ return CURLE_OK;
+
+ memset((void *) &initparams, '\0', sizeof(initparams));
+ initparams.length = sizeof(initparams);
+
+ if(cert_dir) {
+ char *certpath = aprintf("sql:%s", cert_dir);
+ if(!certpath)
+ return CURLE_OUT_OF_MEMORY;
+
+ infof(data, "Initializing NSS with certpath: %s\n", certpath);
+ nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
+ NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
+ free(certpath);
+
+ if(nss_context != NULL)
+ return CURLE_OK;
+
+ infof(data, "Unable to initialize NSS database\n");
+ }
+
+ infof(data, "Initializing NSS with certpath: none\n");
+ nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
+ | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
+ | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
+ if(nss_context != NULL)
+ return CURLE_OK;
+
+ infof(data, "Unable to initialize NSS\n");
+ return CURLE_SSL_CACERT_BADFILE;
+}
+
+/* data might be NULL */
+static CURLcode nss_init(struct SessionHandle *data)
+{
+ char *cert_dir;
+ struct_stat st;
+ CURLcode result;
+
+ if(initialized)
+ return CURLE_OK;
+
+ /* list of all CRL items we need to destroy in Curl_nss_cleanup() */
+ nss_crl_list = Curl_llist_alloc(nss_destroy_crl_item);
+ if(!nss_crl_list)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* First we check if $SSL_DIR points to a valid dir */
+ cert_dir = getenv("SSL_DIR");
+ if(cert_dir) {
+ if((stat(cert_dir, &st) != 0) ||
+ (!S_ISDIR(st.st_mode))) {
+ cert_dir = NULL;
+ }
+ }
+
+ /* Now we check if the default location is a valid dir */
+ if(!cert_dir) {
+ if((stat(SSL_DIR, &st) == 0) &&
+ (S_ISDIR(st.st_mode))) {
+ cert_dir = (char *)SSL_DIR;
+ }
+ }
+
+ if(nspr_io_identity == PR_INVALID_IO_LAYER) {
+ /* allocate an identity for our own NSPR I/O layer */
+ nspr_io_identity = PR_GetUniqueIdentity("libcurl");
+ if(nspr_io_identity == PR_INVALID_IO_LAYER)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* the default methods just call down to the lower I/O layer */
+ memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods);
+
+ /* override certain methods in the table by our wrappers */
+ nspr_io_methods.recv = nspr_io_recv;
+ nspr_io_methods.send = nspr_io_send;
+ nspr_io_methods.close = nspr_io_close;
+ }
+
+ result = nss_init_core(data, cert_dir);
+ if(result)
+ return result;
+
+ if(num_enabled_ciphers() == 0)
+ NSS_SetDomesticPolicy();
+
+ initialized = 1;
+
+ return CURLE_OK;
+}
+
+/**
+ * Global SSL init
+ *
+ * @retval 0 error initializing SSL
+ * @retval 1 SSL initialized successfully
+ */
+CURL_STATIC int Curl_nss_init(void)
+{
+ /* curl_global_init() is not thread-safe so this test is ok */
+ if(nss_initlock == NULL) {
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
+ nss_initlock = PR_NewLock();
+ nss_crllock = PR_NewLock();
+ }
+
+ /* We will actually initialize NSS later */
+
+ return 1;
+}
+
+/* data might be NULL */
+CURL_STATIC CURLcode Curl_nss_force_init(struct SessionHandle *data)
+{
+ CURLcode result;
+ if(!nss_initlock) {
+ if(data)
+ failf(data, "unable to initialize NSS, curl_global_init() should have "
+ "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
+ return CURLE_FAILED_INIT;
+ }
+
+ PR_Lock(nss_initlock);
+ result = nss_init(data);
+ PR_Unlock(nss_initlock);
+
+ return result;
+}
+
+/* Global cleanup */
+CURL_STATIC void Curl_nss_cleanup(void)
+{
+ /* This function isn't required to be threadsafe and this is only done
+ * as a safety feature.
+ */
+ PR_Lock(nss_initlock);
+ if(initialized) {
+ /* Free references to client certificates held in the SSL session cache.
+ * Omitting this hampers destruction of the security module owning
+ * the certificates. */
+ SSL_ClearSessionCache();
+
+ if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
+ SECMOD_DestroyModule(mod);
+ mod = NULL;
+ }
+ NSS_ShutdownContext(nss_context);
+ nss_context = NULL;
+ }
+
+ /* destroy all CRL items */
+ Curl_llist_destroy(nss_crl_list, NULL);
+ nss_crl_list = NULL;
+
+ PR_Unlock(nss_initlock);
+
+ PR_DestroyLock(nss_initlock);
+ PR_DestroyLock(nss_crllock);
+ nss_initlock = NULL;
+
+ initialized = 0;
+}
+
+/*
+ * This function uses SSL_peek to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+CURL_STATIC int
+Curl_nss_check_cxn(struct connectdata *conn)
+{
+ int rc;
+ char buf;
+
+ rc =
+ PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
+ PR_SecondsToInterval(1));
+ if(rc > 0)
+ return 1; /* connection still in place */
+
+ if(rc == 0)
+ return 0; /* connection has been closed */
+
+ return -1; /* connection status unknown */
+}
+
+/*
+ * This function is called when an SSL connection is closed.
+ */
+CURL_STATIC void Curl_nss_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->handle) {
+ /* NSS closes the socket we previously handed to it, so we must mark it
+ as closed to avoid double close */
+ fake_sclose(conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+
+ if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
+ /* A server might require different authentication based on the
+ * particular path being requested by the client. To support this
+ * scenario, we must ensure that a connection will never reuse the
+ * authentication data from a previous connection. */
+ SSL_InvalidateSession(connssl->handle);
+
+ free(connssl->client_nickname);
+ connssl->client_nickname = NULL;
+ /* destroy all NSS objects in order to avoid failure of NSS shutdown */
+ Curl_llist_destroy(connssl->obj_list, NULL);
+ connssl->obj_list = NULL;
+ connssl->obj_clicert = NULL;
+
+ PR_Close(connssl->handle);
+ connssl->handle = NULL;
+ }
+}
+
+/* return true if NSS can provide error code (and possibly msg) for the
+ error */
+static bool is_nss_error(CURLcode err)
+{
+ switch(err) {
+ case CURLE_PEER_FAILED_VERIFICATION:
+ case CURLE_SSL_CACERT:
+ case CURLE_SSL_CERTPROBLEM:
+ case CURLE_SSL_CONNECT_ERROR:
+ case CURLE_SSL_ISSUER_ERROR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* return true if the given error code is related to a client certificate */
+static bool is_cc_error(PRInt32 err)
+{
+ switch(err) {
+ case SSL_ERROR_BAD_CERT_ALERT:
+ case SSL_ERROR_EXPIRED_CERT_ALERT:
+ case SSL_ERROR_REVOKED_CERT_ALERT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static Curl_recv nss_recv;
+static Curl_send nss_send;
+
+static CURLcode nss_load_ca_certificates(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ const char *cafile = data->set.ssl.CAfile;
+ const char *capath = data->set.ssl.CApath;
+
+ if(cafile) {
+ CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
+ if(result)
+ return result;
+ }
+
+ if(capath) {
+ struct_stat st;
+ if(stat(capath, &st) == -1)
+ return CURLE_SSL_CACERT_BADFILE;
+
+ if(S_ISDIR(st.st_mode)) {
+ PRDirEntry *entry;
+ PRDir *dir = PR_OpenDir(capath);
+ if(!dir)
+ return CURLE_SSL_CACERT_BADFILE;
+
+ while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
+ char *fullpath = aprintf("%s/%s", capath, entry->name);
+ if(!fullpath) {
+ PR_CloseDir(dir);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
+ /* This is purposefully tolerant of errors so non-PEM files can
+ * be in the same directory */
+ infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
+
+ free(fullpath);
+ }
+
+ PR_CloseDir(dir);
+ }
+ else
+ infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
+ }
+
+ infof(data, " CAfile: %s\n CApath: %s\n",
+ cafile ? cafile : "none",
+ capath ? capath : "none");
+
+ return CURLE_OK;
+}
+
+static CURLcode nss_init_sslver(SSLVersionRange *sslver,
+ struct SessionHandle *data)
+{
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+#ifdef SSL_LIBRARY_VERSION_TLS_1_2
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+#elif defined SSL_LIBRARY_VERSION_TLS_1_1
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+#else
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+#endif
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_SSLv2:
+ sslver->min = SSL_LIBRARY_VERSION_2;
+ sslver->max = SSL_LIBRARY_VERSION_2;
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_SSLv3:
+ sslver->min = SSL_LIBRARY_VERSION_3_0;
+ sslver->max = SSL_LIBRARY_VERSION_3_0;
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_TLSv1_0:
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_TLSv1_1:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_1
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_1;
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+ return CURLE_OK;
+#endif
+ break;
+
+ case CURL_SSLVERSION_TLSv1_2:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_2
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_2;
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+ return CURLE_OK;
+#endif
+ break;
+ }
+
+ failf(data, "TLS minor version cannot be set");
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
+ struct SessionHandle *data,
+ CURLcode curlerr)
+{
+ PRErrorCode err = 0;
+
+ if(is_nss_error(curlerr)) {
+ /* read NSPR error code */
+ err = PR_GetError();
+ if(is_cc_error(err))
+ curlerr = CURLE_SSL_CERTPROBLEM;
+
+ /* print the error number and error string */
+ infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
+
+ /* print a human-readable message describing the error if available */
+ nss_print_error_message(data, err);
+ }
+
+ /* cleanup on connection failure */
+ Curl_llist_destroy(connssl->obj_list, NULL);
+ connssl->obj_list = NULL;
+
+ return curlerr;
+}
+
+/* Switch the SSL socket into non-blocking mode. */
+static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
+ struct SessionHandle *data)
+{
+ static PRSocketOptionData sock_opt;
+ sock_opt.option = PR_SockOpt_Nonblocking;
+ sock_opt.value.non_blocking = PR_TRUE;
+
+ if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
+ return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
+
+ return CURLE_OK;
+}
+
+static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
+{
+ PRFileDesc *model = NULL;
+ PRFileDesc *nspr_io = NULL;
+ PRFileDesc *nspr_io_stub = NULL;
+ PRBool ssl_no_cache;
+ PRBool ssl_cbc_random_iv;
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode result;
+
+ SSLVersionRange sslver = {
+ SSL_LIBRARY_VERSION_TLS_1_0, /* min */
+ SSL_LIBRARY_VERSION_TLS_1_0 /* max */
+ };
+
+ connssl->data = data;
+
+ /* list of all NSS objects we need to destroy in Curl_nss_close() */
+ connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
+ if(!connssl->obj_list)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* FIXME. NSS doesn't support multiple databases open at the same time. */
+ PR_Lock(nss_initlock);
+ result = nss_init(conn->data);
+ if(result) {
+ PR_Unlock(nss_initlock);
+ goto error;
+ }
+
+ result = CURLE_SSL_CONNECT_ERROR;
+
+ if(!mod) {
+ char *configstring = aprintf("library=%s name=PEM", pem_library);
+ if(!configstring) {
+ PR_Unlock(nss_initlock);
+ goto error;
+ }
+ mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
+ free(configstring);
+
+ if(!mod || !mod->loaded) {
+ if(mod) {
+ SECMOD_DestroyModule(mod);
+ mod = NULL;
+ }
+ infof(data, "WARNING: failed to load NSS PEM library %s. Using "
+ "OpenSSL PEM certificates will not work.\n", pem_library);
+ }
+ }
+
+ PK11_SetPasswordFunc(nss_get_password);
+ PR_Unlock(nss_initlock);
+
+ model = PR_NewTCPSocket();
+ if(!model)
+ goto error;
+ model = SSL_ImportFD(NULL, model);
+
+ if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
+ goto error;
+ if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
+ goto error;
+ if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
+ goto error;
+
+ /* do not use SSL cache if disabled or we are not going to verify peer */
+ ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
+ PR_FALSE : PR_TRUE;
+ if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
+ goto error;
+
+ /* enable/disable the requested SSL version(s) */
+ if(nss_init_sslver(&sslver, data) != CURLE_OK)
+ goto error;
+ if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
+ goto error;
+
+ ssl_cbc_random_iv = !data->set.ssl_enable_beast;
+#ifdef SSL_CBC_RANDOM_IV
+ /* unless the user explicitly asks to allow the protocol vulnerability, we
+ use the work-around */
+ if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
+ infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
+ ssl_cbc_random_iv);
+#else
+ if(ssl_cbc_random_iv)
+ infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
+#endif
+
+ if(data->set.ssl.cipher_list) {
+ if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
+ result = CURLE_SSL_CIPHER;
+ goto error;
+ }
+ }
+
+ if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
+ infof(data, "warning: ignoring value of ssl.verifyhost\n");
+
+ /* bypass the default SSL_AuthCertificate() hook in case we do not want to
+ * verify peer */
+ if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
+ goto error;
+
+ data->set.ssl.certverifyresult=0; /* not checked yet */
+ if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
+ goto error;
+
+ if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
+ goto error;
+
+ if(data->set.ssl.verifypeer) {
+ const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
+ if(rv) {
+ result = rv;
+ goto error;
+ }
+ }
+
+ if(data->set.ssl.CRLfile) {
+ const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile);
+ if(rv) {
+ result = rv;
+ goto error;
+ }
+ infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile);
+ }
+
+ if(data->set.str[STRING_CERT]) {
+ char *nickname = dup_nickname(data, STRING_CERT);
+ if(nickname) {
+ /* we are not going to use libnsspem.so to read the client cert */
+ connssl->obj_clicert = NULL;
+ }
+ else {
+ CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY]);
+ if(rv) {
+ /* failf() is already done in cert_stuff() */
+ result = rv;
+ goto error;
+ }
+ }
+
+ /* store the nickname for SelectClientCert() called during handshake */
+ connssl->client_nickname = nickname;
+ }
+ else
+ connssl->client_nickname = NULL;
+
+ if(SSL_GetClientAuthDataHook(model, SelectClientCert,
+ (void *)connssl) != SECSuccess) {
+ result = CURLE_SSL_CERTPROBLEM;
+ goto error;
+ }
+
+ /* wrap OS file descriptor by NSPR's file descriptor abstraction */
+ nspr_io = PR_ImportTCPSocket(sockfd);
+ if(!nspr_io)
+ goto error;
+
+ /* create our own NSPR I/O layer */
+ nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
+ if(!nspr_io_stub) {
+ PR_Close(nspr_io);
+ goto error;
+ }
+
+ /* make the per-connection data accessible from NSPR I/O callbacks */
+ nspr_io_stub->secret = (void *)connssl;
+
+ /* push our new layer to the NSPR I/O stack */
+ if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
+ PR_Close(nspr_io);
+ PR_Close(nspr_io_stub);
+ goto error;
+ }
+
+ /* import our model socket onto the current I/O stack */
+ connssl->handle = SSL_ImportFD(model, nspr_io);
+ if(!connssl->handle) {
+ PR_Close(nspr_io);
+ goto error;
+ }
+
+ PR_Close(model); /* We don't need this any more */
+ model = NULL;
+
+ /* This is the password associated with the cert that we're using */
+ if(data->set.str[STRING_KEY_PASSWD]) {
+ SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
+ }
+
+#ifdef SSL_ENABLE_OCSP_STAPLING
+ if(data->set.ssl.verifystatus) {
+ if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
+ != SECSuccess)
+ goto error;
+ }
+#endif
+
+#ifdef SSL_ENABLE_NPN
+ if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, data->set.ssl_enable_npn
+ ? PR_TRUE : PR_FALSE) != SECSuccess)
+ goto error;
+#endif
+
+#ifdef SSL_ENABLE_ALPN
+ if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, data->set.ssl_enable_alpn
+ ? PR_TRUE : PR_FALSE) != SECSuccess)
+ goto error;
+#endif
+
+#ifdef SSL_ENABLE_FALSE_START
+ if(data->set.ssl.falsestart) {
+ if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
+ != SECSuccess)
+ goto error;
+
+ if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback,
+ conn) != SECSuccess)
+ goto error;
+ }
+#endif
+
+#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
+ if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) {
+ int cur = 0;
+ unsigned char protocols[128];
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+ protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
+ memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN);
+ cur += NGHTTP2_PROTO_VERSION_ID_LEN;
+ }
+#endif
+ protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
+ memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
+ cur += ALPN_HTTP_1_1_LENGTH;
+
+ if(SSL_SetNextProtoNego(connssl->handle, protocols, cur) != SECSuccess)
+ goto error;
+ }
+#endif
+
+
+ /* Force handshake on next I/O */
+ SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
+
+ SSL_SetURL(connssl->handle, conn->host.name);
+
+ return CURLE_OK;
+
+error:
+ if(model)
+ PR_Close(model);
+
+ return nss_fail_connect(connssl, data, result);
+}
+
+static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ CURLcode result = CURLE_SSL_CONNECT_ERROR;
+ PRUint32 timeout;
+
+ /* check timeout situation */
+ const long time_left = Curl_timeleft(data, NULL, TRUE);
+ if(time_left < 0L) {
+ failf(data, "timed out before SSL handshake");
+ result = CURLE_OPERATION_TIMEDOUT;
+ goto error;
+ }
+
+ /* Force the handshake now */
+ timeout = PR_MillisecondsToInterval((PRUint32) time_left);
+ if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
+ if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
+ /* blocking direction is updated by nss_update_connecting_state() */
+ return CURLE_AGAIN;
+ else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ else if(conn->data->set.ssl.certverifyresult!=0)
+ result = CURLE_SSL_CACERT;
+ goto error;
+ }
+
+ result = display_conn_info(conn, connssl->handle);
+ if(result)
+ goto error;
+
+ if(data->set.str[STRING_SSL_ISSUERCERT]) {
+ SECStatus ret = SECFailure;
+ char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
+ if(nickname) {
+ /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
+ ret = check_issuer_cert(connssl->handle, nickname);
+ free(nickname);
+ }
+
+ if(SECFailure == ret) {
+ infof(data, "SSL certificate issuer check failed\n");
+ result = CURLE_SSL_ISSUER_ERROR;
+ goto error;
+ }
+ else {
+ infof(data, "SSL certificate issuer check ok\n");
+ }
+ }
+
+ return CURLE_OK;
+
+error:
+ return nss_fail_connect(connssl, data, result);
+}
+
+static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ const bool blocking = (done == NULL);
+ CURLcode result;
+
+ if(connssl->state == ssl_connection_complete)
+ return CURLE_OK;
+
+ if(connssl->connecting_state == ssl_connect_1) {
+ result = nss_setup_connect(conn, sockindex);
+ if(result)
+ /* we do not expect CURLE_AGAIN from nss_setup_connect() */
+ return result;
+
+ if(!blocking) {
+ /* in non-blocking mode, set NSS non-blocking mode before handshake */
+ result = nss_set_nonblock(connssl, data);
+ if(result)
+ return result;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+ }
+
+ result = nss_do_connect(conn, sockindex);
+ switch(result) {
+ case CURLE_OK:
+ break;
+ case CURLE_AGAIN:
+ if(!blocking)
+ /* CURLE_AGAIN in non-blocking mode is not an error */
+ return CURLE_OK;
+ /* fall through */
+ default:
+ return result;
+ }
+
+ if(blocking) {
+ /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
+ result = nss_set_nonblock(connssl, data);
+ if(result)
+ return result;
+ }
+ else
+ /* signal completed SSL handshake */
+ *done = TRUE;
+
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = nss_recv;
+ conn->send[sockindex] = nss_send;
+
+ /* ssl_connect_done is never used outside, go back to the initial state */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+{
+ return nss_connect_common(conn, sockindex, /* blocking */ NULL);
+}
+
+CURL_STATIC CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
+{
+ return nss_connect_common(conn, sockindex, done);
+}
+
+static ssize_t nss_send(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *mem, /* send this data */
+ size_t len, /* amount to write */
+ CURLcode *curlcode)
+{
+ ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
+ PR_INTERVAL_NO_WAIT);
+ if(rc < 0) {
+ PRInt32 err = PR_GetError();
+ if(err == PR_WOULD_BLOCK_ERROR)
+ *curlcode = CURLE_AGAIN;
+ else {
+ /* print the error number and error string */
+ const char *err_name = nss_error_to_name(err);
+ infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
+
+ /* print a human-readable message describing the error if available */
+ nss_print_error_message(conn->data, err);
+
+ *curlcode = (is_cc_error(err))
+ ? CURLE_SSL_CERTPROBLEM
+ : CURLE_SEND_ERROR;
+ }
+
+ return -1;
+ }
+
+ return rc; /* number of bytes */
+}
+
+static ssize_t nss_recv(struct connectdata * conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *curlcode)
+{
+ ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
+ PR_INTERVAL_NO_WAIT);
+ if(nread < 0) {
+ /* failed SSL read */
+ PRInt32 err = PR_GetError();
+
+ if(err == PR_WOULD_BLOCK_ERROR)
+ *curlcode = CURLE_AGAIN;
+ else {
+ /* print the error number and error string */
+ const char *err_name = nss_error_to_name(err);
+ infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
+
+ /* print a human-readable message describing the error if available */
+ nss_print_error_message(conn->data, err);
+
+ *curlcode = (is_cc_error(err))
+ ? CURLE_SSL_CERTPROBLEM
+ : CURLE_RECV_ERROR;
+ }
+
+ return -1;
+ }
+
+ return nread;
+}
+
+CURL_STATIC size_t Curl_nss_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
+}
+
+/* data might be NULL */
+CURL_STATIC int Curl_nss_seed(struct SessionHandle *data)
+{
+ /* make sure that NSS is initialized */
+ return !!Curl_nss_force_init(data);
+}
+
+/* data might be NULL */
+CURL_STATIC int Curl_nss_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ Curl_nss_seed(data); /* Initiate the seed if not already done */
+
+ if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length)))
+ /* signal a failure */
+ return -1;
+
+ return 0;
+}
+
+CURL_STATIC void Curl_nss_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+ PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
+ unsigned int MD5out;
+
+ PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
+ PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
+ PK11_DestroyContext(MD5pw, PR_TRUE);
+}
+
+CURL_STATIC bool Curl_nss_cert_status_request(void)
+{
+#ifdef SSL_ENABLE_OCSP_STAPLING
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+CURL_STATIC bool Curl_nss_false_start(void) {
+#ifdef SSL_ENABLE_FALSE_START
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+#endif /* USE_NSS */
diff --git a/libcurl/src/lib/vtls/nssg.h b/libcurl/src/lib/vtls/nssg.h
new file mode 100644
index 0000000..7eba897
--- /dev/null
+++ b/libcurl/src/lib/vtls/nssg.h
@@ -0,0 +1,96 @@
+#ifndef HEADER_CURL_NSSG_H
+#define HEADER_CURL_NSSG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+#ifdef USE_NSS
+/*
+ * This header should only be needed to get included by vtls.c and nss.c
+ */
+
+#include "urldata.h"
+
+CURL_STATIC CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+/* close a SSL connection */
+CURL_STATIC void Curl_nss_close(struct connectdata *conn, int sockindex);
+
+CURL_STATIC int Curl_nss_init(void);
+CURL_STATIC void Curl_nss_cleanup(void);
+
+CURL_STATIC size_t Curl_nss_version(char *buffer, size_t size);
+CURL_STATIC int Curl_nss_check_cxn(struct connectdata *cxn);
+CURL_STATIC int Curl_nss_seed(struct SessionHandle *data);
+
+/* initialize NSS library if not already */
+CURL_STATIC CURLcode Curl_nss_force_init(struct SessionHandle *data);
+
+CURL_STATIC int Curl_nss_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+
+CURL_STATIC void Curl_nss_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+
+CURL_STATIC bool Curl_nss_cert_status_request(void);
+
+CURL_STATIC bool Curl_nss_false_start(void);
+
+/* Set the API backend definition to NSS */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
+
+/* this backend supports the CAPATH option */
+#define have_curlssl_ca_path 1
+
+/* this backend supports CURLOPT_CERTINFO */
+#define have_curlssl_certinfo 1
+
+/* API setup for NSS */
+#define curlssl_init Curl_nss_init
+#define curlssl_cleanup Curl_nss_cleanup
+#define curlssl_connect Curl_nss_connect
+#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking
+
+/* NSS has its own session ID cache */
+#define curlssl_session_free(x) Curl_nop_stmt
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_nss_close
+/* NSS has no shutdown function provided and thus always fail */
+#define curlssl_shutdown(x,y) ((void)x, (void)y, 1)
+#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_nss_version
+#define curlssl_check_cxn(x) Curl_nss_check_cxn(x)
+#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
+#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
+#define curlssl_cert_status_request() Curl_nss_cert_status_request()
+#define curlssl_false_start() Curl_nss_false_start()
+
+#endif /* USE_NSS */
+#endif /* HEADER_CURL_NSSG_H */
diff --git a/libcurl/src/lib/vtls/openssl.c b/libcurl/src/lib/vtls/openssl.c
new file mode 100644
index 0000000..a5e6b98
--- /dev/null
+++ b/libcurl/src/lib/vtls/openssl.c
@@ -0,0 +1,3226 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ */
+
+/*
+ * The original SSLeay-using code for curl was written by Linas Vepstas and
+ * Sampo Kellomaki 1998.
+ */
+
+#include "../curl_setup.h"
+
+#ifdef USE_OPENSSL
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../formdata.h" /* for the boundary function */
+#include "../url.h" /* for the ssl config check function */
+#include "../inet_pton.h"
+#include "openssl.h"
+#include "../connect.h"
+#include "../slist.h"
+#include "../strequal.h"
+#include "../select.h"
+#include "vtls.h"
+#include "../rawstr.h"
+#include "../hostcheck.h"
+#include "../curl_printf.h"
+
+#include <openssl/ssl.h>
+#include <openssl/rand.h>
+#include <openssl/x509v3.h>
+#include <openssl/dsa.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#include <openssl/conf.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#ifdef HAVE_OPENSSL_PKCS12_H
+#include <openssl/pkcs12.h>
+#endif
+
+#ifndef HAVE_BORINGSSL
+#include <openssl/ocsp.h>
+#endif
+
+#include "warnless.h"
+#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef OPENSSL_VERSION_NUMBER
+#error "OPENSSL_VERSION_NUMBER not defined"
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x0090581fL
+#define HAVE_SSL_GET1_SESSION 1
+#else
+#undef HAVE_SSL_GET1_SESSION
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00904100L
+#define HAVE_USERDATA_IN_PWD_CALLBACK 1
+#else
+#undef HAVE_USERDATA_IN_PWD_CALLBACK
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907001L && !defined(OPENSSL_IS_BORINGSSL)
+/* ENGINE_load_private_key() takes four arguments */
+#define HAVE_ENGINE_LOAD_FOUR_ARGS
+#include <openssl/ui.h>
+#else
+/* ENGINE_load_private_key() takes three arguments */
+#undef HAVE_ENGINE_LOAD_FOUR_ARGS
+#endif
+
+#if (OPENSSL_VERSION_NUMBER >= 0x00903001L) && \
+ defined(HAVE_OPENSSL_PKCS12_H) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+/* OpenSSL has PKCS 12 support, BoringSSL does not */
+#define HAVE_PKCS12_SUPPORT
+#else
+/* OpenSSL does not have PKCS12 support */
+#undef HAVE_PKCS12_SUPPORT
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00906001L
+#define HAVE_ERR_ERROR_STRING_N 1
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+#define SSL_METHOD_QUAL const
+#else
+#define SSL_METHOD_QUAL
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+/* 0.9.6 didn't have X509_STORE_set_flags() */
+#define HAVE_X509_STORE_SET_FLAGS 1
+#else
+#define X509_STORE_set_flags(x,y) Curl_nop_stmt
+#endif
+
+#ifdef OPENSSL_IS_BORINGSSL
+/* BoringSSL has no ERR_remove_state() */
+#define ERR_remove_state(x)
+#elif (OPENSSL_VERSION_NUMBER >= 0x10000000L)
+#define HAVE_ERR_REMOVE_THREAD_STATE 1
+#endif
+
+#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \
+ OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */
+#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */
+#define OPENSSL_NO_SSL2
+#endif
+
+#if defined(OPENSSL_IS_BORINGSSL)
+#define NO_RAND_SEED 1
+/* In BoringSSL OpenSSL_add_all_algorithms does nothing */
+#define OpenSSL_add_all_algorithms()
+/* BoringSSL does not have CONF_modules_load_file */
+#define CONF_modules_load_file(a,b,c)
+#endif
+
+/*
+ * Number of bytes to read from the random number seed file. This must be
+ * a finite value (because some entropy "files" like /dev/urandom have
+ * an infinite length), but must be large enough to provide enough
+ * entopy to properly seed OpenSSL's PRNG.
+ */
+#define RAND_LOAD_LENGTH 1024
+
+#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
+static char global_passwd[64];
+#endif
+
+static int passwd_callback(char *buf, int num, int encrypting
+#ifdef HAVE_USERDATA_IN_PWD_CALLBACK
+ /* This was introduced in 0.9.4, we can set this
+ using SSL_CTX_set_default_passwd_cb_userdata()
+ */
+ , void *global_passwd
+#endif
+ )
+{
+ DEBUGASSERT(0 == encrypting);
+
+ if(!encrypting) {
+ int klen = curlx_uztosi(strlen((char *)global_passwd));
+ if(num > klen) {
+ memcpy(buf, global_passwd, klen+1);
+ return klen;
+ }
+ }
+ return 0;
+}
+
+/*
+ * rand_enough() is a function that returns TRUE if we have seeded the random
+ * engine properly. We use some preprocessor magic to provide a seed_enough()
+ * macro to use, just to prevent a compiler warning on this function if we
+ * pass in an argument that is never used.
+ */
+
+#ifndef NO_RAND_SEED
+#ifdef HAVE_RAND_STATUS
+#define seed_enough(x) rand_enough()
+static bool rand_enough(void)
+{
+ return (0 != RAND_status()) ? TRUE : FALSE;
+}
+#else
+#define seed_enough(x) rand_enough(x)
+static bool rand_enough(int nread)
+{
+ /* this is a very silly decision to make */
+ return (nread > 500) ? TRUE : FALSE;
+}
+#endif
+
+static int ossl_seed(struct SessionHandle *data)
+{
+ char *buf = data->state.buffer; /* point to the big buffer */
+ int nread=0;
+
+ /* Q: should we add support for a random file name as a libcurl option?
+ A: Yes, it is here */
+
+#ifndef RANDOM_FILE
+ /* if RANDOM_FILE isn't defined, we only perform this if an option tells
+ us to! */
+ if(data->set.ssl.random_file)
+#define RANDOM_FILE "" /* doesn't matter won't be used */
+#endif
+ {
+ /* let the option override the define */
+ nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]?
+ data->set.str[STRING_SSL_RANDOM_FILE]:
+ RANDOM_FILE),
+ RAND_LOAD_LENGTH);
+ if(seed_enough(nread))
+ return nread;
+ }
+
+#if defined(HAVE_RAND_EGD)
+ /* only available in OpenSSL 0.9.5 and later */
+ /* EGD_SOCKET is set at configure time or not at all */
+#ifndef EGD_SOCKET
+ /* If we don't have the define set, we only do this if the egd-option
+ is set */
+ if(data->set.str[STRING_SSL_EGDSOCKET])
+#define EGD_SOCKET "" /* doesn't matter won't be used */
+#endif
+ {
+ /* If there's an option and a define, the option overrides the
+ define */
+ int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]?
+ data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
+ if(-1 != ret) {
+ nread += ret;
+ if(seed_enough(nread))
+ return nread;
+ }
+ }
+#endif
+
+ /* If we get here, it means we need to seed the PRNG using a "silly"
+ approach! */
+ do {
+ unsigned char randb[64];
+ int len = sizeof(randb);
+ RAND_bytes(randb, len);
+ RAND_add(randb, len, (len >> 1));
+ } while(!RAND_status());
+
+ /* generates a default path for the random seed file */
+ buf[0]=0; /* blank it first */
+ RAND_file_name(buf, BUFSIZE);
+ if(buf[0]) {
+ /* we got a file name to try */
+ nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
+ if(seed_enough(nread))
+ return nread;
+ }
+
+ infof(data, "libcurl is now using a weak random seed!\n");
+ return nread;
+}
+
+static void Curl_ossl_seed(struct SessionHandle *data)
+{
+ /* we have the "SSL is seeded" boolean static to prevent multiple
+ time-consuming seedings in vain */
+ static bool ssl_seeded = FALSE;
+
+ if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
+ data->set.str[STRING_SSL_EGDSOCKET]) {
+ ossl_seed(data);
+ ssl_seeded = TRUE;
+ }
+}
+#else
+/* BoringSSL needs no seeding */
+#define Curl_ossl_seed(x)
+#endif
+
+
+#ifndef SSL_FILETYPE_ENGINE
+#define SSL_FILETYPE_ENGINE 42
+#endif
+#ifndef SSL_FILETYPE_PKCS12
+#define SSL_FILETYPE_PKCS12 43
+#endif
+static int do_file_type(const char *type)
+{
+ if(!type || !type[0])
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "PEM"))
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "DER"))
+ return SSL_FILETYPE_ASN1;
+ if(Curl_raw_equal(type, "ENG"))
+ return SSL_FILETYPE_ENGINE;
+ if(Curl_raw_equal(type, "P12"))
+ return SSL_FILETYPE_PKCS12;
+ return -1;
+}
+
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_LOAD_FOUR_ARGS)
+/*
+ * Supply default password to the engine user interface conversation.
+ * The password is passed by OpenSSL engine from ENGINE_load_private_key()
+ * last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
+ */
+static int ssl_ui_reader(UI *ui, UI_STRING *uis)
+{
+ const char *password;
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ password = (const char*)UI_get0_user_data(ui);
+ if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
+ UI_set_result(ui, uis, password);
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
+}
+
+/*
+ * Suppress interactive request for a default password if available.
+ */
+static int ssl_ui_writer(UI *ui, UI_STRING *uis)
+{
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ if(UI_get0_user_data(ui) &&
+ (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
+}
+#endif
+
+static
+int cert_stuff(struct connectdata *conn,
+ SSL_CTX* ctx,
+ char *cert_file,
+ const char *cert_type,
+ char *key_file,
+ const char *key_type)
+{
+ struct SessionHandle *data = conn->data;
+
+ int file_type = do_file_type(cert_type);
+
+ if(cert_file || (file_type == SSL_FILETYPE_ENGINE)) {
+ SSL *ssl;
+ X509 *x509;
+ int cert_done = 0;
+
+ if(data->set.str[STRING_KEY_PASSWD]) {
+#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
+ /*
+ * If password has been given, we store that in the global
+ * area (*shudder*) for a while:
+ */
+ size_t len = strlen(data->set.str[STRING_KEY_PASSWD]);
+ if(len < sizeof(global_passwd))
+ memcpy(global_passwd, data->set.str[STRING_KEY_PASSWD], len+1);
+ else
+ global_passwd[0] = '\0';
+#else
+ /*
+ * We set the password in the callback userdata
+ */
+ SSL_CTX_set_default_passwd_cb_userdata(ctx,
+ data->set.str[STRING_KEY_PASSWD]);
+#endif
+ /* Set passwd callback: */
+ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
+ }
+
+
+ switch(file_type) {
+ case SSL_FILETYPE_PEM:
+ /* SSL_CTX_use_certificate_chain_file() only works on PEM files */
+ if(SSL_CTX_use_certificate_chain_file(ctx,
+ cert_file) != 1) {
+ failf(data,
+ "could not load PEM client certificate, OpenSSL error %s, "
+ "(no key found, wrong pass phrase, or wrong file format?)",
+ ERR_error_string(ERR_get_error(), NULL) );
+ return 0;
+ }
+ break;
+
+ case SSL_FILETYPE_ASN1:
+ /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
+ we use the case above for PEM so this can only be performed with
+ ASN1 files. */
+ if(SSL_CTX_use_certificate_file(ctx,
+ cert_file,
+ file_type) != 1) {
+ failf(data,
+ "could not load ASN1 client certificate, OpenSSL error %s, "
+ "(no key found, wrong pass phrase, or wrong file format?)",
+ ERR_error_string(ERR_get_error(), NULL) );
+ return 0;
+ }
+ break;
+ case SSL_FILETYPE_ENGINE:
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
+ {
+ if(data->state.engine) {
+ const char *cmd_name = "LOAD_CERT_CTRL";
+ struct {
+ const char *cert_id;
+ X509 *cert;
+ } params;
+
+ params.cert_id = cert_file;
+ params.cert = NULL;
+
+ /* Does the engine supports LOAD_CERT_CTRL ? */
+ if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) {
+ failf(data, "ssl engine does not support loading certificates");
+ return 0;
+ }
+
+ /* Load the certificate from the engine */
+ if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name,
+ 0, &params, NULL, 1)) {
+ failf(data, "ssl engine cannot load client cert with id"
+ " '%s' [%s]", cert_file,
+ ERR_error_string(ERR_get_error(), NULL));
+ return 0;
+ }
+
+ if(!params.cert) {
+ failf(data, "ssl engine didn't initialized the certificate "
+ "properly.");
+ return 0;
+ }
+
+ if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
+ failf(data, "unable to set client certificate");
+ X509_free(params.cert);
+ return 0;
+ }
+ X509_free(params.cert); /* we don't need the handle any more... */
+ }
+ else {
+ failf(data, "crypto engine not set, can't load certificate");
+ return 0;
+ }
+ }
+ break;
+#else
+ failf(data, "file type ENG for certificate not implemented");
+ return 0;
+#endif
+
+ case SSL_FILETYPE_PKCS12:
+ {
+#ifdef HAVE_PKCS12_SUPPORT
+ FILE *f;
+ PKCS12 *p12;
+ EVP_PKEY *pri;
+ STACK_OF(X509) *ca = NULL;
+ int i;
+
+ f = fopen(cert_file, "rb");
+ if(!f) {
+ failf(data, "could not open PKCS12 file '%s'", cert_file);
+ return 0;
+ }
+ p12 = d2i_PKCS12_fp(f, NULL);
+ fclose(f);
+
+ if(!p12) {
+ failf(data, "error reading PKCS12 file '%s'", cert_file);
+ return 0;
+ }
+
+ PKCS12_PBE_add();
+
+ if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
+ &ca)) {
+ failf(data,
+ "could not parse PKCS12 file, check password, OpenSSL error %s",
+ ERR_error_string(ERR_get_error(), NULL) );
+ PKCS12_free(p12);
+ return 0;
+ }
+
+ PKCS12_free(p12);
+
+ if(SSL_CTX_use_certificate(ctx, x509) != 1) {
+ failf(data,
+ "could not load PKCS12 client certificate, OpenSSL error %s",
+ ERR_error_string(ERR_get_error(), NULL) );
+ goto fail;
+ }
+
+ if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
+ failf(data, "unable to use private key from PKCS12 file '%s'",
+ cert_file);
+ goto fail;
+ }
+
+ if(!SSL_CTX_check_private_key (ctx)) {
+ failf(data, "private key from PKCS12 file '%s' "
+ "does not match certificate in same file", cert_file);
+ goto fail;
+ }
+ /* Set Certificate Verification chain */
+ if(ca && sk_X509_num(ca)) {
+ for(i = 0; i < sk_X509_num(ca); i++) {
+ /*
+ * Note that sk_X509_pop() is used below to make sure the cert is
+ * removed from the stack properly before getting passed to
+ * SSL_CTX_add_extra_chain_cert(). Previously we used
+ * sk_X509_value() instead, but then we'd clean it in the subsequent
+ * sk_X509_pop_free() call.
+ */
+ X509 *x = sk_X509_pop(ca);
+ if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
+ failf(data, "cannot add certificate to certificate chain");
+ goto fail;
+ }
+ /* SSL_CTX_add_client_CA() seems to work with either sk_* function,
+ * presumably because it duplicates what we pass to it.
+ */
+ if(!SSL_CTX_add_client_CA(ctx, x)) {
+ failf(data, "cannot add certificate to client CA list");
+ goto fail;
+ }
+ }
+ }
+
+ cert_done = 1;
+ fail:
+ EVP_PKEY_free(pri);
+ X509_free(x509);
+ sk_X509_pop_free(ca, X509_free);
+
+ if(!cert_done)
+ return 0; /* failure! */
+ break;
+#else
+ failf(data, "file type P12 for certificate not supported");
+ return 0;
+#endif
+ }
+ default:
+ failf(data, "not supported file type '%s' for certificate", cert_type);
+ return 0;
+ }
+
+ file_type = do_file_type(key_type);
+
+ switch(file_type) {
+ case SSL_FILETYPE_PEM:
+ if(cert_done)
+ break;
+ if(!key_file)
+ /* cert & key can only be in PEM case in the same file */
+ key_file=cert_file;
+ case SSL_FILETYPE_ASN1:
+ if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
+ failf(data, "unable to set private key file: '%s' type %s",
+ key_file, key_type?key_type:"PEM");
+ return 0;
+ }
+ break;
+ case SSL_FILETYPE_ENGINE:
+#ifdef HAVE_OPENSSL_ENGINE_H
+ { /* XXXX still needs some work */
+ EVP_PKEY *priv_key = NULL;
+ if(data->state.engine) {
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ UI_METHOD *ui_method =
+ UI_create_method((char *)"cURL user interface");
+ if(!ui_method) {
+ failf(data, "unable do create OpenSSL user-interface method");
+ return 0;
+ }
+ UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
+ UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
+ UI_method_set_reader(ui_method, ssl_ui_reader);
+ UI_method_set_writer(ui_method, ssl_ui_writer);
+#endif
+ /* the typecast below was added to please mingw32 */
+ priv_key = (EVP_PKEY *)
+ ENGINE_load_private_key(data->state.engine, key_file,
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ ui_method,
+#endif
+ data->set.str[STRING_KEY_PASSWD]);
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ UI_destroy_method(ui_method);
+#endif
+ if(!priv_key) {
+ failf(data, "failed to load private key from crypto engine");
+ return 0;
+ }
+ if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
+ failf(data, "unable to set private key");
+ EVP_PKEY_free(priv_key);
+ return 0;
+ }
+ EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
+ }
+ else {
+ failf(data, "crypto engine not set, can't load private key");
+ return 0;
+ }
+ }
+ break;
+#else
+ failf(data, "file type ENG for private key not supported");
+ return 0;
+#endif
+ case SSL_FILETYPE_PKCS12:
+ if(!cert_done) {
+ failf(data, "file type P12 for private key not supported");
+ return 0;
+ }
+ break;
+ default:
+ failf(data, "not supported file type for private key");
+ return 0;
+ }
+
+ ssl=SSL_new(ctx);
+ if(!ssl) {
+ failf(data, "unable to create an SSL structure");
+ return 0;
+ }
+
+ x509=SSL_get_certificate(ssl);
+
+ /* This version was provided by Evan Jordan and is supposed to not
+ leak memory as the previous version: */
+ if(x509) {
+ EVP_PKEY *pktmp = X509_get_pubkey(x509);
+ EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl));
+ EVP_PKEY_free(pktmp);
+ }
+
+ SSL_free(ssl);
+
+ /* If we are using DSA, we can copy the parameters from
+ * the private key */
+
+
+ /* Now we know that a key and cert have been set against
+ * the SSL context */
+ if(!SSL_CTX_check_private_key(ctx)) {
+ failf(data, "Private key does not match the certificate public key");
+ return 0;
+ }
+#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
+ /* erase it now */
+ memset(global_passwd, 0, sizeof(global_passwd));
+#endif
+ }
+ return 1;
+}
+
+/* returns non-zero on failure */
+static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
+{
+#if 0
+ return X509_NAME_oneline(a, buf, size);
+#else
+ BIO *bio_out = BIO_new(BIO_s_mem());
+ BUF_MEM *biomem;
+ int rc;
+
+ if(!bio_out)
+ return 1; /* alloc failed! */
+
+ rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC);
+ BIO_get_mem_ptr(bio_out, &biomem);
+
+ if((size_t)biomem->length < size)
+ size = biomem->length;
+ else
+ size--; /* don't overwrite the buffer end */
+
+ memcpy(buf, biomem->data, size);
+ buf[size]=0;
+
+ BIO_free(bio_out);
+
+ return !rc;
+#endif
+}
+
+static
+int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+ X509 *err_cert;
+ char buf[256];
+
+ err_cert=X509_STORE_CTX_get_current_cert(ctx);
+ (void)x509_name_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+ return ok;
+}
+
+/* Return error string for last OpenSSL error
+ */
+static char *SSL_strerror(unsigned long error, char *buf, size_t size)
+{
+#ifdef HAVE_ERR_ERROR_STRING_N
+ /* OpenSSL 0.9.6 and later has a function named
+ ERRO_error_string_n() that takes the size of the buffer as a
+ third argument */
+ ERR_error_string_n(error, buf, size);
+#else
+ (void) size;
+ ERR_error_string(error, buf);
+#endif
+ return buf;
+}
+
+/**
+ * Global SSL init
+ *
+ * @retval 0 error initializing SSL
+ * @retval 1 SSL initialized successfully
+ */
+CURL_STATIC int Curl_ossl_init(void)
+{
+#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
+ ENGINE_load_builtin_engines();
+#endif
+
+ /* Lets get nice error messages */
+ SSL_load_error_strings();
+
+ /* Init the global ciphers and digests */
+ if(!SSLeay_add_ssl_algorithms())
+ return 0;
+
+ OpenSSL_add_all_algorithms();
+
+
+ /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately
+ that function makes an exit() call on wrongly formatted config files
+ which makes it hard to use in some situations. OPENSSL_config() itself
+ calls CONF_modules_load_file() and we use that instead and we ignore
+ its return code! */
+
+ /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and
+ 0.9.8e */
+#ifndef CONF_MFLAGS_DEFAULT_SECTION
+#define CONF_MFLAGS_DEFAULT_SECTION 0x0
+#endif
+
+ CONF_modules_load_file(NULL, NULL,
+ CONF_MFLAGS_DEFAULT_SECTION|
+ CONF_MFLAGS_IGNORE_MISSING_FILE);
+
+ return 1;
+}
+
+/* Global cleanup */
+CURL_STATIC void Curl_ossl_cleanup(void)
+{
+ /* Free ciphers and digests lists */
+ EVP_cleanup();
+
+#ifdef HAVE_ENGINE_CLEANUP
+ /* Free engine list */
+ ENGINE_cleanup();
+#endif
+
+#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
+ /* Free OpenSSL ex_data table */
+ CRYPTO_cleanup_all_ex_data();
+#endif
+
+ /* Free OpenSSL error strings */
+ ERR_free_strings();
+
+ /* Free thread local error state, destroying hash upon zero refcount */
+#ifdef HAVE_ERR_REMOVE_THREAD_STATE
+ ERR_remove_thread_state(NULL);
+#else
+ ERR_remove_state(0);
+#endif
+}
+
+/*
+ * This function uses SSL_peek to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+CURL_STATIC int Curl_ossl_check_cxn(struct connectdata *conn)
+{
+ int rc;
+ char buf;
+
+ rc = SSL_peek(conn->ssl[FIRSTSOCKET].handle, (void*)&buf, 1);
+ if(rc > 0)
+ return 1; /* connection still in place */
+
+ if(rc == 0)
+ return 0; /* connection has been closed */
+
+ return -1; /* connection status unknown */
+}
+
+/* Selects an OpenSSL crypto engine
+ */
+CURL_STATIC CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine)
+{
+#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+ ENGINE *e;
+
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+ e = ENGINE_by_id(engine);
+#else
+ /* avoid memory leak */
+ for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
+ const char *e_id = ENGINE_get_id(e);
+ if(!strcmp(engine, e_id))
+ break;
+ }
+#endif
+
+ if(!e) {
+ failf(data, "SSL Engine '%s' not found", engine);
+ return CURLE_SSL_ENGINE_NOTFOUND;
+ }
+
+ if(data->state.engine) {
+ ENGINE_finish(data->state.engine);
+ ENGINE_free(data->state.engine);
+ data->state.engine = NULL;
+ }
+ if(!ENGINE_init(e)) {
+ char buf[256];
+
+ ENGINE_free(e);
+ failf(data, "Failed to initialise SSL Engine '%s':\n%s",
+ engine, SSL_strerror(ERR_get_error(), buf, sizeof(buf)));
+ return CURLE_SSL_ENGINE_INITFAILED;
+ }
+ data->state.engine = e;
+ return CURLE_OK;
+#else
+ (void)engine;
+ failf(data, "SSL Engine not supported");
+ return CURLE_SSL_ENGINE_NOTFOUND;
+#endif
+}
+
+/* Sets engine as default for all SSL operations
+ */
+CURL_STATIC CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data)
+{
+#ifdef HAVE_OPENSSL_ENGINE_H
+ if(data->state.engine) {
+ if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
+ infof(data, "set default crypto engine '%s'\n",
+ ENGINE_get_id(data->state.engine));
+ }
+ else {
+ failf(data, "set default crypto engine '%s' failed",
+ ENGINE_get_id(data->state.engine));
+ return CURLE_SSL_ENGINE_SETFAILED;
+ }
+ }
+#else
+ (void) data;
+#endif
+ return CURLE_OK;
+}
+
+/* Return list of OpenSSL crypto engine names.
+ */
+CURL_STATIC struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
+{
+ struct curl_slist *list = NULL;
+#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+ struct curl_slist *beg;
+ ENGINE *e;
+
+ for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
+ beg = curl_slist_append(list, ENGINE_get_id(e));
+ if(!beg) {
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ list = beg;
+ }
+#endif
+ (void) data;
+ return list;
+}
+
+
+/*
+ * This function is called when an SSL connection is closed.
+ */
+CURL_STATIC void Curl_ossl_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->handle) {
+ (void)SSL_shutdown(connssl->handle);
+ SSL_set_connect_state(connssl->handle);
+
+ SSL_free (connssl->handle);
+ connssl->handle = NULL;
+ }
+ if(connssl->ctx) {
+ SSL_CTX_free (connssl->ctx);
+ connssl->ctx = NULL;
+ }
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+CURL_STATIC int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
+{
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
+ to be at least 120 bytes long. */
+ unsigned long sslerror;
+ ssize_t nread;
+ int buffsize;
+ int err;
+ int done = 0;
+
+ /* This has only been tested on the proftpd server, and the mod_tls code
+ sends a close notify alert without waiting for a close notify alert in
+ response. Thus we wait for a close notify alert from the server, but
+ we do not send one. Let's hope other servers do the same... */
+
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ (void)SSL_shutdown(connssl->handle);
+
+ if(connssl->handle) {
+ buffsize = (int)sizeof(buf);
+ while(!done) {
+ int what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ if(what > 0) {
+ ERR_clear_error();
+
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server */
+ nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf,
+ buffsize);
+ err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread);
+
+ switch(err) {
+ case SSL_ERROR_NONE: /* this is not an error */
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ /* This is the expected response. There was no data but only
+ the close notify alert */
+ done = 1;
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* there's data pending, re-invoke SSL_read() */
+ infof(data, "SSL_ERROR_WANT_READ\n");
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ /* SSL wants a write. Really odd. Let's bail out. */
+ infof(data, "SSL_ERROR_WANT_WRITE\n");
+ done = 1;
+ break;
+ default:
+ /* openssl/ssl.h says "look at error stack/return value/errno" */
+ sslerror = ERR_get_error();
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(sslerror, buf),
+ SOCKERRNO);
+ done = 1;
+ break;
+ }
+ }
+ else if(0 == what) {
+ /* timeout */
+ failf(data, "SSL shutdown timeout");
+ done = 1;
+ }
+ else {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ retval = -1;
+ done = 1;
+ }
+ } /* while()-loop for the select() */
+
+ if(data->set.verbose) {
+#ifdef HAVE_SSL_GET_SHUTDOWN
+ switch(SSL_get_shutdown(connssl->handle)) {
+ case SSL_SENT_SHUTDOWN:
+ infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
+ break;
+ case SSL_RECEIVED_SHUTDOWN:
+ infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n");
+ break;
+ case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN:
+ infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|"
+ "SSL_RECEIVED__SHUTDOWN\n");
+ break;
+ }
+#endif
+ }
+
+ SSL_free (connssl->handle);
+ connssl->handle = NULL;
+ }
+ return retval;
+}
+
+CURL_STATIC void Curl_ossl_session_free(void *ptr)
+{
+ /* free the ID */
+ SSL_SESSION_free(ptr);
+}
+
+/*
+ * This function is called when the 'data' struct is going away. Close
+ * down everything and free all resources!
+ */
+CURL_STATIC void Curl_ossl_close_all(struct SessionHandle *data)
+{
+#ifdef HAVE_OPENSSL_ENGINE_H
+ if(data->state.engine) {
+ ENGINE_finish(data->state.engine);
+ ENGINE_free(data->state.engine);
+ data->state.engine = NULL;
+ }
+#else
+ (void)data;
+#endif
+}
+
+static int asn1_output(const ASN1_UTCTIME *tm,
+ char *buf,
+ size_t sizeofbuf)
+{
+ const char *asn1_string;
+ int gmt=FALSE;
+ int i;
+ int year=0, month=0, day=0, hour=0, minute=0, second=0;
+
+ i=tm->length;
+ asn1_string=(const char *)tm->data;
+
+ if(i < 10)
+ return 1;
+ if(asn1_string[i-1] == 'Z')
+ gmt=TRUE;
+ for(i=0; i<10; i++)
+ if((asn1_string[i] > '9') || (asn1_string[i] < '0'))
+ return 2;
+
+ year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0');
+ if(year < 50)
+ year+=100;
+
+ month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0');
+ if((month > 12) || (month < 1))
+ return 3;
+
+ day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0');
+ hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0');
+ minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0');
+
+ if((asn1_string[10] >= '0') && (asn1_string[10] <= '9') &&
+ (asn1_string[11] >= '0') && (asn1_string[11] <= '9'))
+ second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0');
+
+ snprintf(buf, sizeofbuf,
+ "%04d-%02d-%02d %02d:%02d:%02d %s",
+ year+1900, month, day, hour, minute, second, (gmt?"GMT":""));
+
+ return 0;
+}
+
+/* ====================================================== */
+
+
+/* Quote from RFC2818 section 3.1 "Server Identity"
+
+ If a subjectAltName extension of type dNSName is present, that MUST
+ be used as the identity. Otherwise, the (most specific) Common Name
+ field in the Subject field of the certificate MUST be used. Although
+ the use of the Common Name is existing practice, it is deprecated and
+ Certification Authorities are encouraged to use the dNSName instead.
+
+ Matching is performed using the matching rules specified by
+ [RFC2459]. If more than one identity of a given type is present in
+ the certificate (e.g., more than one dNSName name, a match in any one
+ of the set is considered acceptable.) Names may contain the wildcard
+ character * which is considered to match any single domain name
+ component or component fragment. E.g., *.a.com matches foo.a.com but
+ not bar.foo.a.com. f*.com matches foo.com but not bar.com.
+
+ In some cases, the URI is specified as an IP address rather than a
+ hostname. In this case, the iPAddress subjectAltName must be present
+ in the certificate and must exactly match the IP in the URI.
+
+*/
+static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
+{
+ int matched = -1; /* -1 is no alternative match yet, 1 means match and 0
+ means mismatch */
+ int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
+ size_t addrlen = 0;
+ struct SessionHandle *data = conn->data;
+ STACK_OF(GENERAL_NAME) *altnames;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ CURLcode result = CURLE_OK;
+
+#ifdef ENABLE_IPV6
+ if(conn->bits.ipv6_ip &&
+ Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
+ target = GEN_IPADD;
+ addrlen = sizeof(struct in6_addr);
+ }
+ else
+#endif
+ if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
+ target = GEN_IPADD;
+ addrlen = sizeof(struct in_addr);
+ }
+
+ /* get a "list" of alternative names */
+ altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
+
+ if(altnames) {
+ int numalts;
+ int i;
+
+ /* get amount of alternatives, RFC2459 claims there MUST be at least
+ one, but we don't depend on it... */
+ numalts = sk_GENERAL_NAME_num(altnames);
+
+ /* loop through all alternatives while none has matched */
+ for(i=0; (i<numalts) && (matched != 1); i++) {
+ /* get a handle to alternative name number i */
+ const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
+
+ /* only check alternatives of the same type the target is */
+ if(check->type == target) {
+ /* get data and length */
+ const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
+
+ switch(target) {
+ case GEN_DNS: /* name/pattern comparison */
+ /* The OpenSSL man page explicitly says: "In general it cannot be
+ assumed that the data returned by ASN1_STRING_data() is null
+ terminated or does not contain embedded nulls." But also that
+ "The actual format of the data will depend on the actual string
+ type itself: for example for and IA5String the data will be ASCII"
+
+ Gisle researched the OpenSSL sources:
+ "I checked the 0.9.6 and 0.9.8 sources before my patch and
+ it always 0-terminates an IA5String."
+ */
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ Curl_cert_hostcheck(altptr, conn->host.name))
+ matched = 1;
+ else
+ matched = 0;
+ break;
+
+ case GEN_IPADD: /* IP address comparison */
+ /* compare alternative IP address if the data chunk is the same size
+ our server IP address is */
+ if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
+ matched = 1;
+ else
+ matched = 0;
+ break;
+ }
+ }
+ }
+ GENERAL_NAMES_free(altnames);
+ }
+
+ if(matched == 1)
+ /* an alternative name matched the server hostname */
+ infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
+ else if(matched == 0) {
+ /* an alternative name field existed, but didn't match and then
+ we MUST fail */
+ infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
+ failf(data, "SSL: no alternative certificate subject name matches "
+ "target host name '%s'", conn->host.dispname);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else {
+ /* we have to look to the last occurrence of a commonName in the
+ distinguished one to get the most significant one. */
+ int j, i=-1;
+
+/* The following is done because of a bug in 0.9.6b */
+
+ unsigned char *nulstr = (unsigned char *)"";
+ unsigned char *peer_CN = nulstr;
+
+ X509_NAME *name = X509_get_subject_name(server_cert);
+ if(name)
+ while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0)
+ i=j;
+
+ /* we have the name entry and we will now convert this to a string
+ that we can use for comparison. Doing this we support BMPstring,
+ UTF8 etc. */
+
+ if(i>=0) {
+ ASN1_STRING *tmp =
+ X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
+
+ /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
+ is already UTF-8 encoded. We check for this case and copy the raw
+ string manually to avoid the problem. This code can be made
+ conditional in the future when OpenSSL has been fixed. Work-around
+ brought by Alexis S. L. Carvalho. */
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
+ }
+ }
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && (curlx_uztosi(strlen((char *)peer_CN)) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ }
+
+ if(peer_CN == nulstr)
+ peer_CN = NULL;
+ else {
+ /* convert peer_CN from UTF8 */
+ CURLcode rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN));
+ /* Curl_convert_from_utf8 calls failf if unsuccessful */
+ if(rc) {
+ OPENSSL_free(peer_CN);
+ return rc;
+ }
+ }
+
+ if(result)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
+ failf(data,
+ "SSL: unable to obtain common name from peer certificate");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+ failf(data, "SSL: certificate subject name '%s' does not match "
+ "target host name '%s'", peer_CN, conn->host.dispname);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else {
+ infof(data, "\t common name: %s (matched)\n", peer_CN);
+ }
+ if(peer_CN)
+ OPENSSL_free(peer_CN);
+ }
+
+ return result;
+}
+
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+static CURLcode verifystatus(struct connectdata *conn,
+ struct ssl_connect_data *connssl)
+{
+ int i, ocsp_status;
+ const unsigned char *p;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ OCSP_RESPONSE *rsp = NULL;
+ OCSP_BASICRESP *br = NULL;
+ X509_STORE *st = NULL;
+ STACK_OF(X509) *ch = NULL;
+
+ long len = SSL_get_tlsext_status_ocsp_resp(connssl->handle, &p);
+
+ if(!p) {
+ failf(data, "No OCSP response received");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+
+ rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
+ if(!rsp) {
+ failf(data, "Invalid OCSP response");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+
+ ocsp_status = OCSP_response_status(rsp);
+ if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ failf(data, "Invalid OCSP response status: %s (%d)",
+ OCSP_response_status_str(ocsp_status), ocsp_status);
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+
+ br = OCSP_response_get1_basic(rsp);
+ if(!br) {
+ failf(data, "Invalid OCSP response");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+
+ ch = SSL_get_peer_cert_chain(connssl->handle);
+ st = SSL_CTX_get_cert_store(connssl->ctx);
+
+#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
+ defined(LIBRESSL_VERSION_NUMBER))
+ /* The authorized responder cert in the OCSP response MUST be signed by the
+ peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert,
+ no problem, but if it's an intermediate cert OpenSSL has a bug where it
+ expects this issuer to be present in the chain embedded in the OCSP
+ response. So we add it if necessary. */
+
+ /* First make sure the peer cert chain includes both a peer and an issuer,
+ and the OCSP response contains a responder cert. */
+ if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) {
+ X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1);
+
+ /* Find issuer of responder cert and add it to the OCSP response chain */
+ for(i = 0; i < sk_X509_num(ch); i++) {
+ X509 *issuer = sk_X509_value(ch, i);
+ if(X509_check_issued(issuer, responder) == X509_V_OK) {
+ if(!OCSP_basic_add1_cert(br, issuer)) {
+ failf(data, "Could not add issuer cert to OCSP response");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+ }
+ }
+ }
+#endif
+
+ if(OCSP_basic_verify(br, ch, st, 0) <= 0) {
+ failf(data, "OCSP response verification failed");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+
+ for(i = 0; i < OCSP_resp_count(br); i++) {
+ int cert_status, crl_reason;
+ OCSP_SINGLERESP *single = NULL;
+
+ ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+
+ if(!(single = OCSP_resp_get0(br, i)))
+ continue;
+
+ cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
+ &thisupd, &nextupd);
+
+ if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
+ failf(data, "OCSP response has expired");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+
+ infof(data, "SSL certificate status: %s (%d)\n",
+ OCSP_cert_status_str(cert_status), cert_status);
+
+ switch(cert_status) {
+ case V_OCSP_CERTSTATUS_GOOD:
+ break;
+
+ case V_OCSP_CERTSTATUS_REVOKED:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+
+ failf(data, "SSL certificate revocation reason: %s (%d)",
+ OCSP_crl_reason_str(crl_reason), crl_reason);
+ goto end;
+
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
+ }
+
+end:
+ if(br) OCSP_BASICRESP_free(br);
+ OCSP_RESPONSE_free(rsp);
+
+ return result;
+}
+#endif
+
+#endif /* USE_OPENSSL */
+
+/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions
+ and thus this cannot be done there. */
+#ifdef SSL_CTRL_SET_MSG_CALLBACK
+
+static const char *ssl_msg_type(int ssl_ver, int msg)
+{
+#ifdef SSL2_VERSION_MAJOR
+ if(ssl_ver == SSL2_VERSION_MAJOR) {
+ switch (msg) {
+ case SSL2_MT_ERROR:
+ return "Error";
+ case SSL2_MT_CLIENT_HELLO:
+ return "Client hello";
+ case SSL2_MT_CLIENT_MASTER_KEY:
+ return "Client key";
+ case SSL2_MT_CLIENT_FINISHED:
+ return "Client finished";
+ case SSL2_MT_SERVER_HELLO:
+ return "Server hello";
+ case SSL2_MT_SERVER_VERIFY:
+ return "Server verify";
+ case SSL2_MT_SERVER_FINISHED:
+ return "Server finished";
+ case SSL2_MT_REQUEST_CERTIFICATE:
+ return "Request CERT";
+ case SSL2_MT_CLIENT_CERTIFICATE:
+ return "Client CERT";
+ }
+ }
+ else
+#endif
+ if(ssl_ver == SSL3_VERSION_MAJOR) {
+ switch (msg) {
+ case SSL3_MT_HELLO_REQUEST:
+ return "Hello request";
+ case SSL3_MT_CLIENT_HELLO:
+ return "Client hello";
+ case SSL3_MT_SERVER_HELLO:
+ return "Server hello";
+ case SSL3_MT_CERTIFICATE:
+ return "CERT";
+ case SSL3_MT_SERVER_KEY_EXCHANGE:
+ return "Server key exchange";
+ case SSL3_MT_CLIENT_KEY_EXCHANGE:
+ return "Client key exchange";
+ case SSL3_MT_CERTIFICATE_REQUEST:
+ return "Request CERT";
+ case SSL3_MT_SERVER_DONE:
+ return "Server finished";
+ case SSL3_MT_CERTIFICATE_VERIFY:
+ return "CERT verify";
+ case SSL3_MT_FINISHED:
+ return "Finished";
+ }
+ }
+ return "Unknown";
+}
+
+static const char *tls_rt_type(int type)
+{
+ return (
+ type == SSL3_RT_CHANGE_CIPHER_SPEC ? "TLS change cipher, " :
+ type == SSL3_RT_ALERT ? "TLS alert, " :
+ type == SSL3_RT_HANDSHAKE ? "TLS handshake, " :
+ type == SSL3_RT_APPLICATION_DATA ? "TLS app data, " :
+ "TLS Unknown, ");
+}
+
+
+/*
+ * Our callback from the SSL/TLS layers.
+ */
+static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
+ const void *buf, size_t len, const SSL *ssl,
+ struct connectdata *conn)
+{
+ struct SessionHandle *data;
+ const char *msg_name, *tls_rt_name;
+ char ssl_buf[1024];
+ char unknown[32];
+ int msg_type, txt_len;
+ const char *verstr;
+
+ if(!conn || !conn->data || !conn->data->set.fdebug ||
+ (direction != 0 && direction != 1))
+ return;
+
+ data = conn->data;
+
+ switch(ssl_ver) {
+#ifdef SSL2_VERSION_MAJOR /* removed in recent versions */
+ case SSL2_VERSION_MAJOR:
+ verstr = "SSLv2";
+ break;
+#endif
+#ifdef SSL3_VERSION
+ case SSL3_VERSION:
+ verstr = "SSLv3";
+ break;
+#endif
+ case TLS1_VERSION:
+ verstr = "TLSv1.0";
+ break;
+#ifdef TLS1_1_VERSION
+ case TLS1_1_VERSION:
+ verstr = "TLSv1.1";
+ break;
+#endif
+#ifdef TLS1_2_VERSION
+ case TLS1_2_VERSION:
+ verstr = "TLSv1.2";
+ break;
+#endif
+ default:
+ snprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
+ verstr = unknown;
+ break;
+ }
+
+ ssl_ver >>= 8; /* check the upper 8 bits only below */
+
+ /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL
+ * always pass-up content-type as 0. But the interesting message-type
+ * is at 'buf[0]'.
+ */
+ if(ssl_ver == SSL3_VERSION_MAJOR && content_type != 0)
+ tls_rt_name = tls_rt_type(content_type);
+ else
+ tls_rt_name = "";
+
+ msg_type = *(char*)buf;
+ msg_name = ssl_msg_type(ssl_ver, msg_type);
+
+ txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s, %s%s (%d):\n",
+ verstr, tls_rt_name, msg_name, msg_type);
+ Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+
+ Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
+ CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
+ (void) ssl;
+}
+#endif
+
+#ifdef USE_OPENSSL
+/* ====================================================== */
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+# define use_sni(x) sni = (x)
+#else
+# define use_sni(x) Curl_nop_stmt
+#endif
+
+/* Check for OpenSSL 1.0.2 which has ALPN support. */
+#undef HAS_ALPN
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
+ && !defined(OPENSSL_NO_TLSEXT)
+# define HAS_ALPN 1
+#endif
+
+/* Check for OpenSSL 1.0.1 which has NPN support. */
+#undef HAS_NPN
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L \
+ && !defined(OPENSSL_NO_TLSEXT) \
+ && !defined(OPENSSL_NO_NEXTPROTONEG)
+# define HAS_NPN 1
+#endif
+
+#ifdef HAS_NPN
+
+/*
+ * in is a list of lenght prefixed strings. this function has to select
+ * the protocol we want to use from the list and write its string into out.
+ */
+
+static int
+select_next_protocol(unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen,
+ const char *key, unsigned int keylen)
+{
+ unsigned int i;
+ for(i = 0; i + keylen <= inlen; i += in[i] + 1) {
+ if(memcmp(&in[i + 1], key, keylen) == 0) {
+ *out = (unsigned char *) &in[i + 1];
+ *outlen = in[i];
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int
+select_next_proto_cb(SSL *ssl,
+ unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen,
+ void *arg)
+{
+ struct connectdata *conn = (struct connectdata*) arg;
+
+ (void)ssl;
+
+#ifdef USE_NGHTTP2
+ if(conn->data->set.httpversion == CURL_HTTP_VERSION_2_0 &&
+ !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN)) {
+ infof(conn->data, "NPN, negotiated HTTP2 (%s)\n",
+ NGHTTP2_PROTO_VERSION_ID);
+ conn->negnpn = CURL_HTTP_VERSION_2_0;
+ return SSL_TLSEXT_ERR_OK;
+ }
+#endif
+
+ if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
+ ALPN_HTTP_1_1_LENGTH)) {
+ infof(conn->data, "NPN, negotiated HTTP1.1\n");
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ infof(conn->data, "NPN, no overlap, use HTTP1.1\n");
+ *out = (unsigned char *)ALPN_HTTP_1_1;
+ *outlen = ALPN_HTTP_1_1_LENGTH;
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+
+ return SSL_TLSEXT_ERR_OK;
+}
+#endif /* HAS_NPN */
+
+static const char *
+get_ssl_version_txt(SSL *ssl)
+{
+ if(!ssl)
+ return "";
+
+ switch(SSL_version(ssl)) {
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ case TLS1_2_VERSION:
+ return "TLSv1.2";
+ case TLS1_1_VERSION:
+ return "TLSv1.1";
+#endif
+ case TLS1_VERSION:
+ return "TLSv1.0";
+ case SSL3_VERSION:
+ return "SSLv3";
+ case SSL2_VERSION:
+ return "SSLv2";
+ }
+ return "unknown";
+}
+
+static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
+{
+ CURLcode result = CURLE_OK;
+ char *ciphers;
+ struct SessionHandle *data = conn->data;
+ SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
+ void *ssl_sessionid = NULL;
+ X509_LOOKUP *lookup = NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ long ctx_options;
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ bool sni;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+#endif
+
+ DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
+
+ /* Make funny stuff to get random input */
+ Curl_ossl_seed(data);
+
+ data->set.ssl.certverifyresult = !X509_V_OK;
+
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ case CURL_SSLVERSION_TLSv1_2:
+ /* it will be handled later with the context options */
+ req_method = SSLv23_client_method();
+ use_sni(TRUE);
+ break;
+ case CURL_SSLVERSION_SSLv2:
+#ifdef OPENSSL_NO_SSL2
+ failf(data, "OpenSSL was built without SSLv2 support");
+ return CURLE_NOT_BUILT_IN;
+#else
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+ return CURLE_SSL_CONNECT_ERROR;
+#endif
+ req_method = SSLv2_client_method();
+ use_sni(FALSE);
+ break;
+#endif
+ case CURL_SSLVERSION_SSLv3:
+#ifdef OPENSSL_NO_SSL3_METHOD
+ failf(data, "OpenSSL was built without SSLv3 support");
+ return CURLE_NOT_BUILT_IN;
+#else
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+ return CURLE_SSL_CONNECT_ERROR;
+#endif
+ req_method = SSLv3_client_method();
+ use_sni(FALSE);
+ break;
+#endif
+ }
+
+ if(connssl->ctx)
+ SSL_CTX_free(connssl->ctx);
+ connssl->ctx = SSL_CTX_new(req_method);
+
+ if(!connssl->ctx) {
+ failf(data, "SSL: couldn't create a context: %s",
+ ERR_error_string(ERR_peek_error(), NULL));
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifdef SSL_MODE_RELEASE_BUFFERS
+ SSL_CTX_set_mode(connssl->ctx, SSL_MODE_RELEASE_BUFFERS);
+#endif
+
+#ifdef SSL_CTRL_SET_MSG_CALLBACK
+ if(data->set.fdebug && data->set.verbose) {
+ /* the SSL trace callback is only used for verbose logging so we only
+ inform about failures of setting it */
+ if(!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK,
+ (void (*)(void))ssl_tls_trace)) {
+ infof(data, "SSL: couldn't set callback!\n");
+ }
+ else if(!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0,
+ conn)) {
+ infof(data, "SSL: couldn't set callback argument!\n");
+ }
+ }
+#endif
+
+ /* OpenSSL contains code to work-around lots of bugs and flaws in various
+ SSL-implementations. SSL_CTX_set_options() is used to enabled those
+ work-arounds. The man page for this option states that SSL_OP_ALL enables
+ all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
+ enable the bug workaround options if compatibility with somewhat broken
+ implementations is desired."
+
+ The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to
+ disable "rfc4507bis session ticket support". rfc4507bis was later turned
+ into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077
+
+ The enabled extension concerns the session management. I wonder how often
+ libcurl stops a connection and then resumes a TLS session. also, sending
+ the session data is some overhead. .I suggest that you just use your
+ proposed patch (which explicitly disables TICKET).
+
+ If someone writes an application with libcurl and openssl who wants to
+ enable the feature, one can do this in the SSL callback.
+
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper
+ interoperability with web server Netscape Enterprise Server 2.0.1 which
+ was released back in 1996.
+
+ Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has
+ become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate
+ CVE-2010-4180 when using previous OpenSSL versions we no longer enable
+ this option regardless of OpenSSL version and SSL_OP_ALL definition.
+
+ OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability
+ (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to
+ SSL_OP_ALL that _disables_ that work-around despite the fact that
+ SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to
+ keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit
+ must not be set.
+ */
+
+ ctx_options = SSL_OP_ALL;
+
+#ifdef SSL_OP_NO_TICKET
+ ctx_options |= SSL_OP_NO_TICKET;
+#endif
+
+#ifdef SSL_OP_NO_COMPRESSION
+ ctx_options |= SSL_OP_NO_COMPRESSION;
+#endif
+
+#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
+ /* mitigate CVE-2010-4180 */
+ ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
+#endif
+
+#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
+ /* unless the user explicitly ask to allow the protocol vulnerability we
+ use the work-around */
+ if(!conn->data->set.ssl_enable_beast)
+ ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+#endif
+
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv3:
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ infof(data, "Set version TLSv1.x for SRP authorisation\n");
+ }
+#endif
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_TLSv1;
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ break;
+
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+ break;
+
+ case CURL_SSLVERSION_TLSv1_0:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ break;
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ case CURL_SSLVERSION_TLSv1_1:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+ break;
+
+ case CURL_SSLVERSION_TLSv1_2:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ break;
+#endif
+
+#ifndef OPENSSL_NO_SSL2
+ case CURL_SSLVERSION_SSLv2:
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ break;
+#endif
+
+ default:
+ failf(data, "Unsupported SSL protocol version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ SSL_CTX_set_options(connssl->ctx, ctx_options);
+
+#ifdef HAS_NPN
+ if(data->set.ssl_enable_npn)
+ SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn);
+#endif
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ int cur = 0;
+ unsigned char protocols[128];
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+ protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
+
+ memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN);
+ cur += NGHTTP2_PROTO_VERSION_ID_LEN;
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
+ memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
+ cur += ALPN_HTTP_1_1_LENGTH;
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ /* expects length prefixed preference ordered list of protocols in wire
+ * format
+ */
+ SSL_CTX_set_alpn_protos(connssl->ctx, protocols, cur);
+ }
+#endif
+
+ if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
+ if(!cert_stuff(conn,
+ connssl->ctx,
+ data->set.str[STRING_CERT],
+ data->set.str[STRING_CERT_TYPE],
+ data->set.str[STRING_KEY],
+ data->set.str[STRING_KEY_TYPE])) {
+ /* failf() is already done in cert_stuff() */
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
+ if(!ciphers)
+ ciphers = (char *)DEFAULT_CIPHER_SELECTION;
+ if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
+ failf(data, "failed setting cipher list: %s", ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "Cipher selection: %s\n", ciphers);
+
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+
+ if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) {
+ failf(data, "Unable to set SRP user name");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) {
+ failf(data, "failed setting SRP password");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ if(!data->set.str[STRING_SSL_CIPHER_LIST]) {
+ infof(data, "Setting cipher list SRP\n");
+
+ if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
+ failf(data, "failed setting SRP cipher list");
+ return CURLE_SSL_CIPHER;
+ }
+ }
+ }
+#endif
+ if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
+ /* tell SSL where to find CA certificates that are used to verify
+ the servers certificate. */
+ if(!SSL_CTX_load_verify_locations(connssl->ctx,
+ data->set.str[STRING_SSL_CAFILE],
+ data->set.str[STRING_SSL_CAPATH])) {
+ if(data->set.ssl.verifypeer) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:\n"
+ " CAfile: %s\n CApath: %s",
+ data->set.str[STRING_SSL_CAFILE]?
+ data->set.str[STRING_SSL_CAFILE]: "none",
+ data->set.str[STRING_SSL_CAPATH]?
+ data->set.str[STRING_SSL_CAPATH] : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Just continue with a warning if no strict certificate verification
+ is required. */
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway:\n");
+ }
+ }
+ else {
+ /* Everything is fine. */
+ infof(data, "successfully set certificate verify locations:\n");
+ }
+ infof(data,
+ " CAfile: %s\n"
+ " CApath: %s\n",
+ data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+ "none",
+ data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+ "none");
+ }
+
+ if(data->set.str[STRING_SSL_CRLFILE]) {
+ /* tell SSL where to find CRL file that is used to check certificate
+ * revocation */
+ lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
+ X509_LOOKUP_file());
+ if(!lookup ||
+ (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE],
+ X509_FILETYPE_PEM)) ) {
+ failf(data, "error loading CRL file: %s",
+ data->set.str[STRING_SSL_CRLFILE]);
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ else {
+ /* Everything is fine. */
+ infof(data, "successfully load CRL file:\n");
+ X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+ }
+ infof(data,
+ " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
+ data->set.str[STRING_SSL_CRLFILE]: "none");
+ }
+
+ /* SSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+ SSL_CTX_set_verify(connssl->ctx,
+ data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
+ cert_verify_callback);
+
+ /* give application a chance to interfere with SSL set up. */
+ if(data->set.ssl.fsslctx) {
+ result = (*data->set.ssl.fsslctx)(data, connssl->ctx,
+ data->set.ssl.fsslctxp);
+ if(result) {
+ failf(data, "error signaled by ssl ctx callback");
+ return result;
+ }
+ }
+
+ /* Lets make an SSL structure */
+ if(connssl->handle)
+ SSL_free(connssl->handle);
+ connssl->handle = SSL_new(connssl->ctx);
+ if(!connssl->handle) {
+ failf(data, "SSL: couldn't create a context (handle)!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+ if(data->set.ssl.verifystatus)
+ SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
+#endif
+
+ SSL_set_connect_state(connssl->handle);
+
+ connssl->server_cert = 0x0;
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+#ifdef ENABLE_IPV6
+ (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+#endif
+ sni &&
+ !SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
+ infof(data, "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+#endif
+
+ /* Check if there's a cached ID we can/should use here! */
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
+ failf(data, "SSL: SSL_set_session failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof (data, "SSL re-using session ID\n");
+ }
+
+ /* pass the raw socket into the SSL layers */
+ if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+ failf(data, "SSL: SSL_set_fd failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+
+ return CURLE_OK;
+}
+
+static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ int err;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
+ || ssl_connect_2_reading == connssl->connecting_state
+ || ssl_connect_2_writing == connssl->connecting_state);
+
+ ERR_clear_error();
+
+ err = SSL_connect(connssl->handle);
+
+ /* 1 is fine
+ 0 is "not successful but was shut down controlled"
+ <0 is "handshake was not successful, because a fatal error occurred" */
+ if(1 != err) {
+ int detail = SSL_get_error(connssl->handle, err);
+
+ if(SSL_ERROR_WANT_READ == detail) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+ else if(SSL_ERROR_WANT_WRITE == detail) {
+ connssl->connecting_state = ssl_connect_2_writing;
+ return CURLE_OK;
+ }
+ else {
+ /* untreated error */
+ unsigned long errdetail;
+ char error_buffer[256]; /* OpenSSL documents that this must be at least
+ 256 bytes long. */
+ CURLcode result;
+ const char *cert_problem = NULL;
+ long lerr;
+
+ connssl->connecting_state = ssl_connect_2; /* the connection failed,
+ we're not waiting for
+ anything else. */
+
+ errdetail = ERR_get_error(); /* Gets the earliest error code from the
+ thread's error queue and removes the
+ entry. */
+
+ switch(errdetail) {
+ case 0x1407E086:
+ /* 1407E086:
+ SSL routines:
+ SSL2_SET_CERTIFICATE:
+ certificate verify failed */
+ /* fall-through */
+ case 0x14090086:
+ /* 14090086:
+ SSL routines:
+ SSL3_GET_SERVER_CERTIFICATE:
+ certificate verify failed */
+ result = CURLE_SSL_CACERT;
+
+ lerr = SSL_get_verify_result(connssl->handle);
+ if(lerr != X509_V_OK) {
+ snprintf(error_buffer, sizeof(error_buffer),
+ "SSL certificate problem: %s",
+ X509_verify_cert_error_string(lerr));
+ }
+ else
+ cert_problem = "SSL certificate problem, verify that the CA cert is"
+ " OK.";
+
+ break;
+ default:
+ result = CURLE_SSL_CONNECT_ERROR;
+ SSL_strerror(errdetail, error_buffer, sizeof(error_buffer));
+ break;
+ }
+
+ /* detail is already set to the SSL error above */
+
+ /* If we e.g. use SSLv2 request-method and the server doesn't like us
+ * (RST connection etc.), OpenSSL gives no explanation whatsoever and
+ * the SO_ERROR is also lost.
+ */
+ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+ failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
+ conn->host.name, conn->remote_port);
+ return result;
+ }
+
+ /* Could be a CERT problem */
+ failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer);
+
+ return result;
+ }
+ }
+ else {
+ /* we have been connected fine, we're not waiting for anything else. */
+ connssl->connecting_state = ssl_connect_3;
+
+ /* Informational message */
+ infof(data, "SSL connection using %s / %s\n",
+ get_ssl_version_txt(connssl->handle),
+ SSL_get_cipher(connssl->handle));
+
+#ifdef HAS_ALPN
+ /* Sets data and len to negotiated protocol, len is 0 if no protocol was
+ * negotiated
+ */
+ if(data->set.ssl_enable_alpn) {
+ const unsigned char* neg_protocol;
+ unsigned int len;
+ SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
+ if(len != 0) {
+ infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
+
+#ifdef USE_NGHTTP2
+ if(len == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) {
+ conn->negnpn = CURL_HTTP_VERSION_2_0;
+ }
+ else
+#endif
+ if(len == ALPN_HTTP_1_1_LENGTH &&
+ !memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ }
+ else
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+#endif
+
+ return CURLE_OK;
+ }
+}
+
+static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
+{
+ int i, ilen;
+
+ if((ilen = (int)len) < 0)
+ return 1; /* buffer too big */
+
+ i = i2t_ASN1_OBJECT(buf, ilen, a);
+
+ if(i >= ilen)
+ return 1; /* buffer too small */
+
+ return 0;
+}
+
+static void pubkey_show(struct SessionHandle *data,
+ int num,
+ const char *type,
+ const char *name,
+ unsigned char *raw,
+ int len)
+{
+ size_t left;
+ int i;
+ char namebuf[32];
+ char *buffer;
+
+ left = len*3 + 1;
+ buffer = malloc(left);
+ if(buffer) {
+ char *ptr=buffer;
+ snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+ for(i=0; i< len; i++) {
+ snprintf(ptr, left, "%02x:", raw[i]);
+ ptr += 3;
+ left -= 3;
+ }
+ infof(data, " %s: %s\n", namebuf, buffer);
+ Curl_ssl_push_certinfo(data, num, namebuf, buffer);
+ free(buffer);
+ }
+}
+
+#define print_pubkey_BN(_type, _name, _num) \
+do { \
+ if(pubkey->pkey._type->_name) { \
+ int len = BN_num_bytes(pubkey->pkey._type->_name); \
+ if(len < CERTBUFFERSIZE) { \
+ BN_bn2bin(pubkey->pkey._type->_name, (unsigned char*)bufp); \
+ bufp[len] = 0; \
+ pubkey_show(data, _num, #_type, #_name, (unsigned char*)bufp, len); \
+ } \
+ } \
+} WHILE_FALSE
+
+static int X509V3_ext(struct SessionHandle *data,
+ int certnum,
+ STACK_OF(X509_EXTENSION) *exts)
+{
+ int i;
+ size_t j;
+
+ if(sk_X509_EXTENSION_num(exts) <= 0)
+ /* no extensions, bail out */
+ return 1;
+
+ for(i=0; i<sk_X509_EXTENSION_num(exts); i++) {
+ ASN1_OBJECT *obj;
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ BUF_MEM *biomem;
+ char buf[512];
+ char *ptr=buf;
+ char namebuf[128];
+ BIO *bio_out = BIO_new(BIO_s_mem());
+
+ if(!bio_out)
+ return 1;
+
+ obj = X509_EXTENSION_get_object(ext);
+
+ asn1_object_dump(obj, namebuf, sizeof(namebuf));
+
+ infof(data, "%s: %s\n", namebuf,
+ X509_EXTENSION_get_critical(ext)?"(critical)":"");
+
+ if(!X509V3_EXT_print(bio_out, ext, 0, 0))
+ ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
+
+ BIO_get_mem_ptr(bio_out, &biomem);
+
+ /* biomem->length bytes at biomem->data, this little loop here is only
+ done for the infof() call, we send the "raw" data to the certinfo
+ function */
+ for(j=0; j<(size_t)biomem->length; j++) {
+ const char *sep="";
+ if(biomem->data[j] == '\n') {
+ sep=", ";
+ j++; /* skip the newline */
+ };
+ while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
+ j++;
+ if(j<(size_t)biomem->length)
+ ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
+ biomem->data[j]);
+ }
+ infof(data, " %s\n", buf);
+
+ Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
+
+ BIO_free(bio_out);
+
+ }
+ return 0; /* all is fine */
+}
+
+
+static void X509_signature(struct SessionHandle *data,
+ int numcert,
+ ASN1_STRING *sig)
+{
+ char buf[1024];
+ char *ptr = buf;
+ int i;
+
+ for(i=0; i<sig->length; i++)
+ ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]);
+
+ infof(data, " Signature: %s\n", buf);
+ Curl_ssl_push_certinfo(data, numcert, "Signature", buf);
+}
+
+static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
+{
+ BIO *bio_out = BIO_new(BIO_s_mem());
+ BUF_MEM *biomem;
+
+ /* this outputs the cert in this 64 column wide style with newlines and
+ -----BEGIN CERTIFICATE----- texts and more */
+ PEM_write_bio_X509(bio_out, x);
+
+ BIO_get_mem_ptr(bio_out, &biomem);
+
+ Curl_ssl_push_certinfo_len(data, numcert,
+ "Cert", biomem->data, biomem->length);
+
+ BIO_free(bio_out);
+}
+
+/*
+ * This size was previously 512 which has been reported "too small" without
+ * any specifics, so it was enlarged to allow more data to get shown uncut.
+ * The "perfect" size is yet to figure out.
+ */
+#define CERTBUFFERSIZE 8192
+
+static CURLcode get_cert_chain(struct connectdata *conn,
+ struct ssl_connect_data *connssl)
+
+{
+ CURLcode result;
+ STACK_OF(X509) *sk;
+ int i;
+ char *bufp;
+ struct SessionHandle *data = conn->data;
+ int numcerts;
+
+ bufp = malloc(CERTBUFFERSIZE);
+ if(!bufp)
+ return CURLE_OUT_OF_MEMORY;
+
+ sk = SSL_get_peer_cert_chain(connssl->handle);
+ if(!sk) {
+ free(bufp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ numcerts = sk_X509_num(sk);
+
+ result = Curl_ssl_init_certinfo(data, numcerts);
+ if(result) {
+ free(bufp);
+ return result;
+ }
+
+ infof(data, "--- Certificate chain\n");
+ for(i=0; i<numcerts; i++) {
+ long value;
+ ASN1_INTEGER *num;
+ ASN1_TIME *certdate;
+
+ /* get the certs in "importance order" */
+#if 0
+ X509 *x = sk_X509_value(sk, numcerts - i - 1);
+#else
+ X509 *x = sk_X509_value(sk, i);
+#endif
+
+ X509_CINF *cinf;
+ EVP_PKEY *pubkey=NULL;
+ int j;
+ char *ptr;
+
+ (void)x509_name_oneline(X509_get_subject_name(x), bufp, CERTBUFFERSIZE);
+ infof(data, "%2d Subject: %s\n", i, bufp);
+ Curl_ssl_push_certinfo(data, i, "Subject", bufp);
+
+ (void)x509_name_oneline(X509_get_issuer_name(x), bufp, CERTBUFFERSIZE);
+ infof(data, " Issuer: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Issuer", bufp);
+
+ value = X509_get_version(x);
+ infof(data, " Version: %lu (0x%lx)\n", value+1, value);
+ snprintf(bufp, CERTBUFFERSIZE, "%lx", value);
+ Curl_ssl_push_certinfo(data, i, "Version", bufp); /* hex */
+
+ num=X509_get_serialNumber(x);
+ {
+ int left = CERTBUFFERSIZE;
+
+ ptr = bufp;
+ if(num->type == V_ASN1_NEG_INTEGER) {
+ *ptr++='-';
+ left--;
+ }
+
+ for(j=0; (j<num->length) && (left>=3); j++) {
+ snprintf(ptr, left, "%02x", num->data[j]);
+ ptr += 2;
+ left -= 2;
+ }
+ if(num->length)
+ infof(data, " Serial Number: %s\n", bufp);
+ else
+ bufp[0]=0;
+ }
+ if(bufp[0])
+ Curl_ssl_push_certinfo(data, i, "Serial Number", bufp); /* hex */
+
+ cinf = x->cert_info;
+
+ j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE);
+ if(!j) {
+ infof(data, " Signature Algorithm: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Signature Algorithm", bufp);
+ }
+
+ certdate = X509_get_notBefore(x);
+ asn1_output(certdate, bufp, CERTBUFFERSIZE);
+ infof(data, " Start date: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Start date", bufp);
+
+ certdate = X509_get_notAfter(x);
+ asn1_output(certdate, bufp, CERTBUFFERSIZE);
+ infof(data, " Expire date: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Expire date", bufp);
+
+ j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE);
+ if(!j) {
+ infof(data, " Public Key Algorithm: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Public Key Algorithm", bufp);
+ }
+
+ pubkey = X509_get_pubkey(x);
+ if(!pubkey)
+ infof(data, " Unable to load public key\n");
+ else {
+ switch(pubkey->type) {
+ case EVP_PKEY_RSA:
+ infof(data, " RSA Public Key (%d bits)\n",
+ BN_num_bits(pubkey->pkey.rsa->n));
+ snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n));
+ Curl_ssl_push_certinfo(data, i, "RSA Public Key", bufp);
+
+ print_pubkey_BN(rsa, n, i);
+ print_pubkey_BN(rsa, e, i);
+ print_pubkey_BN(rsa, d, i);
+ print_pubkey_BN(rsa, p, i);
+ print_pubkey_BN(rsa, q, i);
+ print_pubkey_BN(rsa, dmp1, i);
+ print_pubkey_BN(rsa, dmq1, i);
+ print_pubkey_BN(rsa, iqmp, i);
+ break;
+ case EVP_PKEY_DSA:
+ print_pubkey_BN(dsa, p, i);
+ print_pubkey_BN(dsa, q, i);
+ print_pubkey_BN(dsa, g, i);
+ print_pubkey_BN(dsa, priv_key, i);
+ print_pubkey_BN(dsa, pub_key, i);
+ break;
+ case EVP_PKEY_DH:
+ print_pubkey_BN(dh, p, i);
+ print_pubkey_BN(dh, g, i);
+ print_pubkey_BN(dh, priv_key, i);
+ print_pubkey_BN(dh, pub_key, i);
+ break;
+#if 0
+ case EVP_PKEY_EC: /* symbol not present in OpenSSL 0.9.6 */
+ /* left TODO */
+ break;
+#endif
+ }
+ EVP_PKEY_free(pubkey);
+ }
+
+ X509V3_ext(data, i, cinf->extensions);
+
+ X509_signature(data, i, x->signature);
+
+ dumpcert(data, x, i);
+ }
+
+ free(bufp);
+
+ return CURLE_OK;
+}
+
+/*
+ * Heavily modified from:
+ * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
+ */
+static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey)
+{
+ /* Scratch */
+ int len1 = 0, len2 = 0;
+ unsigned char *buff1 = NULL, *temp = NULL;
+
+ /* Result is returned to caller */
+ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+
+ /* if a path wasn't specified, don't pin */
+ if(!pinnedpubkey)
+ return CURLE_OK;
+
+ if(!cert)
+ return result;
+
+ do {
+ /* Begin Gyrations to get the subjectPublicKeyInfo */
+ /* Thanks to Viktor Dukhovni on the OpenSSL mailing list */
+
+ /* https://groups.google.com/group/mailing.openssl.users/browse_thread
+ /thread/d61858dae102c6c7 */
+ len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
+ if(len1 < 1)
+ break; /* failed */
+
+ /* https://www.openssl.org/docs/crypto/buffer.html */
+ buff1 = temp = OPENSSL_malloc(len1);
+ if(!buff1)
+ break; /* failed */
+
+ /* https://www.openssl.org/docs/crypto/d2i_X509.html */
+ len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp);
+
+ /*
+ * These checks are verifying we got back the same values as when we
+ * sized the buffer. It's pretty weak since they should always be the
+ * same. But it gives us something to test.
+ */
+ if((len1 != len2) || !temp || ((temp - buff1) != len1))
+ break; /* failed */
+
+ /* End Gyrations */
+
+ /* The one good exit point */
+ result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1);
+ } while(0);
+
+ /* https://www.openssl.org/docs/crypto/buffer.html */
+ if(buff1)
+ OPENSSL_free(buff1);
+
+ return result;
+}
+
+/*
+ * Get the server cert, verify it and show it etc, only call failf() if the
+ * 'strict' argument is TRUE as otherwise all this is for informational
+ * purposes only!
+ *
+ * We check certificates to authenticate the server; otherwise we risk
+ * man-in-the-middle attack.
+ */
+static CURLcode servercert(struct connectdata *conn,
+ struct ssl_connect_data *connssl,
+ bool strict)
+{
+ CURLcode result = CURLE_OK;
+ int rc;
+ long lerr;
+ ASN1_TIME *certdate;
+ struct SessionHandle *data = conn->data;
+ X509 *issuer;
+ FILE *fp;
+ char *buffer = data->state.buffer;
+ const char *ptr;
+
+ if(data->set.ssl.certinfo)
+ /* we've been asked to gather certificate info! */
+ (void)get_cert_chain(conn, connssl);
+
+ connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
+ if(!connssl->server_cert) {
+ if(strict)
+ failf(data, "SSL: couldn't get peer certificate!");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ infof(data, "Server certificate:\n");
+
+ rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
+ buffer, BUFSIZE);
+ infof(data, "\t subject: %s\n", rc?"[NONE]":buffer);
+
+ certdate = X509_get_notBefore(connssl->server_cert);
+ asn1_output(certdate, buffer, BUFSIZE);
+ infof(data, "\t start date: %s\n", buffer);
+
+ certdate = X509_get_notAfter(connssl->server_cert);
+ asn1_output(certdate, buffer, BUFSIZE);
+ infof(data, "\t expire date: %s\n", buffer);
+
+ if(data->set.ssl.verifyhost) {
+ result = verifyhost(conn, connssl->server_cert);
+ if(result) {
+ X509_free(connssl->server_cert);
+ connssl->server_cert = NULL;
+ return result;
+ }
+ }
+
+ rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert),
+ buffer, BUFSIZE);
+ if(rc) {
+ if(strict)
+ failf(data, "SSL: couldn't get X509-issuer name!");
+ result = CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ infof(data, "\t issuer: %s\n", buffer);
+
+ /* We could do all sorts of certificate verification stuff here before
+ deallocating the certificate. */
+
+ /* e.g. match issuer name with provided issuer certificate */
+ if(data->set.str[STRING_SSL_ISSUERCERT]) {
+ fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], "r");
+ if(!fp) {
+ if(strict)
+ failf(data, "SSL: Unable to open issuer cert (%s)",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(connssl->server_cert);
+ connssl->server_cert = NULL;
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+
+ issuer = PEM_read_X509(fp, NULL, ZERO_NULL, NULL);
+ if(!issuer) {
+ if(strict)
+ failf(data, "SSL: Unable to read issuer cert (%s)",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(connssl->server_cert);
+ X509_free(issuer);
+ fclose(fp);
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+
+ fclose(fp);
+
+ if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
+ if(strict)
+ failf(data, "SSL: Certificate issuer check failed (%s)",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(connssl->server_cert);
+ X509_free(issuer);
+ connssl->server_cert = NULL;
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+
+ infof(data, "\t SSL certificate issuer check ok (%s)\n",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(issuer);
+ }
+
+ lerr = data->set.ssl.certverifyresult =
+ SSL_get_verify_result(connssl->handle);
+
+ if(data->set.ssl.certverifyresult != X509_V_OK) {
+ if(data->set.ssl.verifypeer) {
+ /* We probably never reach this, because SSL_connect() will fail
+ and we return earlier if verifypeer is set? */
+ if(strict)
+ failf(data, "SSL certificate verify result: %s (%ld)",
+ X509_verify_cert_error_string(lerr), lerr);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t SSL certificate verify result: %s (%ld),"
+ " continuing anyway.\n",
+ X509_verify_cert_error_string(lerr), lerr);
+ }
+ else
+ infof(data, "\t SSL certificate verify ok.\n");
+ }
+
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+ if(data->set.ssl.verifystatus) {
+ result = verifystatus(conn, connssl);
+ if(result) {
+ X509_free(connssl->server_cert);
+ connssl->server_cert = NULL;
+ return result;
+ }
+ }
+#endif
+
+ if(!strict)
+ /* when not strict, we don't bother about the verify cert problems */
+ result = CURLE_OK;
+
+ ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ if(!result && ptr) {
+ result = pkp_pin_peer_pubkey(connssl->server_cert, ptr);
+ if(result)
+ failf(data, "SSL: public key does not match pinned public key!");
+ }
+
+ X509_free(connssl->server_cert);
+ connssl->server_cert = NULL;
+ connssl->connecting_state = ssl_connect_done;
+
+ return result;
+}
+
+static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
+{
+ CURLcode result = CURLE_OK;
+ void *old_ssl_sessionid = NULL;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ bool incache;
+ SSL_SESSION *our_ssl_sessionid;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+#ifdef HAVE_SSL_GET1_SESSION
+ our_ssl_sessionid = SSL_get1_session(connssl->handle);
+
+ /* SSL_get1_session() will increment the reference
+ count and the session will stay in memory until explicitly freed with
+ SSL_SESSION_free(3), regardless of its state.
+ This function was introduced in openssl 0.9.5a. */
+#else
+ our_ssl_sessionid = SSL_get_session(connssl->handle);
+
+ /* if SSL_get1_session() is unavailable, use SSL_get_session().
+ This is an inferior option because the session can be flushed
+ at any time by openssl. It is included only so curl compiles
+ under versions of openssl < 0.9.5a.
+
+ WARNING: How curl behaves if it's session is flushed is
+ untested.
+ */
+#endif
+
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+
+ if(!incache) {
+ result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ 0 /* unknown size */);
+ if(result) {
+ failf(data, "failed to store ssl session");
+ return result;
+ }
+ }
+#ifdef HAVE_SSL_GET1_SESSION
+ else {
+ /* Session was incache, so refcount already incremented earlier.
+ * Avoid further increments with each SSL_get1_session() call.
+ * This does not free the session as refcount remains > 0
+ */
+ SSL_SESSION_free(our_ssl_sessionid);
+ }
+#endif
+
+ /*
+ * We check certificates to authenticate the server; otherwise we risk
+ * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
+ * verify the peer ignore faults and failures from the server cert
+ * operations.
+ */
+
+ result = servercert(conn, connssl,
+ (data->set.ssl.verifypeer || data->set.ssl.verifyhost));
+
+ if(!result)
+ connssl->connecting_state = ssl_connect_done;
+
+ return result;
+}
+
+static Curl_recv ossl_recv;
+static Curl_send ossl_send;
+
+static CURLcode ossl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1 == connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ result = ossl_connect_step1(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading ||
+ connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if this
+ * connection is done nonblocking and this loop would execute again. This
+ * permits the owner of a multi handle to abort a connection attempt
+ * before step2 has completed while ensuring that a client using select()
+ * or epoll() will always have a valid fdset to wait on.
+ */
+ result = ossl_connect_step2(conn, sockindex);
+ if(result || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return result;
+
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ result = ossl_connect_step3(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = ossl_recv;
+ conn->send[sockindex] = ossl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return ossl_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURL_STATIC CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = ossl_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+CURL_STATIC bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
+{
+ if(conn->ssl[connindex].handle)
+ /* SSL is in use */
+ return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+static ssize_t ossl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ /* SSL_write() is said to return 'int' while write() and send() returns
+ 'size_t' */
+ int err;
+ char error_buffer[120]; /* OpenSSL documents that this must be at least 120
+ bytes long. */
+ unsigned long sslerror;
+ int memlen;
+ int rc;
+
+ ERR_clear_error();
+
+ memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
+ rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+
+ if(rc <= 0) {
+ err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+
+ switch(err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* The operation did not complete; the same TLS/SSL I/O function
+ should be called again later. This is basically an EWOULDBLOCK
+ equivalent. */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ case SSL_ERROR_SYSCALL:
+ failf(conn->data, "SSL_write() returned SYSCALL, errno = %d",
+ SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ case SSL_ERROR_SSL:
+ /* A failure in the SSL library occurred, usually a protocol error.
+ The OpenSSL error queue contains more information on the error. */
+ sslerror = ERR_get_error();
+ failf(conn->data, "SSL_write() error: %s",
+ ERR_error_string(sslerror, error_buffer));
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ /* a true error */
+ failf(conn->data, "SSL_write() return error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ *curlcode = CURLE_OK;
+ return (ssize_t)rc; /* number of bytes */
+}
+
+static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *curlcode)
+{
+ char error_buffer[120]; /* OpenSSL documents that this must be at
+ least 120 bytes long. */
+ unsigned long sslerror;
+ ssize_t nread;
+ int buffsize;
+
+ ERR_clear_error();
+
+ buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
+ if(nread <= 0) {
+ /* failed SSL_read */
+ int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
+
+ switch(err) {
+ case SSL_ERROR_NONE: /* this is not an error */
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_read() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
+ value/errno" */
+ /* https://www.openssl.org/docs/crypto/ERR_get_error.html */
+ sslerror = ERR_get_error();
+ if((nread < 0) || sslerror) {
+ /* If the return code was negative or there actually is an error in the
+ queue */
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(sslerror, error_buffer),
+ SOCKERRNO);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ }
+ return nread;
+}
+
+CURL_STATIC size_t Curl_ossl_version(char *buffer, size_t size)
+{
+#ifdef YASSL_VERSION
+ /* yassl provides an OpenSSL API compatibility layer so it looks identical
+ to OpenSSL in all other aspects */
+ return snprintf(buffer, size, "yassl/%s", YASSL_VERSION);
+#else /* YASSL_VERSION */
+#ifdef OPENSSL_IS_BORINGSSL
+ return snprintf(buffer, size, "BoringSSL");
+#else /* OPENSSL_IS_BORINGSSL */
+
+#if(OPENSSL_VERSION_NUMBER >= 0x905000)
+ {
+ char sub[3];
+ unsigned long ssleay_value;
+ sub[2]='\0';
+ sub[1]='\0';
+ ssleay_value=SSLeay();
+ if(ssleay_value < 0x906000) {
+ ssleay_value=SSLEAY_VERSION_NUMBER;
+ sub[0]='\0';
+ }
+ else {
+ if(ssleay_value&0xff0) {
+ int minor_ver = (ssleay_value >> 4) & 0xff;
+ if(minor_ver > 26) {
+ /* handle extended version introduced for 0.9.8za */
+ sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1);
+ sub[0] = 'z';
+ }
+ else {
+ sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1);
+ }
+ }
+ else
+ sub[0]='\0';
+ }
+
+ return snprintf(buffer, size, "%s/%lx.%lx.%lx%s",
+#ifdef LIBRESSL_VERSION_NUMBER
+ "LibreSSL"
+#else
+ "OpenSSL"
+#endif
+ , (ssleay_value>>28)&0xf,
+ (ssleay_value>>20)&0xff,
+ (ssleay_value>>12)&0xff,
+ sub);
+ }
+
+#else /* OPENSSL_VERSION_NUMBER is less than 0.9.5 */
+
+#if(OPENSSL_VERSION_NUMBER >= 0x900000)
+ return snprintf(buffer, size, "OpenSSL/%lx.%lx.%lx",
+ (OPENSSL_VERSION_NUMBER>>28)&0xff,
+ (OPENSSL_VERSION_NUMBER>>20)&0xff,
+ (OPENSSL_VERSION_NUMBER>>12)&0xf);
+
+#else /* (OPENSSL_VERSION_NUMBER >= 0x900000) */
+ {
+ char sub[2];
+ sub[1]='\0';
+ if(OPENSSL_VERSION_NUMBER&0x0f) {
+ sub[0]=(OPENSSL_VERSION_NUMBER&0x0f) + 'a' -1;
+ }
+ else
+ sub[0]='\0';
+
+ return snprintf(buffer, size, "SSL/%x.%x.%x%s",
+ (OPENSSL_VERSION_NUMBER>>12)&0xff,
+ (OPENSSL_VERSION_NUMBER>>8)&0xf,
+ (OPENSSL_VERSION_NUMBER>>4)&0xf, sub);
+ }
+#endif /* (OPENSSL_VERSION_NUMBER >= 0x900000) */
+#endif /* OPENSSL_VERSION_NUMBER is less than 0.9.5 */
+
+#endif /* OPENSSL_IS_BORINGSSL */
+#endif /* YASSL_VERSION */
+}
+
+/* can be called with data == NULL */
+CURL_STATIC int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
+ size_t length)
+{
+ if(data) {
+ Curl_ossl_seed(data); /* Initiate the seed if not already done */
+ }
+ RAND_bytes(entropy, curlx_uztosi(length));
+ return 0; /* 0 as in no problem */
+}
+
+CURL_STATIC void Curl_ossl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum /* output */,
+ size_t unused)
+{
+ MD5_CTX MD5pw;
+ (void)unused;
+ MD5_Init(&MD5pw);
+ MD5_Update(&MD5pw, tmp, tmplen);
+ MD5_Final(md5sum, &MD5pw);
+}
+
+bool Curl_ossl_cert_status_request(void)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+#endif /* USE_OPENSSL */
diff --git a/libcurl/src/lib/vtls/openssl.h b/libcurl/src/lib/vtls/openssl.h
new file mode 100644
index 0000000..bfa3bc0
--- /dev/null
+++ b/libcurl/src/lib/vtls/openssl.h
@@ -0,0 +1,113 @@
+#ifndef HEADER_CURL_SSLUSE_H
+#define HEADER_CURL_SSLUSE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "../curl_setup.h"
+
+#ifdef USE_OPENSSL
+/*
+ * This header should only be needed to get included by vtls.c and openssl.c
+ */
+
+#include "urldata.h"
+
+CURL_STATIC CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+/* close a SSL connection */
+CURL_STATIC void Curl_ossl_close(struct connectdata *conn, int sockindex);
+
+/* tell OpenSSL to close down all open information regarding connections (and
+ thus session ID caching etc) */
+CURL_STATIC void Curl_ossl_close_all(struct SessionHandle *data);
+
+/* Sets an OpenSSL engine */
+CURL_STATIC CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine);
+
+/* function provided for the generic SSL-layer, called when a session id
+ should be freed */
+CURL_STATIC void Curl_ossl_session_free(void *ptr);
+
+/* Sets engine as default for all SSL operations */
+CURL_STATIC CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data);
+
+/* Build list of OpenSSL engines */
+CURL_STATIC struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data);
+
+CURL_STATIC int Curl_ossl_init(void);
+CURL_STATIC void Curl_ossl_cleanup(void);
+
+CURL_STATIC size_t Curl_ossl_version(char *buffer, size_t size);
+CURL_STATIC int Curl_ossl_check_cxn(struct connectdata *cxn);
+CURL_STATIC int Curl_ossl_shutdown(struct connectdata *conn, int sockindex);
+CURL_STATIC bool Curl_ossl_data_pending(const struct connectdata *conn,
+ int connindex);
+
+/* return 0 if a find random is filled in */
+CURL_STATIC int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
+ size_t length);
+CURL_STATIC void Curl_ossl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum /* output */,
+ size_t unused);
+
+bool Curl_ossl_cert_status_request(void);
+
+/* Set the API backend definition to OpenSSL */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
+
+/* this backend supports the CAPATH option */
+#define have_curlssl_ca_path 1
+
+/* this backend supports CURLOPT_CERTINFO */
+#define have_curlssl_certinfo 1
+
+/* this backend suppots CURLOPT_SSL_CTX_* */
+#define have_curlssl_ssl_ctx 1
+
+/* API setup for OpenSSL */
+#define curlssl_init Curl_ossl_init
+#define curlssl_cleanup Curl_ossl_cleanup
+#define curlssl_connect Curl_ossl_connect
+#define curlssl_connect_nonblocking Curl_ossl_connect_nonblocking
+#define curlssl_session_free(x) Curl_ossl_session_free(x)
+#define curlssl_close_all Curl_ossl_close_all
+#define curlssl_close Curl_ossl_close
+#define curlssl_shutdown(x,y) Curl_ossl_shutdown(x,y)
+#define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y)
+#define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x)
+#define curlssl_engines_list(x) Curl_ossl_engines_list(x)
+#define curlssl_version Curl_ossl_version
+#define curlssl_check_cxn Curl_ossl_check_cxn
+#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
+#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z)
+#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d)
+#define curlssl_cert_status_request() Curl_ossl_cert_status_request()
+
+#define DEFAULT_CIPHER_SELECTION \
+ "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
+
+#endif /* USE_OPENSSL */
+#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/libcurl/src/lib/vtls/polarssl.c b/libcurl/src/lib/vtls/polarssl.c
new file mode 100644
index 0000000..8deef27
--- /dev/null
+++ b/libcurl/src/lib/vtls/polarssl.c
@@ -0,0 +1,753 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+#include "../curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+#include <polarssl/net.h>
+#include <polarssl/ssl.h>
+#include <polarssl/certs.h>
+#include <polarssl/x509.h>
+#include <polarssl/version.h>
+
+#if POLARSSL_VERSION_NUMBER < 0x01030000
+#error too old PolarSSL
+#endif
+
+#include <polarssl/error.h>
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "polarssl.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "rawstr.h"
+#include "polarssl_threadlock.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* apply threading? */
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+#define THREADING_SUPPORT
+#endif
+
+#if defined(THREADING_SUPPORT)
+static entropy_context entropy;
+
+static int entropy_init_initialized = 0;
+
+/* start of entropy_init_mutex() */
+static void entropy_init_mutex(entropy_context *ctx)
+{
+ /* lock 0 = entropy_init_mutex() */
+ polarsslthreadlock_lock_function(0);
+ if(entropy_init_initialized == 0) {
+ entropy_init(ctx);
+ entropy_init_initialized = 1;
+ }
+ polarsslthreadlock_unlock_function(0);
+}
+/* end of entropy_init_mutex() */
+
+/* start of entropy_func_mutex() */
+static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
+{
+ int ret;
+ /* lock 1 = entropy_func_mutex() */
+ polarsslthreadlock_lock_function(1);
+ ret = entropy_func(data, output, len);
+ polarsslthreadlock_unlock_function(1);
+
+ return ret;
+}
+/* end of entropy_func_mutex() */
+
+#endif /* THREADING_SUPPORT */
+
+/* Define this to enable lots of debugging for PolarSSL */
+#undef POLARSSL_DEBUG
+
+#ifdef POLARSSL_DEBUG
+static void polarssl_debug(void *context, int level, const char *line)
+{
+ struct SessionHandle *data = NULL;
+
+ if(!context)
+ return;
+
+ data = (struct SessionHandle *)context;
+
+ infof(data, "%s", line);
+ (void) level;
+}
+#else
+#endif
+
+/* ALPN for http2? */
+#ifdef POLARSSL_SSL_ALPN
+# define HAS_ALPN
+#endif
+
+static Curl_recv polarssl_recv;
+static Curl_send polarssl_send;
+
+
+static CURLcode
+polarssl_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+
+ bool sni = TRUE; /* default is SNI enabled */
+ int ret = -1;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ void *old_session = NULL;
+ size_t old_session_size = 0;
+ char errorbuf[128];
+ errorbuf[0]=0;
+
+ /* PolarSSL only supports SSLv3 and TLSv1 */
+ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ failf(data, "PolarSSL does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
+ sni = FALSE; /* SSLv3 has no SNI */
+
+#ifdef THREADING_SUPPORT
+ entropy_init_mutex(&entropy);
+
+ if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
+ connssl->ssn.id, connssl->ssn.length)) != 0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+#else
+ entropy_init(&connssl->entropy);
+
+ if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
+ connssl->ssn.id, connssl->ssn.length)) != 0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+#endif /* THREADING_SUPPORT */
+
+ /* Load the trusted CA */
+ memset(&connssl->cacert, 0, sizeof(x509_crt));
+
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ ret = x509_crt_parse_file(&connssl->cacert,
+ data->set.str[STRING_SSL_CAFILE]);
+
+ if(ret<0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+
+ if(data->set.str[STRING_SSL_CAPATH]) {
+ ret = x509_crt_parse_path(&connssl->cacert,
+ data->set.str[STRING_SSL_CAPATH]);
+
+ if(ret<0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+
+ /* Load the client certificate */
+ memset(&connssl->clicert, 0, sizeof(x509_crt));
+
+ if(data->set.str[STRING_CERT]) {
+ ret = x509_crt_parse_file(&connssl->clicert,
+ data->set.str[STRING_CERT]);
+
+ if(ret) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_CERT], -ret, errorbuf);
+
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Load the client private key */
+ if(data->set.str[STRING_KEY]) {
+ pk_context pk;
+ pk_init(&pk);
+ ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
+ data->set.str[STRING_KEY_PASSWD]);
+ if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
+ ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+ if(ret == 0)
+ rsa_copy(&connssl->rsa, pk_rsa(pk));
+ else
+ rsa_free(&connssl->rsa);
+ pk_free(&pk);
+
+ if(ret) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_KEY], -ret, errorbuf);
+
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Load the CRL */
+ memset(&connssl->crl, 0, sizeof(x509_crl));
+
+ if(data->set.str[STRING_SSL_CRLFILE]) {
+ ret = x509_crl_parse_file(&connssl->crl,
+ data->set.str[STRING_SSL_CRLFILE]);
+
+ if(ret) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ }
+
+ infof(data, "PolarSSL: Connecting to %s:%d\n",
+ conn->host.name, conn->remote_port);
+
+ if(ssl_init(&connssl->ssl)) {
+ failf(data, "PolarSSL: ssl_init failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_1);
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_0);
+ ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_0);
+ infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_1);
+ ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_1);
+ infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_2);
+ ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_2);
+ infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_3);
+ ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_3);
+ infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
+ break;
+ }
+
+ ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
+ ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
+
+ ssl_set_rng(&connssl->ssl, ctr_drbg_random,
+ &connssl->ctr_drbg);
+ ssl_set_bio(&connssl->ssl,
+ net_recv, &conn->sock[sockindex],
+ net_send, &conn->sock[sockindex]);
+
+ ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
+ if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
+ memcpy(&connssl->ssn, old_session, old_session_size);
+ infof(data, "PolarSSL re-using session\n");
+ }
+
+ ssl_set_session(&connssl->ssl,
+ &connssl->ssn);
+
+ ssl_set_ca_chain(&connssl->ssl,
+ &connssl->cacert,
+ &connssl->crl,
+ conn->host.name);
+
+ ssl_set_own_cert_rsa(&connssl->ssl,
+ &connssl->clicert, &connssl->rsa);
+
+ if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
+#ifdef ENABLE_IPV6
+ !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
+#endif
+ sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+ infof(data, "WARNING: failed to configure "
+ "server name indication (SNI) TLS extension\n");
+ }
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ static const char* protocols[3];
+ int cur = 0;
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+ protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ protocols[cur++] = ALPN_HTTP_1_1;
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ protocols[cur] = NULL;
+
+ ssl_set_alpn_protocols(&connssl->ssl, protocols);
+ }
+#endif
+
+#ifdef POLARSSL_DEBUG
+ ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
+#endif
+
+ connssl->connecting_state = ssl_connect_2;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+polarssl_connect_step2(struct connectdata *conn,
+ int sockindex)
+{
+ int ret;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ char buffer[1024];
+
+ char errorbuf[128];
+ errorbuf[0] = 0;
+
+ conn->recv[sockindex] = polarssl_recv;
+ conn->send[sockindex] = polarssl_send;
+
+ ret = ssl_handshake(&connssl->ssl);
+
+ switch(ret) {
+ case 0:
+ break;
+
+ case POLARSSL_ERR_NET_WANT_READ:
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+
+ case POLARSSL_ERR_NET_WANT_WRITE:
+ connssl->connecting_state = ssl_connect_2_writing;
+ return CURLE_OK;
+
+ default:
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
+ -ret, errorbuf);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
+ ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) );
+
+ ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+
+ if(ret && data->set.ssl.verifypeer) {
+ if(ret & BADCERT_EXPIRED)
+ failf(data, "Cert verify failed: BADCERT_EXPIRED");
+
+ if(ret & BADCERT_REVOKED) {
+ failf(data, "Cert verify failed: BADCERT_REVOKED");
+ return CURLE_SSL_CACERT;
+ }
+
+ if(ret & BADCERT_CN_MISMATCH)
+ failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
+
+ if(ret & BADCERT_NOT_TRUSTED)
+ failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
+
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(ssl_get_peer_cert(&(connssl->ssl))) {
+ /* If the session was resumed, there will be no peer certs */
+ memset(buffer, 0, sizeof(buffer));
+
+ if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
+ ssl_get_peer_cert(&(connssl->ssl))) != -1)
+ infof(data, "Dumping cert info:\n%s\n", buffer);
+ }
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl);
+
+ if(next_protocol != NULL) {
+ infof(data, "ALPN, server accepted to use %s\n", next_protocol);
+
+#ifdef USE_NGHTTP2
+ if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN)) {
+ conn->negnpn = CURL_HTTP_VERSION_2_0;
+ }
+ else
+#endif
+ if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ }
+ else
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+#endif
+
+ connssl->connecting_state = ssl_connect_3;
+ infof(data, "SSL connected\n");
+
+ return CURLE_OK;
+}
+
+static CURLcode
+polarssl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode result = CURLE_OK;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ void *old_ssl_sessionid = NULL;
+ ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn;
+ bool incache;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ /* Save the current session data for possible re-use */
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+
+ if(!incache) {
+ void *new_session = malloc(sizeof(ssl_session));
+
+ if(new_session) {
+ memcpy(new_session, our_ssl_sessionid, sizeof(ssl_session));
+
+ result = Curl_ssl_addsessionid(conn, new_session, sizeof(ssl_session));
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+
+ if(result) {
+ failf(data, "failed to store ssl session");
+ return result;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return CURLE_OK;
+}
+
+static ssize_t polarssl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ int ret = -1;
+
+ ret = ssl_write(&conn->ssl[sockindex].ssl,
+ (unsigned char *)mem, len);
+
+ if(ret < 0) {
+ *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
+ CURLE_AGAIN : CURLE_SEND_ERROR;
+ ret = -1;
+ }
+
+ return ret;
+}
+
+CURL_STATIC void Curl_polarssl_close(struct connectdata *conn, int sockindex)
+{
+ rsa_free(&conn->ssl[sockindex].rsa);
+ x509_crt_free(&conn->ssl[sockindex].clicert);
+ x509_crt_free(&conn->ssl[sockindex].cacert);
+ x509_crl_free(&conn->ssl[sockindex].crl);
+ ssl_free(&conn->ssl[sockindex].ssl);
+}
+
+static ssize_t polarssl_recv(struct connectdata *conn,
+ int num,
+ char *buf,
+ size_t buffersize,
+ CURLcode *curlcode)
+{
+ int ret = -1;
+ ssize_t len = -1;
+
+ memset(buf, 0, buffersize);
+ ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
+
+ if(ret <= 0) {
+ if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
+ return 0;
+
+ *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
+ CURLE_AGAIN : CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ len = ret;
+
+ return len;
+}
+
+CURL_STATIC void Curl_polarssl_session_free(void *ptr)
+{
+ free(ptr);
+}
+
+/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
+ higher) will be mbed TLS branded.. */
+
+CURL_STATIC size_t Curl_polarssl_version(char *buffer, size_t size)
+{
+ unsigned int version = version_get_number();
+ return snprintf(buffer, size, "%s/%d.%d.%d",
+ version >= 0x01030A00?"mbedTLS":"PolarSSL",
+ version>>24, (version>>16)&0xff, (version>>8)&0xff);
+}
+
+static CURLcode
+polarssl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1 == connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ result = polarssl_connect_step1(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading ||
+ connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ result = polarssl_connect_step2(conn, sockindex);
+ if(result || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return result;
+
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ result = polarssl_connect_step3(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = polarssl_recv;
+ conn->send[sockindex] = polarssl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+CURL_STATIC CURLcode
+Curl_polarssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return polarssl_connect_common(conn, sockindex, TRUE, done);
+}
+
+
+CURL_STATIC CURLcode
+Curl_polarssl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = polarssl_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+/*
+ * return 0 error initializing SSL
+ * return 1 SSL initialized successfully
+ */
+int polarssl_init(void)
+{
+ return polarsslthreadlock_thread_setup();
+}
+
+void polarssl_cleanup(void)
+{
+ (void)polarsslthreadlock_thread_cleanup();
+}
+
+#endif /* USE_POLARSSL */
diff --git a/libcurl/src/lib/vtls/polarssl.h b/libcurl/src/lib/vtls/polarssl.h
new file mode 100644
index 0000000..98c2e5c
--- /dev/null
+++ b/libcurl/src/lib/vtls/polarssl.h
@@ -0,0 +1,75 @@
+#ifndef HEADER_CURL_POLARSSL_H
+#define HEADER_CURL_POLARSSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+/* Called on first use PolarSSL, setup threading if supported */
+int polarssl_init(void);
+void polarssl_cleanup(void);
+
+
+CURL_STATIC CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
+
+CURL_STATIC CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+ /* close a SSL connection */
+CURL_STATIC void Curl_polarssl_close(struct connectdata *conn, int sockindex);
+
+CURL_STATIC void Curl_polarssl_session_free(void *ptr);
+CURL_STATIC size_t Curl_polarssl_version(char *buffer, size_t size);
+CURL_STATIC int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
+
+/* Set the API backend definition to PolarSSL */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL
+
+/* this backend supports the CAPATH option */
+#define have_curlssl_ca_path 1
+
+/* API setup for PolarSSL */
+#define curlssl_init() polarssl_init()
+#define curlssl_cleanup() polarssl_cleanup()
+#define curlssl_connect Curl_polarssl_connect
+#define curlssl_connect_nonblocking Curl_polarssl_connect_nonblocking
+#define curlssl_session_free(x) Curl_polarssl_session_free(x)
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_polarssl_close
+#define curlssl_shutdown(x,y) 0
+#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_polarssl_version
+#define curlssl_check_cxn(x) ((void)x, -1)
+#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+
+/* This might cause libcurl to use a weeker random!
+ TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that
+*/
+#define curlssl_random(x,y,z) ((void)x, (void)y, (void)z, CURLE_NOT_BUILT_IN)
+
+#endif /* USE_POLARSSL */
+#endif /* HEADER_CURL_POLARSSL_H */
diff --git a/libcurl/src/lib/vtls/polarssl_threadlock.c b/libcurl/src/lib/vtls/polarssl_threadlock.c
new file mode 100644
index 0000000..8a8d3ea
--- /dev/null
+++ b/libcurl/src/lib/vtls/polarssl_threadlock.c
@@ -0,0 +1,153 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+#if defined(USE_POLARSSL) && \
+ (defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32))
+
+#if defined(USE_THREADS_POSIX)
+# ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+# endif
+#elif defined(USE_THREADS_WIN32)
+# ifdef HAVE_PROCESS_H
+# include <process.h>
+# endif
+#endif
+
+#include "polarssl_threadlock.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* number of thread locks */
+#define NUMT 2
+
+/* This array will store all of the mutexes available to PolarSSL. */
+static POLARSSL_MUTEX_T *mutex_buf = NULL;
+
+int polarsslthreadlock_thread_setup(void)
+{
+ int i;
+ int ret;
+
+ mutex_buf = malloc(NUMT * sizeof(POLARSSL_MUTEX_T));
+ if(!mutex_buf)
+ return 0; /* error, no number of threads defined */
+
+#ifdef HAVE_PTHREAD_H
+ for(i = 0; i < NUMT; i++) {
+ ret = pthread_mutex_init(&mutex_buf[i], NULL);
+ if(ret)
+ return 0; /* pthread_mutex_init failed */
+ }
+#elif defined(HAVE_PROCESS_H)
+ for(i = 0; i < NUMT; i++) {
+ mutex_buf[i] = CreateMutex(0, FALSE, 0);
+ if(mutex_buf[i] == 0)
+ return 0; /* CreateMutex failed */
+ }
+#endif /* HAVE_PTHREAD_H */
+
+ return 1; /* OK */
+}
+
+int polarsslthreadlock_thread_cleanup(void)
+{
+ int i;
+ int ret;
+
+ if(!mutex_buf)
+ return 0; /* error, no threads locks defined */
+
+#ifdef HAVE_PTHREAD_H
+ for(i = 0; i < NUMT; i++) {
+ ret = pthread_mutex_destroy(&mutex_buf[i]);
+ if(ret)
+ return 0; /* pthread_mutex_destroy failed */
+ }
+#elif defined(HAVE_PROCESS_H)
+ for(i = 0; i < NUMT; i++) {
+ ret = CloseHandle(mutex_buf[i]);
+ if(!ret)
+ return 0; /* CloseHandle failed */
+ }
+#endif /* HAVE_PTHREAD_H */
+ free(mutex_buf);
+ mutex_buf = NULL;
+
+ return 1; /* OK */
+}
+
+int polarsslthreadlock_lock_function(int n)
+{
+ int ret;
+#ifdef HAVE_PTHREAD_H
+ if(n < NUMT) {
+ ret = pthread_mutex_lock(&mutex_buf[n]);
+ if(ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_lock_function failed\n"));
+ return 0; /* pthread_mutex_lock failed */
+ }
+ }
+#elif defined(HAVE_PROCESS_H)
+ if(n < NUMT) {
+ ret = (WaitForSingleObject(mutex_buf[n], INFINITE)==WAIT_FAILED?1:0);
+ if(ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_lock_function failed\n"));
+ return 0; /* pthread_mutex_lock failed */
+ }
+ }
+#endif /* HAVE_PTHREAD_H */
+ return 1; /* OK */
+}
+
+int polarsslthreadlock_unlock_function(int n)
+{
+ int ret;
+#ifdef HAVE_PTHREAD_H
+ if(n < NUMT) {
+ ret = pthread_mutex_unlock(&mutex_buf[n]);
+ if(ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_unlock_function failed\n"));
+ return 0; /* pthread_mutex_unlock failed */
+ }
+ }
+#elif defined(HAVE_PROCESS_H)
+ if(n < NUMT) {
+ ret = ReleaseMutex(mutex_buf[n]);
+ if(!ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_unlock_function failed\n"));
+ return 0; /* pthread_mutex_lock failed */
+ }
+ }
+#endif /* HAVE_PTHREAD_H */
+ return 1; /* OK */
+}
+
+#endif /* USE_POLARSSL */
diff --git a/libcurl/src/lib/vtls/polarssl_threadlock.h b/libcurl/src/lib/vtls/polarssl_threadlock.h
new file mode 100644
index 0000000..b67b3f9
--- /dev/null
+++ b/libcurl/src/lib/vtls/polarssl_threadlock.h
@@ -0,0 +1,53 @@
+#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H
+#define HEADER_CURL_POLARSSL_THREADLOCK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+#if defined(USE_THREADS_POSIX)
+# define POLARSSL_MUTEX_T pthread_mutex_t
+#elif defined(USE_THREADS_WIN32)
+# define POLARSSL_MUTEX_T HANDLE
+#endif
+
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+
+int polarsslthreadlock_thread_setup(void);
+int polarsslthreadlock_thread_cleanup(void);
+int polarsslthreadlock_lock_function(int n);
+int polarsslthreadlock_unlock_function(int n);
+
+#else
+
+#define polarsslthreadlock_thread_setup() 1
+#define polarsslthreadlock_thread_cleanup() 1
+#define polarsslthreadlock_lock_function(x) 1
+#define polarsslthreadlock_unlock_function(x) 1
+
+#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
+
+#endif /* USE_POLARSSL */
+
+#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */
diff --git a/libcurl/src/lib/vtls/schannel.c b/libcurl/src/lib/vtls/schannel.c
new file mode 100644
index 0000000..00f6b81
--- /dev/null
+++ b/libcurl/src/lib/vtls/schannel.c
@@ -0,0 +1,1364 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all SChannel-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+/*
+ * Based upon the PolarSSL implementation in polarssl.c and polarssl.h:
+ * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ *
+ * Based upon the CyaSSL implementation in cyassl.c and cyassl.h:
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * Thanks for code and inspiration!
+ */
+
+#include "../curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#ifndef USE_WINDOWS_SSPI
+# error "Can't compile SCHANNEL support without SSPI."
+#endif
+
+#include "../curl_sspi.h"
+#include "schannel.h"
+#include "vtls.h"
+#include "../sendf.h"
+#include "../connect.h" /* for the connect timeout */
+#include "../strerror.h"
+#include "../select.h" /* for the socket readyness */
+#include "../inet_pton.h" /* for IP addr SNI check */
+#include "../curl_multibyte.h"
+#include "../warnless.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+/* The last #include file should be: */
+#include "../memdebug.h"
+
+/* Uncomment to force verbose output
+ * #define infof(x, y, ...) printf(y, __VA_ARGS__)
+ * #define failf(x, y, ...) printf(y, __VA_ARGS__)
+ */
+
+static Curl_recv schannel_recv;
+static Curl_send schannel_send;
+
+#ifdef _WIN32_WCE
+static CURLcode verify_certificate(struct connectdata *conn, int sockindex);
+#endif
+
+static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
+ void *BufDataPtr, unsigned long BufByteSize)
+{
+ buffer->cbBuffer = BufByteSize;
+ buffer->BufferType = BufType;
+ buffer->pvBuffer = BufDataPtr;
+}
+
+static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
+ unsigned long NumArrElem)
+{
+ desc->ulVersion = SECBUFFER_VERSION;
+ desc->pBuffers = BufArr;
+ desc->cBuffers = NumArrElem;
+}
+
+static CURLcode
+schannel_connect_step1(struct connectdata *conn, int sockindex)
+{
+ ssize_t written = -1;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SecBuffer outbuf;
+ SecBufferDesc outbuf_desc;
+ SCHANNEL_CRED schannel_cred;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+ struct curl_schannel_cred *old_cred = NULL;
+ struct in_addr addr;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+ TCHAR *host_name;
+ CURLcode result;
+
+ infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
+ conn->host.name, conn->remote_port);
+
+ /* check for an existing re-usable credential handle */
+ if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) {
+ connssl->cred = old_cred;
+ infof(data, "schannel: re-using existing credential handle\n");
+ }
+ else {
+ /* setup Schannel API options */
+ memset(&schannel_cred, 0, sizeof(schannel_cred));
+ schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
+
+ if(data->set.ssl.verifypeer) {
+#ifdef _WIN32_WCE
+ /* certificate validation on CE doesn't seem to work right; we'll
+ do it following a more manual process. */
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
+ SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+#else
+ schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
+ SCH_CRED_REVOCATION_CHECK_CHAIN;
+#endif
+ infof(data, "schannel: checking server certificate revocation\n");
+ }
+ else {
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
+ SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+ infof(data, "schannel: disable server certificate revocation checks\n");
+ }
+
+ if(!data->set.ssl.verifyhost) {
+ schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
+ infof(data, "schannel: verifyhost setting prevents Schannel from "
+ "comparing the supplied target name with the subject "
+ "names in server certificates. Also disables SNI.\n");
+ }
+
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
+ SP_PROT_TLS1_1_CLIENT |
+ SP_PROT_TLS1_2_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
+ break;
+ }
+
+ /* allocate memory for the re-usable credential handle */
+ connssl->cred = (struct curl_schannel_cred *)
+ malloc(sizeof(struct curl_schannel_cred));
+ if(!connssl->cred) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memset(connssl->cred, 0, sizeof(struct curl_schannel_cred));
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx */
+ sspi_status = s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
+ SECPKG_CRED_OUTBOUND, NULL, &schannel_cred, NULL, NULL,
+ &connssl->cred->cred_handle, &connssl->cred->time_stamp);
+
+ if(sspi_status != SEC_E_OK) {
+ if(sspi_status == SEC_E_WRONG_PRINCIPAL)
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ else
+ failf(data, "schannel: AcquireCredentialsHandle failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ Curl_safefree(connssl->cred);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* Warn if SNI is disabled due to use of an IP address */
+ if(Curl_inet_pton(AF_INET, conn->host.name, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, conn->host.name, &addr6)
+#endif
+ ) {
+ infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
+ }
+
+ /* setup output buffer */
+ InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
+
+ /* setup request flags */
+ connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
+ ISC_REQ_STREAM;
+
+ /* allocate memory for the security context handle */
+ connssl->ctxt = (struct curl_schannel_ctxt *)
+ malloc(sizeof(struct curl_schannel_ctxt));
+ if(!connssl->ctxt) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
+
+ host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ if(!host_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */
+
+ sspi_status = s_pSecFn->InitializeSecurityContext(
+ &connssl->cred->cred_handle, NULL, host_name,
+ connssl->req_flags, 0, 0, NULL, 0, &connssl->ctxt->ctxt_handle,
+ &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+
+ Curl_unicodefree(host_name);
+
+ if(sspi_status != SEC_I_CONTINUE_NEEDED) {
+ if(sspi_status == SEC_E_WRONG_PRINCIPAL)
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ else
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ Curl_safefree(connssl->ctxt);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ infof(data, "schannel: sending initial handshake data: "
+ "sending %lu bytes...\n", outbuf.cbBuffer);
+
+ /* send initial handshake data which is now stored in output buffer */
+ result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ outbuf.cbBuffer, &written);
+ s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
+ if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
+ failf(data, "schannel: failed to send initial handshake data: "
+ "sent %zd of %lu bytes", written, outbuf.cbBuffer);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ infof(data, "schannel: sent initial handshake data: "
+ "sent %zd bytes\n", written);
+
+ /* continue to second handshake step */
+ connssl->connecting_state = ssl_connect_2;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+schannel_connect_step2(struct connectdata *conn, int sockindex)
+{
+ int i;
+ ssize_t nread = -1, written = -1;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ unsigned char *reallocated_buffer;
+ size_t reallocated_length;
+ SecBuffer outbuf[2];
+ SecBufferDesc outbuf_desc;
+ SecBuffer inbuf[2];
+ SecBufferDesc inbuf_desc;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+ TCHAR *host_name;
+ CURLcode result;
+ bool doread;
+
+ doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
+
+ infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
+ conn->host.name, conn->remote_port);
+
+ if(!connssl->cred || !connssl->ctxt)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* buffer to store previously received and encrypted data */
+ if(connssl->encdata_buffer == NULL) {
+ connssl->encdata_offset = 0;
+ connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ connssl->encdata_buffer = malloc(connssl->encdata_length);
+ if(connssl->encdata_buffer == NULL) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* if we need a bigger buffer to read a full message, increase buffer now */
+ if(connssl->encdata_length - connssl->encdata_offset <
+ CURL_SCHANNEL_BUFFER_FREE_SIZE) {
+ /* increase internal encrypted data buffer */
+ reallocated_length = connssl->encdata_offset +
+ CURL_SCHANNEL_BUFFER_FREE_SIZE;
+ reallocated_buffer = realloc(connssl->encdata_buffer,
+ reallocated_length);
+
+ if(reallocated_buffer == NULL) {
+ failf(data, "schannel: unable to re-allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ connssl->encdata_buffer = reallocated_buffer;
+ connssl->encdata_length = reallocated_length;
+ }
+ }
+
+ for(;;) {
+ if(doread) {
+ /* read encrypted handshake data from socket */
+ result = Curl_read_plain(conn->sock[sockindex],
+ (char *) (connssl->encdata_buffer +
+ connssl->encdata_offset),
+ connssl->encdata_length -
+ connssl->encdata_offset,
+ &nread);
+ if(result == CURLE_AGAIN) {
+ if(connssl->connecting_state != ssl_connect_2_writing)
+ connssl->connecting_state = ssl_connect_2_reading;
+ infof(data, "schannel: failed to receive handshake, "
+ "need more data\n");
+ return CURLE_OK;
+ }
+ else if((result != CURLE_OK) || (nread == 0)) {
+ failf(data, "schannel: failed to receive handshake, "
+ "SSL/TLS connection failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* increase encrypted data buffer offset */
+ connssl->encdata_offset += nread;
+ }
+
+ infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+
+ /* setup input buffers */
+ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset),
+ curlx_uztoul(connssl->encdata_offset));
+ InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&inbuf_desc, inbuf, 2);
+
+ /* setup output buffers */
+ InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
+ InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, outbuf, 2);
+
+ if(inbuf[0].pvBuffer == NULL) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* copy received handshake data into input buffer */
+ memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
+ connssl->encdata_offset);
+
+ host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ if(!host_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */
+
+ sspi_status = s_pSecFn->InitializeSecurityContext(
+ &connssl->cred->cred_handle, &connssl->ctxt->ctxt_handle,
+ host_name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+ &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+
+ Curl_unicodefree(host_name);
+
+ /* free buffer for received handshake data */
+ Curl_safefree(inbuf[0].pvBuffer);
+
+ /* check if the handshake was incomplete */
+ if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ infof(data, "schannel: received incomplete message, need more data\n");
+ return CURLE_OK;
+ }
+
+ /* check if the handshake needs to be continued */
+ if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) {
+ for(i = 0; i < 2; i++) {
+ /* search for handshake tokens that need to be send */
+ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
+ infof(data, "schannel: sending next handshake data: "
+ "sending %lu bytes...\n", outbuf[i].cbBuffer);
+
+ /* send handshake token to server */
+ result = Curl_write_plain(conn, conn->sock[sockindex],
+ outbuf[i].pvBuffer, outbuf[i].cbBuffer,
+ &written);
+ if((result != CURLE_OK) ||
+ (outbuf[i].cbBuffer != (size_t) written)) {
+ failf(data, "schannel: failed to send next handshake data: "
+ "sent %zd of %lu bytes", written, outbuf[i].cbBuffer);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* free obsolete buffer */
+ if(outbuf[i].pvBuffer != NULL) {
+ s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer);
+ }
+ }
+ }
+ else {
+ if(sspi_status == SEC_E_WRONG_PRINCIPAL)
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ else
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* check if there was additional remaining encrypted data */
+ if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
+ infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer);
+ /*
+ There are two cases where we could be getting extra data here:
+ 1) If we're renegotiating a connection and the handshake is already
+ complete (from the server perspective), it can encrypted app data
+ (not handshake data) in an extra buffer at this point.
+ 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a
+ connection and this extra data is part of the handshake.
+ We should process the data immediately; waiting for the socket to
+ be ready may fail since the server is done sending handshake data.
+ */
+ /* check if the remaining data is less than the total amount
+ and therefore begins after the already processed data */
+ if(connssl->encdata_offset > inbuf[1].cbBuffer) {
+ memmove(connssl->encdata_buffer,
+ (connssl->encdata_buffer + connssl->encdata_offset) -
+ inbuf[1].cbBuffer, inbuf[1].cbBuffer);
+ connssl->encdata_offset = inbuf[1].cbBuffer;
+ if(sspi_status == SEC_I_CONTINUE_NEEDED) {
+ doread = FALSE;
+ continue;
+ }
+ }
+ }
+ else {
+ connssl->encdata_offset = 0;
+ }
+ break;
+ }
+
+ /* check if the handshake needs to be continued */
+ if(sspi_status == SEC_I_CONTINUE_NEEDED) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+
+ /* check if the handshake is complete */
+ if(sspi_status == SEC_E_OK) {
+ connssl->connecting_state = ssl_connect_3;
+ infof(data, "schannel: SSL/TLS handshake complete\n");
+ }
+
+#ifdef _WIN32_WCE
+ /* Windows CE doesn't do any server certificate validation.
+ We have to do it manually. */
+ if(data->set.ssl.verifypeer)
+ return verify_certificate(conn, sockindex);
+#endif
+
+ return CURLE_OK;
+}
+
+static CURLcode
+schannel_connect_step3(struct connectdata *conn, int sockindex)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct curl_schannel_cred *old_cred = NULL;
+ bool incache;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
+ conn->host.name, conn->remote_port);
+
+ if(!connssl->cred)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* check if the required context attributes are met */
+ if(connssl->ret_flags != connssl->req_flags) {
+ if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT))
+ failf(data, "schannel: failed to setup sequence detection");
+ if(!(connssl->ret_flags & ISC_RET_REPLAY_DETECT))
+ failf(data, "schannel: failed to setup replay detection");
+ if(!(connssl->ret_flags & ISC_RET_CONFIDENTIALITY))
+ failf(data, "schannel: failed to setup confidentiality");
+ if(!(connssl->ret_flags & ISC_RET_ALLOCATED_MEMORY))
+ failf(data, "schannel: failed to setup memory allocation");
+ if(!(connssl->ret_flags & ISC_RET_STREAM))
+ failf(data, "schannel: failed to setup stream orientation");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* increment the reference counter of the credential/session handle */
+ if(connssl->cred && connssl->ctxt) {
+ connssl->cred->refcount++;
+ infof(data, "schannel: incremented credential handle refcount = %d\n",
+ connssl->cred->refcount);
+ }
+
+ /* save the current session data for possible re-use */
+ incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL));
+ if(incache) {
+ if(old_cred != connssl->cred) {
+ infof(data, "schannel: old credential handle is stale, removing\n");
+ Curl_ssl_delsessionid(conn, (void *)old_cred);
+ incache = FALSE;
+ }
+ }
+
+ if(!incache) {
+ result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
+ sizeof(struct curl_schannel_cred));
+ if(result) {
+ failf(data, "schannel: failed to store credential handle");
+ return result;
+ }
+ else {
+ connssl->cred->cached = TRUE;
+ infof(data, "schannel: stored credential handle in session cache\n");
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+schannel_connect_common(struct connectdata *conn, int sockindex,
+ bool nonblocking, bool *done)
+{
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1 == connssl->connecting_state) {
+ /* check out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL/TLS connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ result = schannel_connect_step1(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL/TLS connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing ==
+ connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading ==
+ connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking ? 0 : timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL/TLS connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ result = schannel_connect_step2(conn, sockindex);
+ if(result || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return result;
+
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ result = schannel_connect_step3(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = schannel_recv;
+ conn->send[sockindex] = schannel_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* reset our connection state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+static ssize_t
+schannel_send(struct connectdata *conn, int sockindex,
+ const void *buf, size_t len, CURLcode *err)
+{
+ ssize_t written = -1;
+ size_t data_len = 0;
+ unsigned char *data = NULL;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SecBuffer outbuf[4];
+ SecBufferDesc outbuf_desc;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+ CURLcode result;
+
+ /* check if the maximum stream sizes were queried */
+ if(connssl->stream_sizes.cbMaximumMessage == 0) {
+ sspi_status = s_pSecFn->QueryContextAttributes(
+ &connssl->ctxt->ctxt_handle,
+ SECPKG_ATTR_STREAM_SIZES,
+ &connssl->stream_sizes);
+ if(sspi_status != SEC_E_OK) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ }
+
+ /* check if the buffer is longer than the maximum message length */
+ if(len > connssl->stream_sizes.cbMaximumMessage) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ /* calculate the complete message length and allocate a buffer for it */
+ data_len = connssl->stream_sizes.cbHeader + len +
+ connssl->stream_sizes.cbTrailer;
+ data = (unsigned char *) malloc(data_len);
+ if(data == NULL) {
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ /* setup output buffers (header, data, trailer, empty) */
+ InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
+ data, connssl->stream_sizes.cbHeader);
+ InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
+ data + connssl->stream_sizes.cbHeader, curlx_uztoul(len));
+ InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
+ data + connssl->stream_sizes.cbHeader + len,
+ connssl->stream_sizes.cbTrailer);
+ InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, outbuf, 4);
+
+ /* copy data into output buffer */
+ memcpy(outbuf[1].pvBuffer, buf, len);
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
+ sspi_status = s_pSecFn->EncryptMessage(&connssl->ctxt->ctxt_handle, 0,
+ &outbuf_desc, 0);
+
+ /* check if the message was encrypted */
+ if(sspi_status == SEC_E_OK) {
+ written = 0;
+
+ /* send the encrypted message including header, data and trailer */
+ len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
+
+ /*
+ It's important to send the full message which includes the header,
+ encrypted payload, and trailer. Until the client receives all the
+ data a coherent message has not been delivered and the client
+ can't read any of it.
+
+ If we wanted to buffer the unwritten encrypted bytes, we would
+ tell the client that all data it has requested to be sent has been
+ sent. The unwritten encrypted bytes would be the first bytes to
+ send on the next invocation.
+ Here's the catch with this - if we tell the client that all the
+ bytes have been sent, will the client call this method again to
+ send the buffered data? Looking at who calls this function, it
+ seems the answer is NO.
+ */
+
+ /* send entire message or fail */
+ while(len > (size_t)written) {
+ ssize_t this_write;
+ long timeleft;
+ int what;
+
+ this_write = 0;
+
+ timeleft = Curl_timeleft(conn->data, NULL, FALSE);
+ if(timeleft < 0) {
+ /* we already got the timeout */
+ failf(conn->data, "schannel: timed out sending data "
+ "(bytes sent: %zd)", written);
+ *err = CURLE_OPERATION_TIMEDOUT;
+ written = -1;
+ break;
+ }
+
+ what = Curl_socket_ready(CURL_SOCKET_BAD, conn->sock[sockindex],
+ timeleft);
+ if(what < 0) {
+ /* fatal error */
+ failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ *err = CURLE_SEND_ERROR;
+ written = -1;
+ break;
+ }
+ else if(0 == what) {
+ failf(conn->data, "schannel: timed out sending data "
+ "(bytes sent: %zd)", written);
+ *err = CURLE_OPERATION_TIMEDOUT;
+ written = -1;
+ break;
+ }
+ /* socket is writable */
+
+ result = Curl_write_plain(conn, conn->sock[sockindex], data + written,
+ len - written, &this_write);
+ if(result == CURLE_AGAIN)
+ continue;
+ else if(result != CURLE_OK) {
+ *err = result;
+ written = -1;
+ break;
+ }
+
+ written += this_write;
+ }
+ }
+ else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) {
+ *err = CURLE_OUT_OF_MEMORY;
+ }
+ else{
+ *err = CURLE_SEND_ERROR;
+ }
+
+ Curl_safefree(data);
+
+ if(len == (size_t)written)
+ /* Encrypted message including header, data and trailer entirely sent.
+ The return value is the number of unencrypted bytes that were sent. */
+ written = outbuf[1].cbBuffer;
+
+ return written;
+}
+
+static ssize_t
+schannel_recv(struct connectdata *conn, int sockindex,
+ char *buf, size_t len, CURLcode *err)
+{
+ size_t size = 0;
+ ssize_t nread = 0, ret = -1;
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ unsigned char *reallocated_buffer;
+ size_t reallocated_length;
+ bool done = FALSE;
+ SecBuffer inbuf[4];
+ SecBufferDesc inbuf_desc;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+
+ infof(data, "schannel: client wants to read %zu bytes\n", len);
+ *err = CURLE_OK;
+
+ /* buffer to store previously received and decrypted data */
+ if(connssl->decdata_buffer == NULL) {
+ connssl->decdata_offset = 0;
+ connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ connssl->decdata_buffer = malloc(connssl->decdata_length);
+ if(connssl->decdata_buffer == NULL) {
+ failf(data, "schannel: unable to allocate memory");
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ }
+
+ /* increase buffer in order to fit the requested amount of data */
+ if(connssl->encdata_length - connssl->encdata_offset <
+ CURL_SCHANNEL_BUFFER_FREE_SIZE || connssl->encdata_length < len) {
+ /* increase internal encrypted data buffer */
+ reallocated_length = connssl->encdata_offset +
+ CURL_SCHANNEL_BUFFER_FREE_SIZE;
+ /* make sure that the requested amount of data fits */
+ if(reallocated_length < len) {
+ reallocated_length = len;
+ }
+ reallocated_buffer = realloc(connssl->encdata_buffer,
+ reallocated_length);
+
+ if(reallocated_buffer == NULL) {
+ failf(data, "schannel: unable to re-allocate memory");
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ else {
+ connssl->encdata_buffer = reallocated_buffer;
+ connssl->encdata_length = reallocated_length;
+ }
+ }
+
+ /* read encrypted data from socket */
+ infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+ size = connssl->encdata_length - connssl->encdata_offset;
+ if(size > 0) {
+ *err = Curl_read_plain(conn->sock[sockindex],
+ (char *) (connssl->encdata_buffer + connssl->encdata_offset),
+ size, &nread);
+ /* check for received data */
+ if(*err != CURLE_OK)
+ ret = -1;
+ else {
+ if(nread > 0)
+ /* increase encrypted data buffer offset */
+ connssl->encdata_offset += nread;
+ ret = nread;
+ }
+ infof(data, "schannel: encrypted data got %zd\n", ret);
+ }
+
+ infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+
+ /* check if we still have some data in our buffers */
+ while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK &&
+ connssl->decdata_offset < len) {
+ /* prepare data buffer for DecryptMessage call */
+ InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer,
+ curlx_uztoul(connssl->encdata_offset));
+
+ /* we need 3 more empty input buffers for possible output */
+ InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
+
+ InitSecBufferDesc(&inbuf_desc, inbuf, 4);
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx */
+ sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle,
+ &inbuf_desc, 0, NULL);
+
+ /* check if we need more data */
+ if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+ infof(data, "schannel: failed to decrypt data, need more data\n");
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+
+ /* check if everything went fine (server may want to renegotiate
+ or shutdown the connection context) */
+ if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE ||
+ sspi_status == SEC_I_CONTEXT_EXPIRED) {
+ /* check for successfully decrypted data, even before actual
+ renegotiation or shutdown of the connection context */
+ if(inbuf[1].BufferType == SECBUFFER_DATA) {
+ infof(data, "schannel: decrypted data length: %lu\n",
+ inbuf[1].cbBuffer);
+
+ /* increase buffer in order to fit the received amount of data */
+ size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
+ inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
+ if(connssl->decdata_length - connssl->decdata_offset < size ||
+ connssl->decdata_length < len) {
+ /* increase internal decrypted data buffer */
+ reallocated_length = connssl->decdata_offset + size;
+ /* make sure that the requested amount of data fits */
+ if(reallocated_length < len) {
+ reallocated_length = len;
+ }
+ reallocated_buffer = realloc(connssl->decdata_buffer,
+ reallocated_length);
+
+ if(reallocated_buffer == NULL) {
+ failf(data, "schannel: unable to re-allocate memory");
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ else {
+ connssl->decdata_buffer = reallocated_buffer;
+ connssl->decdata_length = reallocated_length;
+ }
+ }
+
+ /* copy decrypted data to internal buffer */
+ size = inbuf[1].cbBuffer;
+ if(size > 0) {
+ memcpy(connssl->decdata_buffer + connssl->decdata_offset,
+ inbuf[1].pvBuffer, size);
+ connssl->decdata_offset += size;
+ }
+
+ infof(data, "schannel: decrypted data added: %zu\n", size);
+ infof(data, "schannel: decrypted data cached: offset %zu length %zu\n",
+ connssl->decdata_offset, connssl->decdata_length);
+ }
+
+ /* check for remaining encrypted data */
+ if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
+ infof(data, "schannel: encrypted data length: %lu\n",
+ inbuf[3].cbBuffer);
+
+ /* check if the remaining data is less than the total amount
+ * and therefore begins after the already processed data
+ */
+ if(connssl->encdata_offset > inbuf[3].cbBuffer) {
+ /* move remaining encrypted data forward to the beginning of
+ buffer */
+ memmove(connssl->encdata_buffer,
+ (connssl->encdata_buffer + connssl->encdata_offset) -
+ inbuf[3].cbBuffer, inbuf[3].cbBuffer);
+ connssl->encdata_offset = inbuf[3].cbBuffer;
+ }
+
+ infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+ }
+ else{
+ /* reset encrypted buffer offset, because there is no data remaining */
+ connssl->encdata_offset = 0;
+ }
+ }
+
+ /* check if server wants to renegotiate the connection context */
+ if(sspi_status == SEC_I_RENEGOTIATE) {
+ infof(data, "schannel: remote party requests SSL/TLS renegotiation\n");
+
+ /* begin renegotiation */
+ infof(data, "schannel: renegotiating SSL/TLS connection\n");
+ connssl->state = ssl_connection_negotiating;
+ connssl->connecting_state = ssl_connect_2_writing;
+ result = schannel_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ *err = result;
+ else {
+ infof(data, "schannel: SSL/TLS connection renegotiated\n");
+ /* now retry receiving data */
+ return schannel_recv(conn, sockindex, buf, len, err);
+ }
+ }
+ }
+
+ infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
+ connssl->decdata_offset, connssl->decdata_length);
+
+ /* copy requested decrypted data to supplied buffer */
+ size = len < connssl->decdata_offset ? len : connssl->decdata_offset;
+ if(size > 0) {
+ memcpy(buf, connssl->decdata_buffer, size);
+ ret = size;
+
+ /* move remaining decrypted data forward to the beginning of buffer */
+ memmove(connssl->decdata_buffer, connssl->decdata_buffer + size,
+ connssl->decdata_offset - size);
+ connssl->decdata_offset -= size;
+
+ infof(data, "schannel: decrypted data returned %zd\n", size);
+ infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
+ connssl->decdata_offset, connssl->decdata_length);
+ }
+ else
+ ret = 0;
+
+ /* check if the server closed the connection */
+ if(ret <= 0 && ( /* special check for Windows 2000 Professional */
+ sspi_status == SEC_I_CONTEXT_EXPIRED || (sspi_status == SEC_E_OK &&
+ connssl->encdata_offset > 0 && connssl->encdata_buffer[0] == 0x15))) {
+ infof(data, "schannel: server closed the connection\n");
+ *err = CURLE_OK;
+ return 0;
+ }
+
+ /* check if something went wrong and we need to return an error */
+ if(ret < 0 && sspi_status != SEC_E_OK) {
+ infof(data, "schannel: failed to read data from server: %s\n",
+ Curl_sspi_strerror(conn, sspi_status));
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ return ret;
+}
+
+CURL_STATIC CURLcode
+Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ return schannel_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURL_STATIC CURLcode
+Curl_schannel_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = schannel_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+CURL_STATIC bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->use) /* SSL/TLS is in use */
+ return (connssl->encdata_offset > 0 ||
+ connssl->decdata_offset > 0 ) ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+CURL_STATIC void Curl_schannel_close(struct connectdata *conn, int sockindex)
+{
+ if(conn->ssl[sockindex].use)
+ /* if the SSL/TLS channel hasn't been shut down yet, do that now. */
+ Curl_ssl_shutdown(conn, sockindex);
+}
+
+CURL_STATIC int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
+{
+ /* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
+ * Shutting Down an Schannel Connection
+ */
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
+ conn->host.name, conn->remote_port);
+
+ if(connssl->cred && connssl->ctxt) {
+ SecBufferDesc BuffDesc;
+ SecBuffer Buffer;
+ SECURITY_STATUS sspi_status;
+ SecBuffer outbuf;
+ SecBufferDesc outbuf_desc;
+ CURLcode result;
+ TCHAR *host_name;
+ DWORD dwshut = SCHANNEL_SHUTDOWN;
+
+ InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
+ InitSecBufferDesc(&BuffDesc, &Buffer, 1);
+
+ sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle,
+ &BuffDesc);
+
+ if(sspi_status != SEC_E_OK)
+ failf(data, "schannel: ApplyControlToken failure: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+
+ host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ if(!host_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* setup output buffer */
+ InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
+
+ sspi_status = s_pSecFn->InitializeSecurityContext(
+ &connssl->cred->cred_handle,
+ &connssl->ctxt->ctxt_handle,
+ host_name,
+ connssl->req_flags,
+ 0,
+ 0,
+ NULL,
+ 0,
+ &connssl->ctxt->ctxt_handle,
+ &outbuf_desc,
+ &connssl->ret_flags,
+ &connssl->ctxt->time_stamp);
+
+ Curl_unicodefree(host_name);
+
+ if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
+ /* send close message which is in output buffer */
+ ssize_t written;
+ result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ outbuf.cbBuffer, &written);
+
+ s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
+ if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
+ infof(data, "schannel: failed to send close msg: %s"
+ " (bytes written: %zd)\n", curl_easy_strerror(result), written);
+ }
+ }
+ }
+
+ /* free SSPI Schannel API security context handle */
+ if(connssl->ctxt) {
+ infof(data, "schannel: clear security context handle\n");
+ s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
+ Curl_safefree(connssl->ctxt);
+ }
+
+ /* free SSPI Schannel API credential handle */
+ if(connssl->cred) {
+ /* decrement the reference counter of the credential/session handle */
+ if(connssl->cred->refcount > 0) {
+ connssl->cred->refcount--;
+ infof(data, "schannel: decremented credential handle refcount = %d\n",
+ connssl->cred->refcount);
+ }
+
+ /* if the handle was not cached and the refcount is zero */
+ if(!connssl->cred->cached && connssl->cred->refcount == 0) {
+ infof(data, "schannel: clear credential handle\n");
+ s_pSecFn->FreeCredentialsHandle(&connssl->cred->cred_handle);
+ Curl_safefree(connssl->cred);
+ }
+ }
+
+ /* free internal buffer for received encrypted data */
+ if(connssl->encdata_buffer != NULL) {
+ Curl_safefree(connssl->encdata_buffer);
+ connssl->encdata_length = 0;
+ connssl->encdata_offset = 0;
+ }
+
+ /* free internal buffer for received decrypted data */
+ if(connssl->decdata_buffer != NULL) {
+ Curl_safefree(connssl->decdata_buffer);
+ connssl->decdata_length = 0;
+ connssl->decdata_offset = 0;
+ }
+
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_schannel_session_free(void *ptr)
+{
+ struct curl_schannel_cred *cred = ptr;
+
+ if(cred && cred->cached) {
+ if(cred->refcount == 0) {
+ s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+ Curl_safefree(cred);
+ }
+ else {
+ cred->cached = FALSE;
+ }
+ }
+}
+
+CURL_STATIC int Curl_schannel_init(void)
+{
+ return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
+}
+
+CURL_STATIC void Curl_schannel_cleanup(void)
+{
+ Curl_sspi_global_cleanup();
+}
+
+CURL_STATIC size_t Curl_schannel_version(char *buffer, size_t size)
+{
+ size = snprintf(buffer, size, "WinSSL");
+
+ return size;
+}
+
+CURL_STATIC int Curl_schannel_random(unsigned char *entropy, size_t length)
+{
+ HCRYPTPROV hCryptProv = 0;
+
+ if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ return 1;
+
+ if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
+ CryptReleaseContext(hCryptProv, 0UL);
+ return 1;
+ }
+
+ CryptReleaseContext(hCryptProv, 0UL);
+ return 0;
+}
+
+#ifdef _WIN32_WCE
+static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+{
+ SECURITY_STATUS status;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode result = CURLE_OK;
+ CERT_CONTEXT *pCertContextServer = NULL;
+ const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+
+ status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
+
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_PARA ChainPara;
+ memset(&ChainPara, 0, sizeof(ChainPara));
+ ChainPara.cbSize = sizeof(ChainPara);
+
+ if(!CertGetCertificateChain(NULL,
+ pCertContextServer,
+ NULL,
+ pCertContextServer->hCertStore,
+ &ChainPara,
+ 0,
+ NULL,
+ &pChainContext)) {
+ failf(data, "schannel: CertGetCertificateChain failed: %s",
+ Curl_sspi_strerror(conn, GetLastError()));
+ pChainContext = NULL;
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK) {
+ CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
+ DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED|
+ CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
+ dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
+ if(dwTrustErrorMask) {
+ if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_PARTIAL_CHAIN");
+ if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_UNTRUSTED_ROOT");
+ if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_NOT_TIME_VALID");
+ failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+ dwTrustErrorMask);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(data->set.ssl.verifyhost) {
+ TCHAR cert_hostname_buff[128];
+ xcharp_u hostname;
+ xcharp_u cert_hostname;
+ DWORD len;
+
+ cert_hostname.const_tchar_ptr = cert_hostname_buff;
+ hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);
+
+ len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ 0,
+ NULL,
+ cert_hostname.tchar_ptr,
+ 128);
+ if(len > 0 && *cert_hostname.tchar_ptr == '*') {
+ /* this is a wildcard cert. try matching the last len - 1 chars */
+ int hostname_len = strlen(conn->host.name);
+ cert_hostname.tchar_ptr++;
+ if(_tcsicmp(cert_hostname.const_tchar_ptr,
+ hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr,
+ cert_hostname.const_tchar_ptr) != 0) {
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ if(result == CURLE_PEER_FAILED_VERIFICATION) {
+ char *_cert_hostname;
+ _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr);
+ failf(data, "schannel: CertGetNameString() certificate hostname "
+ "(%s) did not match connection (%s)",
+ _cert_hostname, conn->host.name);
+ Curl_unicodefree(_cert_hostname);
+ }
+ Curl_unicodefree(hostname.tchar_ptr);
+ }
+ }
+
+ if(pChainContext)
+ CertFreeCertificateChain(pChainContext);
+
+ if(pCertContextServer)
+ CertFreeCertificateContext(pCertContextServer);
+
+ return result;
+}
+#endif /* _WIN32_WCE */
+
+#endif /* USE_SCHANNEL */
diff --git a/libcurl/src/lib/vtls/schannel.h b/libcurl/src/lib/vtls/schannel.h
new file mode 100644
index 0000000..e48dd97
--- /dev/null
+++ b/libcurl/src/lib/vtls/schannel.h
@@ -0,0 +1,117 @@
+#ifndef HEADER_CURL_SCHANNEL_H
+#define HEADER_CURL_SCHANNEL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
+ * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#include "../urldata.h"
+
+#ifndef UNISP_NAME_A
+#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME_W
+#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME
+#ifdef UNICODE
+#define UNISP_NAME UNISP_NAME_W
+#else
+#define UNISP_NAME UNISP_NAME_A
+#endif
+#endif
+
+#ifndef SP_PROT_SSL2_CLIENT
+#define SP_PROT_SSL2_CLIENT 0x00000008
+#endif
+
+#ifndef SP_PROT_SSL3_CLIENT
+#define SP_PROT_SSL3_CLIENT 0x00000008
+#endif
+
+#ifndef SP_PROT_TLS1_CLIENT
+#define SP_PROT_TLS1_CLIENT 0x00000080
+#endif
+
+#ifndef SP_PROT_TLS1_0_CLIENT
+#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
+#endif
+
+#ifndef SP_PROT_TLS1_1_CLIENT
+#define SP_PROT_TLS1_1_CLIENT 0x00000200
+#endif
+
+#ifndef SP_PROT_TLS1_2_CLIENT
+#define SP_PROT_TLS1_2_CLIENT 0x00000800
+#endif
+
+#ifndef SECBUFFER_ALERT
+#define SECBUFFER_ALERT 17
+#endif
+
+#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
+#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
+
+
+CURL_STATIC CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex);
+
+CURL_STATIC CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+CURL_STATIC bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex);
+CURL_STATIC void Curl_schannel_close(struct connectdata *conn, int sockindex);
+CURL_STATIC int Curl_schannel_shutdown(struct connectdata *conn, int sockindex);
+CURL_STATIC void Curl_schannel_session_free(void *ptr);
+
+CURL_STATIC int Curl_schannel_init(void);
+CURL_STATIC void Curl_schannel_cleanup(void);
+CURL_STATIC size_t Curl_schannel_version(char *buffer, size_t size);
+
+CURL_STATIC int Curl_schannel_random(unsigned char *entropy, size_t length);
+
+/* Set the API backend definition to Schannel */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
+
+/* API setup for Schannel */
+#define curlssl_init Curl_schannel_init
+#define curlssl_cleanup Curl_schannel_cleanup
+#define curlssl_connect Curl_schannel_connect
+#define curlssl_connect_nonblocking Curl_schannel_connect_nonblocking
+#define curlssl_session_free Curl_schannel_session_free
+#define curlssl_close_all(x) ((void)x)
+#define curlssl_close Curl_schannel_close
+#define curlssl_shutdown Curl_schannel_shutdown
+#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_schannel_version
+#define curlssl_check_cxn(x) ((void)x, -1)
+#define curlssl_data_pending Curl_schannel_data_pending
+#define curlssl_random(x,y,z) ((void)x, Curl_schannel_random(y,z))
+
+#endif /* USE_SCHANNEL */
+#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/libcurl/src/lib/vtls/vtls.c b/libcurl/src/lib/vtls/vtls.c
new file mode 100644
index 0000000..b7f7059
--- /dev/null
+++ b/libcurl/src/lib/vtls/vtls.c
@@ -0,0 +1,895 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This file is for implementing all "generic" SSL functions that all libcurl
+ internals should use. It is then responsible for calling the proper
+ "backend" function.
+
+ SSL-functions in libcurl should call functions in this source file, and not
+ to any specific SSL-layer.
+
+ Curl_ssl_ - prefix for generic ones
+ Curl_ossl_ - prefix for OpenSSL ones
+ Curl_gtls_ - prefix for GnuTLS ones
+ Curl_nss_ - prefix for NSS ones
+ Curl_gskit_ - prefix for GSKit ones
+ Curl_polarssl_ - prefix for PolarSSL ones
+ Curl_cyassl_ - prefix for CyaSSL ones
+ Curl_schannel_ - prefix for Schannel SSPI ones
+ Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones
+
+ Note that this source code uses curlssl_* functions, and they are all
+ defines/macros #defined by the lib-specific header files.
+
+ "SSL/TLS Strong Encryption: An Introduction"
+ http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html
+*/
+
+#include "../curl_setup.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "../urldata.h"
+
+#include "vtls.h" /* generic SSL protos etc */
+#include "../slist.h"
+#include "../sendf.h"
+#include "../rawstr.h"
+#include "../url.h"
+#include "../progress.h"
+#include "../share.h"
+#include "../timeval.h"
+#include "../curl_md5.h"
+#include "../warnless.h"
+#include "../curl_base64.h"
+#include "../curl_printf.h"
+
+/* The last #include files should be: */
+#include "../curl_memory.h"
+#include "../memdebug.h"
+
+/* convenience macro to check if this handle is using a shared SSL session */
+#define SSLSESSION_SHARED(data) (data->share && \
+ (data->share->specifier & \
+ (1<<CURL_LOCK_DATA_SSL_SESSION)))
+
+static bool safe_strequal(char* str1, char* str2)
+{
+ if(str1 && str2)
+ /* both pointers point to something then compare them */
+ return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE;
+ else
+ /* if both pointers are NULL then treat them as equal */
+ return (!str1 && !str2) ? TRUE : FALSE;
+}
+
+CURL_STATIC bool
+Curl_ssl_config_matches(struct ssl_config_data* data,
+ struct ssl_config_data* needle)
+{
+ if((data->version == needle->version) &&
+ (data->verifypeer == needle->verifypeer) &&
+ (data->verifyhost == needle->verifyhost) &&
+ safe_strequal(data->CApath, needle->CApath) &&
+ safe_strequal(data->CAfile, needle->CAfile) &&
+ safe_strequal(data->random_file, needle->random_file) &&
+ safe_strequal(data->egdsocket, needle->egdsocket) &&
+ safe_strequal(data->cipher_list, needle->cipher_list))
+ return TRUE;
+
+ return FALSE;
+}
+
+CURL_STATIC bool
+Curl_clone_ssl_config(struct ssl_config_data *source,
+ struct ssl_config_data *dest)
+{
+ dest->sessionid = source->sessionid;
+ dest->verifyhost = source->verifyhost;
+ dest->verifypeer = source->verifypeer;
+ dest->version = source->version;
+
+ if(source->CAfile) {
+ dest->CAfile = strdup(source->CAfile);
+ if(!dest->CAfile)
+ return FALSE;
+ }
+ else
+ dest->CAfile = NULL;
+
+ if(source->CApath) {
+ dest->CApath = strdup(source->CApath);
+ if(!dest->CApath)
+ return FALSE;
+ }
+ else
+ dest->CApath = NULL;
+
+ if(source->cipher_list) {
+ dest->cipher_list = strdup(source->cipher_list);
+ if(!dest->cipher_list)
+ return FALSE;
+ }
+ else
+ dest->cipher_list = NULL;
+
+ if(source->egdsocket) {
+ dest->egdsocket = strdup(source->egdsocket);
+ if(!dest->egdsocket)
+ return FALSE;
+ }
+ else
+ dest->egdsocket = NULL;
+
+ if(source->random_file) {
+ dest->random_file = strdup(source->random_file);
+ if(!dest->random_file)
+ return FALSE;
+ }
+ else
+ dest->random_file = NULL;
+
+ return TRUE;
+}
+
+CURL_STATIC void Curl_free_ssl_config(struct ssl_config_data* sslc)
+{
+ Curl_safefree(sslc->CAfile);
+ Curl_safefree(sslc->CApath);
+ Curl_safefree(sslc->cipher_list);
+ Curl_safefree(sslc->egdsocket);
+ Curl_safefree(sslc->random_file);
+}
+
+
+/*
+ * Curl_rand() returns a random unsigned integer, 32bit.
+ *
+ * This non-SSL function is put here only because this file is the only one
+ * with knowledge of what the underlying SSL libraries provide in terms of
+ * randomizers.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+
+CURL_STATIC unsigned int Curl_rand(struct SessionHandle *data)
+{
+ unsigned int r = 0;
+ static unsigned int randseed;
+ static bool seeded = FALSE;
+
+#ifdef CURLDEBUG
+ char *force_entropy = getenv("CURL_ENTROPY");
+ if(force_entropy) {
+ if(!seeded) {
+ size_t elen = strlen(force_entropy);
+ size_t clen = sizeof(randseed);
+ size_t min = elen < clen ? elen : clen;
+ memcpy((char *)&randseed, force_entropy, min);
+ seeded = TRUE;
+ }
+ else
+ randseed++;
+ return randseed;
+ }
+#endif
+
+ /* data may be NULL! */
+ if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)))
+ return r;
+
+ /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we
+ instead perform a "best effort" */
+
+#ifdef RANDOM_FILE
+ if(!seeded) {
+ /* if there's a random file to read a seed from, use it */
+ int fd = open(RANDOM_FILE, O_RDONLY);
+ if(fd > -1) {
+ /* read random data into the randseed variable */
+ ssize_t nread = read(fd, &randseed, sizeof(randseed));
+ if(nread == sizeof(randseed))
+ seeded = TRUE;
+ close(fd);
+ }
+ }
+#endif
+
+ if(!seeded) {
+ struct timeval now = curlx_tvnow();
+ infof(data, "WARNING: Using weak random seed\n");
+ randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
+ randseed = randseed * 1103515245 + 12345;
+ randseed = randseed * 1103515245 + 12345;
+ randseed = randseed * 1103515245 + 12345;
+ seeded = TRUE;
+ }
+
+ /* Return an unsigned 32-bit pseudo-random number. */
+ r = randseed = randseed * 1103515245 + 12345;
+ return (r << 16) | ((r >> 16) & 0xFFFF);
+}
+
+CURL_STATIC int Curl_ssl_backend(void)
+{
+ return (int)CURL_SSL_BACKEND;
+}
+
+#ifdef USE_SSL
+
+/* "global" init done? */
+static bool init_ssl=FALSE;
+
+/**
+ * Global SSL init
+ *
+ * @retval 0 error initializing SSL
+ * @retval 1 SSL initialized successfully
+ */
+CURL_STATIC int Curl_ssl_init(void)
+{
+ /* make sure this is only done once */
+ if(init_ssl)
+ return 1;
+ init_ssl = TRUE; /* never again */
+
+ return curlssl_init();
+}
+
+
+/* Global cleanup */
+CURL_STATIC void Curl_ssl_cleanup(void)
+{
+ if(init_ssl) {
+ /* only cleanup if we did a previous init */
+ curlssl_cleanup();
+ init_ssl = FALSE;
+ }
+}
+
+static bool ssl_prefs_check(struct SessionHandle *data)
+{
+ /* check for CURLOPT_SSLVERSION invalid parameter value */
+ if((data->set.ssl.version < 0)
+ || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) {
+ failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+CURL_STATIC CURLcode
+Curl_ssl_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode result;
+
+ if(!ssl_prefs_check(conn->data))
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* mark this is being ssl-enabled from here on. */
+ conn->ssl[sockindex].use = TRUE;
+ conn->ssl[sockindex].state = ssl_connection_negotiating;
+
+ result = curlssl_connect(conn, sockindex);
+
+ if(!result)
+ Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+
+ return result;
+}
+
+CURL_STATIC CURLcode
+Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ CURLcode result;
+
+ if(!ssl_prefs_check(conn->data))
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* mark this is being ssl requested from here on. */
+ conn->ssl[sockindex].use = TRUE;
+#ifdef curlssl_connect_nonblocking
+ result = curlssl_connect_nonblocking(conn, sockindex, done);
+#else
+ *done = TRUE; /* fallback to BLOCKING */
+ result = curlssl_connect(conn, sockindex);
+#endif /* non-blocking connect support */
+ if(!result && *done)
+ Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+ return result;
+}
+
+/*
+ * Check if there's a session ID for the given connection in the cache, and if
+ * there's one suitable, it is provided. Returns TRUE when no entry matched.
+ */
+CURL_STATIC bool Curl_ssl_getsessionid(struct connectdata *conn,
+ void **ssl_sessionid,
+ size_t *idsize) /* set 0 if unknown */
+{
+ struct curl_ssl_session *check;
+ struct SessionHandle *data = conn->data;
+ size_t i;
+ long *general_age;
+ bool no_match = TRUE;
+
+ *ssl_sessionid = NULL;
+
+ if(!conn->ssl_config.sessionid)
+ /* session ID re-use is disabled */
+ return TRUE;
+
+ /* Lock if shared */
+ if(SSLSESSION_SHARED(data)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+ general_age = &data->share->sessionage;
+ }
+ else
+ general_age = &data->state.sessionage;
+
+ for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+ check = &data->state.session[i];
+ if(!check->sessionid)
+ /* not session ID means blank entry */
+ continue;
+ if(Curl_raw_equal(conn->host.name, check->name) &&
+ (conn->remote_port == check->remote_port) &&
+ Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
+ /* yes, we have a session ID! */
+ (*general_age)++; /* increase general age */
+ check->age = *general_age; /* set this as used in this age */
+ *ssl_sessionid = check->sessionid;
+ if(idsize)
+ *idsize = check->idsize;
+ no_match = FALSE;
+ break;
+ }
+ }
+
+ /* Unlock */
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
+ return no_match;
+}
+
+/*
+ * Kill a single session ID entry in the cache.
+ */
+CURL_STATIC void Curl_ssl_kill_session(struct curl_ssl_session *session)
+{
+ if(session->sessionid) {
+ /* defensive check */
+
+ /* free the ID the SSL-layer specific way */
+ curlssl_session_free(session->sessionid);
+
+ session->sessionid = NULL;
+ session->age = 0; /* fresh */
+
+ Curl_free_ssl_config(&session->ssl_config);
+
+ Curl_safefree(session->name);
+ }
+}
+
+/*
+ * Delete the given session ID from the cache.
+ */
+CURL_STATIC void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
+{
+ size_t i;
+ struct SessionHandle *data=conn->data;
+
+ if(SSLSESSION_SHARED(data))
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+
+ for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+ struct curl_ssl_session *check = &data->state.session[i];
+
+ if(check->sessionid == ssl_sessionid) {
+ Curl_ssl_kill_session(check);
+ break;
+ }
+ }
+
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+}
+
+/*
+ * Store session id in the session cache. The ID passed on to this function
+ * must already have been extracted and allocated the proper way for the SSL
+ * layer. Curl_XXXX_session_free() will be called to free/kill the session ID
+ * later on.
+ */
+CURL_STATIC CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+ void *ssl_sessionid,
+ size_t idsize)
+{
+ size_t i;
+ struct SessionHandle *data=conn->data; /* the mother of all structs */
+ struct curl_ssl_session *store = &data->state.session[0];
+ long oldest_age=data->state.session[0].age; /* zero if unused */
+ char *clone_host;
+ long *general_age;
+
+ /* Even though session ID re-use might be disabled, that only disables USING
+ IT. We still store it here in case the re-using is again enabled for an
+ upcoming transfer */
+
+ clone_host = strdup(conn->host.name);
+ if(!clone_host)
+ return CURLE_OUT_OF_MEMORY; /* bail out */
+
+ /* Now we should add the session ID and the host name to the cache, (remove
+ the oldest if necessary) */
+
+ /* If using shared SSL session, lock! */
+ if(SSLSESSION_SHARED(data)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+ general_age = &data->share->sessionage;
+ }
+ else {
+ general_age = &data->state.sessionage;
+ }
+
+ /* find an empty slot for us, or find the oldest */
+ for(i = 1; (i < data->set.ssl.max_ssl_sessions) &&
+ data->state.session[i].sessionid; i++) {
+ if(data->state.session[i].age < oldest_age) {
+ oldest_age = data->state.session[i].age;
+ store = &data->state.session[i];
+ }
+ }
+ if(i == data->set.ssl.max_ssl_sessions)
+ /* cache is full, we must "kill" the oldest entry! */
+ Curl_ssl_kill_session(store);
+ else
+ store = &data->state.session[i]; /* use this slot */
+
+ /* now init the session struct wisely */
+ store->sessionid = ssl_sessionid;
+ store->idsize = idsize;
+ store->age = *general_age; /* set current age */
+ /* free it if there's one already present */
+ free(store->name);
+ store->name = clone_host; /* clone host name */
+ store->remote_port = conn->remote_port; /* port number */
+
+
+ /* Unlock */
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
+ if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
+ store->sessionid = NULL; /* let caller free sessionid */
+ free(clone_host);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ return CURLE_OK;
+}
+
+
+CURL_STATIC void Curl_ssl_close_all(struct SessionHandle *data)
+{
+ size_t i;
+ /* kill the session ID cache if not shared */
+ if(data->state.session && !SSLSESSION_SHARED(data)) {
+ for(i = 0; i < data->set.ssl.max_ssl_sessions; i++)
+ /* the single-killer function handles empty table slots */
+ Curl_ssl_kill_session(&data->state.session[i]);
+
+ /* free the cache data */
+ Curl_safefree(data->state.session);
+ }
+
+ curlssl_close_all(data);
+}
+
+CURL_STATIC void Curl_ssl_close(struct connectdata *conn, int sockindex)
+{
+ DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
+ curlssl_close(conn, sockindex);
+}
+
+CURL_STATIC CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
+{
+ if(curlssl_shutdown(conn, sockindex))
+ return CURLE_SSL_SHUTDOWN_FAILED;
+
+ conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
+ conn->ssl[sockindex].state = ssl_connection_none;
+
+ conn->recv[sockindex] = Curl_recv_plain;
+ conn->send[sockindex] = Curl_send_plain;
+
+ return CURLE_OK;
+}
+
+/* Selects an SSL crypto engine
+ */
+CURL_STATIC CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
+{
+ return curlssl_set_engine(data, engine);
+}
+
+/* Selects the default SSL crypto engine
+ */
+CURL_STATIC CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
+{
+ return curlssl_set_engine_default(data);
+}
+
+/* Return list of OpenSSL crypto engine names. */
+CURL_STATIC struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
+{
+ return curlssl_engines_list(data);
+}
+
+/*
+ * This sets up a session ID cache to the specified size. Make sure this code
+ * is agnostic to what underlying SSL technology we use.
+ */
+CURL_STATIC CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount)
+{
+ struct curl_ssl_session *session;
+
+ if(data->state.session)
+ /* this is just a precaution to prevent multiple inits */
+ return CURLE_OK;
+
+ session = calloc(amount, sizeof(struct curl_ssl_session));
+ if(!session)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* store the info in the SSL section */
+ data->set.ssl.max_ssl_sessions = amount;
+ data->state.session = session;
+ data->state.sessionage = 1; /* this is brand new */
+ return CURLE_OK;
+}
+
+CURL_STATIC size_t Curl_ssl_version(char *buffer, size_t size)
+{
+ return curlssl_version(buffer, size);
+}
+
+/*
+ * This function tries to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+CURL_STATIC int Curl_ssl_check_cxn(struct connectdata *conn)
+{
+ return curlssl_check_cxn(conn);
+}
+
+CURL_STATIC bool Curl_ssl_data_pending(const struct connectdata *conn,
+ int connindex)
+{
+ return curlssl_data_pending(conn, connindex);
+}
+
+CURL_STATIC void Curl_ssl_free_certinfo(struct SessionHandle *data)
+{
+ int i;
+ struct curl_certinfo *ci = &data->info.certs;
+
+ if(ci->num_of_certs) {
+ /* free all individual lists used */
+ for(i=0; i<ci->num_of_certs; i++) {
+ curl_slist_free_all(ci->certinfo[i]);
+ ci->certinfo[i] = NULL;
+ }
+
+ free(ci->certinfo); /* free the actual array too */
+ ci->certinfo = NULL;
+ ci->num_of_certs = 0;
+ }
+}
+
+CURL_STATIC CURLcode Curl_ssl_init_certinfo(struct SessionHandle *data, int num)
+{
+ struct curl_certinfo *ci = &data->info.certs;
+ struct curl_slist **table;
+
+ /* Free any previous certificate information structures */
+ Curl_ssl_free_certinfo(data);
+
+ /* Allocate the required certificate information structures */
+ table = calloc((size_t) num, sizeof(struct curl_slist *));
+ if(!table)
+ return CURLE_OUT_OF_MEMORY;
+
+ ci->num_of_certs = num;
+ ci->certinfo = table;
+
+ return CURLE_OK;
+}
+
+/*
+ * 'value' is NOT a zero terminated string
+ */
+CURL_STATIC CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
+ int certnum,
+ const char *label,
+ const char *value,
+ size_t valuelen)
+{
+ struct curl_certinfo * ci = &data->info.certs;
+ char * output;
+ struct curl_slist * nl;
+ CURLcode result = CURLE_OK;
+ size_t labellen = strlen(label);
+ size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
+
+ output = malloc(outlen);
+ if(!output)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* sprintf the label and colon */
+ snprintf(output, outlen, "%s:", label);
+
+ /* memcpy the value (it might not be zero terminated) */
+ memcpy(&output[labellen+1], value, valuelen);
+
+ /* zero terminate the output */
+ output[labellen + 1 + valuelen] = 0;
+
+ nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
+ if(!nl) {
+ free(output);
+ curl_slist_free_all(ci->certinfo[certnum]);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ ci->certinfo[certnum] = nl;
+ return result;
+}
+
+/*
+ * This is a convenience function for push_certinfo_len that takes a zero
+ * terminated value.
+ */
+CURL_STATIC CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data,
+ int certnum,
+ const char *label,
+ const char *value)
+{
+ size_t valuelen = strlen(value);
+
+ return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
+}
+
+CURL_STATIC int Curl_ssl_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ return curlssl_random(data, entropy, length);
+}
+
+/*
+ * Public key pem to der conversion
+ */
+
+static CURLcode pubkey_pem_to_der(const char *pem,
+ unsigned char **der, size_t *der_len)
+{
+ char *stripped_pem, *begin_pos, *end_pos;
+ size_t pem_count, stripped_pem_count = 0, pem_len;
+ CURLcode result;
+
+ /* if no pem, exit. */
+ if(!pem)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----");
+ if(!begin_pos)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ pem_count = begin_pos - pem;
+ /* Invalid if not at beginning AND not directly following \n */
+ if(0 != pem_count && '\n' != pem[pem_count - 1])
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* 26 is length of "-----BEGIN PUBLIC KEY-----" */
+ pem_count += 26;
+
+ /* Invalid if not directly following \n */
+ end_pos = strstr(pem + pem_count, "\n-----END PUBLIC KEY-----");
+ if(!end_pos)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ pem_len = end_pos - pem;
+
+ stripped_pem = malloc(pem_len - pem_count + 1);
+ if(!stripped_pem)
+ return CURLE_OUT_OF_MEMORY;
+
+ /*
+ * Here we loop through the pem array one character at a time between the
+ * correct indices, and place each character that is not '\n' or '\r'
+ * into the stripped_pem array, which should represent the raw base64 string
+ */
+ while(pem_count < pem_len) {
+ if('\n' != pem[pem_count] && '\r' != pem[pem_count])
+ stripped_pem[stripped_pem_count++] = pem[pem_count];
+ ++pem_count;
+ }
+ /* Place the null terminator in the correct place */
+ stripped_pem[stripped_pem_count] = '\0';
+
+ result = Curl_base64_decode(stripped_pem, der, der_len);
+
+ Curl_safefree(stripped_pem);
+
+ return result;
+}
+
+/*
+ * Generic pinned public key check.
+ */
+
+CURL_STATIC CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
+ const unsigned char *pubkey, size_t pubkeylen)
+{
+ FILE *fp;
+ unsigned char *buf = NULL, *pem_ptr = NULL;
+ long filesize;
+ size_t size, pem_len;
+ CURLcode pem_read;
+ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+
+ /* if a path wasn't specified, don't pin */
+ if(!pinnedpubkey)
+ return CURLE_OK;
+ if(!pubkey || !pubkeylen)
+ return result;
+ fp = fopen(pinnedpubkey, "rb");
+ if(!fp)
+ return result;
+
+ do {
+ /* Determine the file's size */
+ if(fseek(fp, 0, SEEK_END))
+ break;
+ filesize = ftell(fp);
+ if(fseek(fp, 0, SEEK_SET))
+ break;
+ if(filesize < 0 || filesize > MAX_PINNED_PUBKEY_SIZE)
+ break;
+
+ /*
+ * if the size of our certificate is bigger than the file
+ * size then it can't match
+ */
+ size = curlx_sotouz((curl_off_t) filesize);
+ if(pubkeylen > size)
+ break;
+
+ /*
+ * Allocate buffer for the pinned key
+ * With 1 additional byte for null terminator in case of PEM key
+ */
+ buf = malloc(size + 1);
+ if(!buf)
+ break;
+
+ /* Returns number of elements read, which should be 1 */
+ if((int) fread(buf, size, 1, fp) != 1)
+ break;
+
+ /* If the sizes are the same, it can't be base64 encoded, must be der */
+ if(pubkeylen == size) {
+ if(!memcmp(pubkey, buf, pubkeylen))
+ result = CURLE_OK;
+ break;
+ }
+
+ /*
+ * Otherwise we will assume it's PEM and try to decode it
+ * after placing null terminator
+ */
+ buf[size] = '\0';
+ pem_read = pubkey_pem_to_der((const char *)buf, &pem_ptr, &pem_len);
+ /* if it wasn't read successfully, exit */
+ if(pem_read)
+ break;
+
+ /*
+ * if the size of our certificate doesn't match the size of
+ * the decoded file, they can't be the same, otherwise compare
+ */
+ if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen))
+ result = CURLE_OK;
+ } while(0);
+
+ Curl_safefree(buf);
+ Curl_safefree(pem_ptr);
+ fclose(fp);
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+CURL_STATIC CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+#ifdef curlssl_md5sum
+ curlssl_md5sum(tmp, tmplen, md5sum, md5len);
+#else
+ MD5_context *MD5pw;
+
+ (void) md5len;
+
+ MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!MD5pw)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen));
+ Curl_MD5_final(MD5pw, md5sum);
+#endif
+ return CURLE_OK;
+}
+#endif
+
+/*
+ * Check whether the SSL backend supports the status_request extension.
+ */
+CURL_STATIC bool Curl_ssl_cert_status_request(void)
+{
+#ifdef curlssl_cert_status_request
+ return curlssl_cert_status_request();
+#else
+ return FALSE;
+#endif
+}
+
+/*
+ * Check whether the SSL backend supports false start.
+ */
+CURL_STATIC bool Curl_ssl_false_start(void)
+{
+#ifdef curlssl_false_start
+ return curlssl_false_start();
+#else
+ return FALSE;
+#endif
+}
+
+#endif /* USE_SSL */
diff --git a/libcurl/src/lib/vtls/vtls.h b/libcurl/src/lib/vtls/vtls.h
new file mode 100644
index 0000000..cc2503f
--- /dev/null
+++ b/libcurl/src/lib/vtls/vtls.h
@@ -0,0 +1,153 @@
+#ifndef HEADER_CURL_VTLS_H
+#define HEADER_CURL_VTLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "../curl_setup.h"
+
+#include "openssl.h" /* OpenSSL versions */
+#include "gtls.h" /* GnuTLS versions */
+#include "nssg.h" /* NSS versions */
+#include "gskit.h" /* Global Secure ToolKit versions */
+#include "polarssl.h" /* PolarSSL versions */
+#include "axtls.h" /* axTLS versions */
+#include "cyassl.h" /* CyaSSL versions */
+#include "schannel.h" /* Schannel SSPI version */
+#include "darwinssl.h" /* SecureTransport (Darwin) version */
+
+#ifndef MAX_PINNED_PUBKEY_SIZE
+#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
+#endif
+
+#ifndef MD5_DIGEST_LENGTH
+#define MD5_DIGEST_LENGTH 16 /* fixed size */
+#endif
+
+/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
+#define ALPN_HTTP_1_1_LENGTH 8
+#define ALPN_HTTP_1_1 "http/1.1"
+
+CURL_STATIC bool Curl_ssl_config_matches(struct ssl_config_data* data,
+ struct ssl_config_data* needle);
+CURL_STATIC bool Curl_clone_ssl_config(struct ssl_config_data* source,
+ struct ssl_config_data* dest);
+CURL_STATIC void Curl_free_ssl_config(struct ssl_config_data* sslc);
+
+CURL_STATIC unsigned int Curl_rand(struct SessionHandle *);
+
+CURL_STATIC int Curl_ssl_backend(void);
+
+#ifdef USE_SSL
+CURL_STATIC int Curl_ssl_init(void);
+CURL_STATIC void Curl_ssl_cleanup(void);
+CURL_STATIC CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+/* tell the SSL stuff to close down all open information regarding
+ connections (and thus session ID caching etc) */
+CURL_STATIC void Curl_ssl_close_all(struct SessionHandle *data);
+CURL_STATIC void Curl_ssl_close(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex);
+CURL_STATIC CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine);
+/* Sets engine as default for all SSL operations */
+CURL_STATIC CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data);
+CURL_STATIC struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data);
+
+/* init the SSL session ID cache */
+CURL_STATIC CURLcode Curl_ssl_initsessions(struct SessionHandle *, size_t);
+CURL_STATIC size_t Curl_ssl_version(char *buffer, size_t size);
+CURL_STATIC bool Curl_ssl_data_pending(const struct connectdata *conn,
+ int connindex);
+CURL_STATIC int Curl_ssl_check_cxn(struct connectdata *conn);
+
+/* Certificate information list handling. */
+
+CURL_STATIC void Curl_ssl_free_certinfo(struct SessionHandle *data);
+CURL_STATIC CURLcode Curl_ssl_init_certinfo(struct SessionHandle * data, int num);
+CURL_STATIC CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle * data, int certnum,
+ const char * label, const char * value,
+ size_t valuelen);
+CURL_STATIC CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum,
+ const char * label, const char * value);
+
+/* Functions to be used by SSL library adaptation functions */
+
+/* extract a session ID */
+CURL_STATIC bool Curl_ssl_getsessionid(struct connectdata *conn,
+ void **ssl_sessionid,
+ size_t *idsize) /* set 0 if unknown */;
+/* add a new session ID */
+CURL_STATIC CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+ void *ssl_sessionid,
+ size_t idsize);
+/* Kill a single session ID entry in the cache */
+CURL_STATIC void Curl_ssl_kill_session(struct curl_ssl_session *session);
+/* delete a session from the cache */
+CURL_STATIC void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
+
+/* get N random bytes into the buffer, return 0 if a find random is filled
+ in */
+CURL_STATIC int Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer,
+ size_t length);
+CURL_STATIC CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+/* Check pinned public key. */
+CURL_STATIC CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
+ const unsigned char *pubkey, size_t pubkeylen);
+
+CURL_STATIC bool Curl_ssl_cert_status_request(void);
+
+CURL_STATIC bool Curl_ssl_false_start(void);
+
+#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
+
+#else
+/* Set the API backend definition to none */
+#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE
+
+/* When SSL support is not present, just define away these function calls */
+#define Curl_ssl_init() 1
+#define Curl_ssl_cleanup() Curl_nop_stmt
+#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_close_all(x) Curl_nop_stmt
+#define Curl_ssl_close(x,y) Curl_nop_stmt
+#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
+#define Curl_ssl_engines_list(x) NULL
+#define Curl_ssl_send(a,b,c,d,e) -1
+#define Curl_ssl_recv(a,b,c,d,e) -1
+#define Curl_ssl_initsessions(x,y) CURLE_OK
+#define Curl_ssl_version(x,y) 0
+#define Curl_ssl_data_pending(x,y) 0
+#define Curl_ssl_check_cxn(x) 0
+#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
+#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN
+#define Curl_ssl_kill_session(x) Curl_nop_stmt
+#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
+#define Curl_ssl_cert_status_request() FALSE
+#define Curl_ssl_false_start() FALSE
+#endif
+
+#endif /* HEADER_CURL_VTLS_H */
diff --git a/libcurl/src/lib/warnless.c b/libcurl/src/lib/warnless.c
new file mode 100644
index 0000000..7e4415e
--- /dev/null
+++ b/libcurl/src/lib/warnless.c
@@ -0,0 +1,486 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(__INTEL_COMPILER) && defined(__unix__)
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#endif /* __INTEL_COMPILER && __unix__ */
+
+#define BUILDING_WARNLESS_C 1
+
+#include "warnless.h"
+
+#define CURL_MASK_SCHAR 0x7F
+#define CURL_MASK_UCHAR 0xFF
+
+#if (SIZEOF_SHORT == 2)
+# define CURL_MASK_SSHORT 0x7FFF
+# define CURL_MASK_USHORT 0xFFFF
+#elif (SIZEOF_SHORT == 4)
+# define CURL_MASK_SSHORT 0x7FFFFFFF
+# define CURL_MASK_USHORT 0xFFFFFFFF
+#elif (SIZEOF_SHORT == 8)
+# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF
+# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF
+#else
+# error "SIZEOF_SHORT not defined"
+#endif
+
+#if (SIZEOF_INT == 2)
+# define CURL_MASK_SINT 0x7FFF
+# define CURL_MASK_UINT 0xFFFF
+#elif (SIZEOF_INT == 4)
+# define CURL_MASK_SINT 0x7FFFFFFF
+# define CURL_MASK_UINT 0xFFFFFFFF
+#elif (SIZEOF_INT == 8)
+# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF
+# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF
+#elif (SIZEOF_INT == 16)
+# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+#else
+# error "SIZEOF_INT not defined"
+#endif
+
+#if (CURL_SIZEOF_LONG == 2)
+# define CURL_MASK_SLONG 0x7FFFL
+# define CURL_MASK_ULONG 0xFFFFUL
+#elif (CURL_SIZEOF_LONG == 4)
+# define CURL_MASK_SLONG 0x7FFFFFFFL
+# define CURL_MASK_ULONG 0xFFFFFFFFUL
+#elif (CURL_SIZEOF_LONG == 8)
+# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL
+# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL
+#elif (CURL_SIZEOF_LONG == 16)
+# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL
+# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL
+#else
+# error "CURL_SIZEOF_LONG not defined"
+#endif
+
+#if (CURL_SIZEOF_CURL_OFF_T == 2)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF)
+#elif (CURL_SIZEOF_CURL_OFF_T == 4)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF)
+#elif (CURL_SIZEOF_CURL_OFF_T == 8)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF)
+#elif (CURL_SIZEOF_CURL_OFF_T == 16)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
+#else
+# error "CURL_SIZEOF_CURL_OFF_T not defined"
+#endif
+
+#if (SIZEOF_SIZE_T == SIZEOF_SHORT)
+# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT
+# define CURL_MASK_USIZE_T CURL_MASK_USHORT
+#elif (SIZEOF_SIZE_T == SIZEOF_INT)
+# define CURL_MASK_SSIZE_T CURL_MASK_SINT
+# define CURL_MASK_USIZE_T CURL_MASK_UINT
+#elif (SIZEOF_SIZE_T == CURL_SIZEOF_LONG)
+# define CURL_MASK_SSIZE_T CURL_MASK_SLONG
+# define CURL_MASK_USIZE_T CURL_MASK_ULONG
+#elif (SIZEOF_SIZE_T == CURL_SIZEOF_CURL_OFF_T)
+# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT
+# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT
+#else
+# error "SIZEOF_SIZE_T not defined"
+#endif
+
+/*
+** unsigned long to unsigned short
+*/
+
+CURL_STATIC unsigned short curlx_ultous(unsigned long ulnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_USHORT);
+ return (unsigned short)(ulnum & (unsigned long) CURL_MASK_USHORT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned long to unsigned char
+*/
+
+CURL_STATIC unsigned char curlx_ultouc(unsigned long ulnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_UCHAR);
+ return (unsigned char)(ulnum & (unsigned long) CURL_MASK_UCHAR);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned long to signed int
+*/
+
+CURL_STATIC int curlx_ultosi(unsigned long ulnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT);
+ return (int)(ulnum & (unsigned long) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to signed curl_off_t
+*/
+
+CURL_STATIC curl_off_t curlx_uztoso(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT);
+ return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to signed int
+*/
+
+CURL_STATIC int curlx_uztosi(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_SINT);
+ return (int)(uznum & (size_t) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to unsigned long
+*/
+
+CURL_STATIC unsigned long curlx_uztoul(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+#if (CURL_SIZEOF_LONG < SIZEOF_SIZE_T)
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG);
+#endif
+ return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to unsigned int
+*/
+
+CURL_STATIC unsigned int curlx_uztoui(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+#if (SIZEOF_INT < SIZEOF_SIZE_T)
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT);
+#endif
+ return (unsigned int)(uznum & (size_t) CURL_MASK_UINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed long to signed int
+*/
+
+CURL_STATIC int curlx_sltosi(long slnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(slnum >= 0);
+#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+ DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT);
+#endif
+ return (int)(slnum & (long) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed long to unsigned int
+*/
+
+CURL_STATIC unsigned int curlx_sltoui(long slnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(slnum >= 0);
+#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+ DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT);
+#endif
+ return (unsigned int)(slnum & (long) CURL_MASK_UINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed long to unsigned short
+*/
+
+CURL_STATIC unsigned short curlx_sltous(long slnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(slnum >= 0);
+ DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_USHORT);
+ return (unsigned short)(slnum & (long) CURL_MASK_USHORT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to signed ssize_t
+*/
+
+CURL_STATIC ssize_t curlx_uztosz(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_SSIZE_T);
+ return (ssize_t)(uznum & (size_t) CURL_MASK_SSIZE_T);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed curl_off_t to unsigned size_t
+*/
+
+CURL_STATIC size_t curlx_sotouz(curl_off_t sonum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(sonum >= 0);
+ return (size_t)(sonum & (curl_off_t) CURL_MASK_USIZE_T);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed ssize_t to signed int
+*/
+
+CURL_STATIC int curlx_sztosi(ssize_t sznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(sznum >= 0);
+#if (SIZEOF_INT < SIZEOF_SIZE_T)
+ DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT);
+#endif
+ return (int)(sznum & (ssize_t) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed int to unsigned size_t
+*/
+
+CURL_STATIC size_t curlx_sitouz(int sinum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(sinum >= 0);
+ return (size_t) sinum;
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+#ifdef USE_WINSOCK
+
+/*
+** curl_socket_t to signed int
+*/
+
+CURL_STATIC int curlx_sktosi(curl_socket_t s)
+{
+ return (int)((ssize_t) s);
+}
+
+/*
+** signed int to curl_socket_t
+*/
+
+CURL_STATIC curl_socket_t curlx_sitosk(int i)
+{
+ return (curl_socket_t)((ssize_t) i);
+}
+
+#endif /* USE_WINSOCK */
+
+#if defined(WIN32) || defined(_WIN32)
+
+CURL_STATIC ssize_t curlx_read(int fd, void *buf, size_t count)
+{
+ return (ssize_t)_read(fd, buf, curlx_uztoui(count));
+}
+
+CURL_STATIC ssize_t curlx_write(int fd, const void *buf, size_t count)
+{
+ return (ssize_t)_write(fd, buf, curlx_uztoui(count));
+}
+
+#endif /* WIN32 || _WIN32 */
+
+#if defined(__INTEL_COMPILER) && defined(__unix__)
+
+CURL_STATIC int curlx_FD_ISSET(int fd, fd_set *fdset)
+{
+ #pragma warning(push)
+ #pragma warning(disable:1469) /* clobber ignored */
+ return FD_ISSET(fd, fdset);
+ #pragma warning(pop)
+}
+
+CURL_STATIC void curlx_FD_SET(int fd, fd_set *fdset)
+{
+ #pragma warning(push)
+ #pragma warning(disable:1469) /* clobber ignored */
+ FD_SET(fd, fdset);
+ #pragma warning(pop)
+}
+
+CURL_STATIC void curlx_FD_ZERO(fd_set *fdset)
+{
+ #pragma warning(push)
+ #pragma warning(disable:593) /* variable was set but never used */
+ FD_ZERO(fdset);
+ #pragma warning(pop)
+}
+
+CURL_STATIC unsigned short curlx_htons(unsigned short usnum)
+{
+#if (__INTEL_COMPILER == 910) && defined(__i386__)
+ return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
+#else
+ #pragma warning(push)
+ #pragma warning(disable:810) /* conversion may lose significant bits */
+ return htons(usnum);
+ #pragma warning(pop)
+#endif
+}
+
+CURL_STATIC unsigned short curlx_ntohs(unsigned short usnum)
+{
+#if (__INTEL_COMPILER == 910) && defined(__i386__)
+ return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
+#else
+ #pragma warning(push)
+ #pragma warning(disable:810) /* conversion may lose significant bits */
+ return ntohs(usnum);
+ #pragma warning(pop)
+#endif
+}
+
+#endif /* __INTEL_COMPILER && __unix__ */
diff --git a/libcurl/src/lib/warnless.h b/libcurl/src/lib/warnless.h
new file mode 100644
index 0000000..53fa0d6
--- /dev/null
+++ b/libcurl/src/lib/warnless.h
@@ -0,0 +1,107 @@
+#ifndef HEADER_CURL_WARNLESS_H
+#define HEADER_CURL_WARNLESS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_WINSOCK
+#include <curl/curl.h> /* for curl_socket_t */
+#endif
+
+CURL_STATIC unsigned short curlx_ultous(unsigned long ulnum);
+
+CURL_STATIC unsigned char curlx_ultouc(unsigned long ulnum);
+
+CURL_STATIC int curlx_ultosi(unsigned long ulnum);
+
+CURL_STATIC int curlx_uztosi(size_t uznum);
+
+CURL_STATIC curl_off_t curlx_uztoso(size_t uznum);
+
+CURL_STATIC unsigned long curlx_uztoul(size_t uznum);
+
+CURL_STATIC unsigned int curlx_uztoui(size_t uznum);
+
+CURL_STATIC int curlx_sltosi(long slnum);
+
+CURL_STATIC unsigned int curlx_sltoui(long slnum);
+
+CURL_STATIC unsigned short curlx_sltous(long slnum);
+
+CURL_STATIC ssize_t curlx_uztosz(size_t uznum);
+
+CURL_STATIC size_t curlx_sotouz(curl_off_t sonum);
+
+CURL_STATIC int curlx_sztosi(ssize_t sznum);
+
+CURL_STATIC size_t curlx_sitouz(int sinum);
+
+#ifdef USE_WINSOCK
+
+CURL_STATIC int curlx_sktosi(curl_socket_t s);
+
+CURL_STATIC curl_socket_t curlx_sitosk(int i);
+
+#endif /* USE_WINSOCK */
+
+#if defined(WIN32) || defined(_WIN32)
+
+CURL_STATIC ssize_t curlx_read(int fd, void *buf, size_t count);
+
+CURL_STATIC ssize_t curlx_write(int fd, const void *buf, size_t count);
+
+#ifndef BUILDING_WARNLESS_C
+# undef read
+# define read(fd, buf, count) curlx_read(fd, buf, count)
+# undef write
+# define write(fd, buf, count) curlx_write(fd, buf, count)
+#endif
+
+#endif /* WIN32 || _WIN32 */
+
+#if defined(__INTEL_COMPILER) && defined(__unix__)
+
+CURL_STATIC int curlx_FD_ISSET(int fd, fd_set *fdset);
+
+CURL_STATIC void curlx_FD_SET(int fd, fd_set *fdset);
+
+CURL_STATIC void curlx_FD_ZERO(fd_set *fdset);
+
+CURL_STATIC unsigned short curlx_htons(unsigned short usnum);
+
+CURL_STATIC unsigned short curlx_ntohs(unsigned short usnum);
+
+#ifndef BUILDING_WARNLESS_C
+# undef FD_ISSET
+# define FD_ISSET(a,b) curlx_FD_ISSET((a),(b))
+# undef FD_SET
+# define FD_SET(a,b) curlx_FD_SET((a),(b))
+# undef FD_ZERO
+# define FD_ZERO(a) curlx_FD_ZERO((a))
+# undef htons
+# define htons(a) curlx_htons((a))
+# undef ntohs
+# define ntohs(a) curlx_ntohs((a))
+#endif
+
+#endif /* __INTEL_COMPILER && __unix__ */
+
+#endif /* HEADER_CURL_WARNLESS_H */
diff --git a/libcurl/src/lib/wildcard.c b/libcurl/src/lib/wildcard.c
new file mode 100644
index 0000000..a16a06a
--- /dev/null
+++ b/libcurl/src/lib/wildcard.c
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "wildcard.h"
+#include "llist.h"
+#include "fileinfo.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURL_STATIC CURLcode Curl_wildcard_init(struct WildcardData *wc)
+{
+ DEBUGASSERT(wc->filelist == NULL);
+ /* now allocate only wc->filelist, everything else
+ will be allocated if it is needed. */
+ wc->filelist = Curl_llist_alloc(Curl_fileinfo_dtor);
+ if(!wc->filelist) {;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
+CURL_STATIC void Curl_wildcard_dtor(struct WildcardData *wc)
+{
+ if(!wc)
+ return;
+
+ if(wc->tmp_dtor) {
+ wc->tmp_dtor(wc->tmp);
+ wc->tmp_dtor = ZERO_NULL;
+ wc->tmp = NULL;
+ }
+ DEBUGASSERT(wc->tmp == NULL);
+
+ if(wc->filelist) {
+ Curl_llist_destroy(wc->filelist, NULL);
+ wc->filelist = NULL;
+ }
+
+ free(wc->path);
+ wc->path = NULL;
+ free(wc->pattern);
+ wc->pattern = NULL;
+
+ wc->customptr = NULL;
+ wc->state = CURLWC_INIT;
+}
diff --git a/libcurl/src/lib/wildcard.h b/libcurl/src/lib/wildcard.h
new file mode 100644
index 0000000..3a0ddbd
--- /dev/null
+++ b/libcurl/src/lib/wildcard.h
@@ -0,0 +1,58 @@
+#ifndef HEADER_CURL_WILDCARD_H
+#define HEADER_CURL_WILDCARD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+/* list of wildcard process states */
+typedef enum {
+ CURLWC_INIT = 0,
+ CURLWC_MATCHING, /* library is trying to get list of addresses for
+ downloading */
+ CURLWC_DOWNLOADING,
+ CURLWC_CLEAN, /* deallocate resources and reset settings */
+ CURLWC_SKIP, /* skip over concrete file */
+ CURLWC_ERROR, /* error cases */
+ CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop
+ will end */
+} curl_wildcard_states;
+
+typedef void (*curl_wildcard_tmp_dtor)(void *ptr);
+
+/* struct keeping information about wildcard download process */
+struct WildcardData {
+ curl_wildcard_states state;
+ char *path; /* path to the directory, where we trying wildcard-match */
+ char *pattern; /* wildcard pattern */
+ struct curl_llist *filelist; /* llist with struct Curl_fileinfo */
+ void *tmp; /* pointer to protocol specific temporary data */
+ curl_wildcard_tmp_dtor tmp_dtor;
+ void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
+};
+
+CURL_STATIC CURLcode Curl_wildcard_init(struct WildcardData *wc);
+CURL_STATIC void Curl_wildcard_dtor(struct WildcardData *wc);
+
+struct SessionHandle;
+
+#endif /* HEADER_CURL_WILDCARD_H */
diff --git a/libcurl/src/lib/x509asn1.c b/libcurl/src/lib/x509asn1.c
new file mode 100644
index 0000000..d0d6b7d
--- /dev/null
+++ b/libcurl/src/lib/x509asn1.c
@@ -0,0 +1,1187 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS)
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "strequal.h"
+#include "hostcheck.h"
+#include "vtls/vtls.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "curl_base64.h"
+#include "x509asn1.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+/* ASN.1 OIDs. */
+static const char cnOID[] = "2.5.4.3"; /* Common name. */
+static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */
+
+static const curl_OID OIDtable[] = {
+ { "1.2.840.10040.4.1", "dsa" },
+ { "1.2.840.10040.4.3", "dsa-with-sha1" },
+ { "1.2.840.10045.2.1", "ecPublicKey" },
+ { "1.2.840.10045.3.0.1", "c2pnb163v1" },
+ { "1.2.840.10045.4.1", "ecdsa-with-SHA1" },
+ { "1.2.840.10046.2.1", "dhpublicnumber" },
+ { "1.2.840.113549.1.1.1", "rsaEncryption" },
+ { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" },
+ { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" },
+ { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" },
+ { "1.2.840.113549.1.1.10", "RSASSA-PSS" },
+ { "1.2.840.113549.1.1.14", "sha224WithRSAEncryption" },
+ { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" },
+ { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" },
+ { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" },
+ { "1.2.840.113549.2.2", "md2" },
+ { "1.2.840.113549.2.5", "md5" },
+ { "1.3.14.3.2.26", "sha1" },
+ { cnOID, "CN" },
+ { "2.5.4.4", "SN" },
+ { "2.5.4.5", "serialNumber" },
+ { "2.5.4.6", "C" },
+ { "2.5.4.7", "L" },
+ { "2.5.4.8", "ST" },
+ { "2.5.4.9", "streetAddress" },
+ { "2.5.4.10", "O" },
+ { "2.5.4.11", "OU" },
+ { "2.5.4.12", "title" },
+ { "2.5.4.13", "description" },
+ { "2.5.4.17", "postalCode" },
+ { "2.5.4.41", "name" },
+ { "2.5.4.42", "givenName" },
+ { "2.5.4.43", "initials" },
+ { "2.5.4.44", "generationQualifier" },
+ { "2.5.4.45", "X500UniqueIdentifier" },
+ { "2.5.4.46", "dnQualifier" },
+ { "2.5.4.65", "pseudonym" },
+ { "1.2.840.113549.1.9.1", "emailAddress" },
+ { "2.5.4.72", "role" },
+ { sanOID, "subjectAltName" },
+ { "2.5.29.18", "issuerAltName" },
+ { "2.5.29.19", "basicConstraints" },
+ { "2.16.840.1.101.3.4.2.4", "sha224" },
+ { "2.16.840.1.101.3.4.2.1", "sha256" },
+ { "2.16.840.1.101.3.4.2.2", "sha384" },
+ { "2.16.840.1.101.3.4.2.3", "sha512" },
+ { (const char *) NULL, (const char *) NULL }
+};
+
+/*
+ * Lightweight ASN.1 parser.
+ * In particular, it does not check for syntactic/lexical errors.
+ * It is intended to support certificate information gathering for SSL backends
+ * that offer a mean to get certificates as a whole, but do not supply
+ * entry points to get particular certificate sub-fields.
+ * Please note there is no pretention here to rewrite a full SSL library.
+ */
+
+
+CURL_STATIC const char * Curl_getASN1Element(curl_asn1Element * elem,
+ const char * beg, const char * end)
+{
+ unsigned char b;
+ unsigned long len;
+ curl_asn1Element lelem;
+
+ /* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg'
+ ending at `end'.
+ Returns a pointer in source string after the parsed element, or NULL
+ if an error occurs. */
+
+ if(beg >= end || !*beg)
+ return (const char *) NULL;
+
+ /* Process header byte. */
+ elem->header = beg;
+ b = (unsigned char) *beg++;
+ elem->constructed = (b & 0x20) != 0;
+ elem->class = (b >> 6) & 3;
+ b &= 0x1F;
+ if(b == 0x1F)
+ return (const char *) NULL; /* Long tag values not supported here. */
+ elem->tag = b;
+
+ /* Process length. */
+ if(beg >= end)
+ return (const char *) NULL;
+ b = (unsigned char) *beg++;
+ if(!(b & 0x80))
+ len = b;
+ else if(!(b &= 0x7F)) {
+ /* Unspecified length. Since we have all the data, we can determine the
+ effective length by skipping element until an end element is found. */
+ if(!elem->constructed)
+ return (const char *) NULL;
+ elem->beg = beg;
+ while(beg < end && *beg) {
+ beg = Curl_getASN1Element(&lelem, beg, end);
+ if(!beg)
+ return (const char *) NULL;
+ }
+ if(beg >= end)
+ return (const char *) NULL;
+ elem->end = beg;
+ return beg + 1;
+ }
+ else if(beg + b > end)
+ return (const char *) NULL; /* Does not fit in source. */
+ else {
+ /* Get long length. */
+ len = 0;
+ do {
+ if(len & 0xFF000000L)
+ return (const char *) NULL; /* Lengths > 32 bits are not supported. */
+ len = (len << 8) | (unsigned char) *beg++;
+ } while(--b);
+ }
+ if((unsigned long) (end - beg) < len)
+ return (const char *) NULL; /* Element data does not fit in source. */
+ elem->beg = beg;
+ elem->end = beg + len;
+ return elem->end;
+}
+
+static const curl_OID * searchOID(const char * oid)
+{
+ const curl_OID * op;
+
+ /* Search the null terminated OID or OID identifier in local table.
+ Return the table entry pointer or NULL if not found. */
+
+ for(op = OIDtable; op->numoid; op++)
+ if(!strcmp(op->numoid, oid) || curl_strequal(op->textoid, oid))
+ return op;
+
+ return (const curl_OID *) NULL;
+}
+
+static const char * bool2str(const char * beg, const char * end)
+{
+ /* Convert an ASN.1 Boolean value into its string representation.
+ Return the dynamically allocated string, or NULL if source is not an
+ ASN.1 Boolean value. */
+
+ if(end - beg != 1)
+ return (const char *) NULL;
+ return strdup(*beg? "TRUE": "FALSE");
+}
+
+static const char * octet2str(const char * beg, const char * end)
+{
+ size_t n = end - beg;
+ char * buf;
+
+ /* Convert an ASN.1 octet string to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ buf = malloc(3 * n + 1);
+ if(buf)
+ for(n = 0; beg < end; n += 3)
+ snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+ return buf;
+}
+
+static const char * bit2str(const char * beg, const char * end)
+{
+ /* Convert an ASN.1 bit string to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(++beg > end)
+ return (const char *) NULL;
+ return octet2str(beg, end);
+}
+
+static const char * int2str(const char * beg, const char * end)
+{
+ long val = 0;
+ size_t n = end - beg;
+
+ /* Convert an ASN.1 integer value into its string representation.
+ Return the dynamically allocated string, or NULL if source is not an
+ ASN.1 integer value. */
+
+ if(!n)
+ return (const char *) NULL;
+
+ if(n > 4)
+ return octet2str(beg, end);
+
+ /* Represent integers <= 32-bit as a single value. */
+ if(*beg & 0x80)
+ val = ~val;
+
+ do
+ val = (val << 8) | *(const unsigned char *) beg++;
+ while(beg < end);
+ return curl_maprintf("%s%lx", (val < 0 || val >= 10)? "0x": "", val);
+}
+
+static ssize_t
+utf8asn1str(char * * to, int type, const char * from, const char * end)
+{
+ size_t inlength = end - from;
+ int size = 1;
+ size_t outlength;
+ int charsize;
+ unsigned int wc;
+ char * buf;
+
+ /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
+ destination buffer dynamically. The allocation size will normally be too
+ large: this is to avoid buffer overflows.
+ Terminate the string with a nul byte and return the converted
+ string length. */
+
+ *to = (char *) NULL;
+ switch (type) {
+ case CURL_ASN1_BMP_STRING:
+ size = 2;
+ break;
+ case CURL_ASN1_UNIVERSAL_STRING:
+ size = 4;
+ break;
+ case CURL_ASN1_NUMERIC_STRING:
+ case CURL_ASN1_PRINTABLE_STRING:
+ case CURL_ASN1_TELETEX_STRING:
+ case CURL_ASN1_IA5_STRING:
+ case CURL_ASN1_VISIBLE_STRING:
+ case CURL_ASN1_UTF8_STRING:
+ break;
+ default:
+ return -1; /* Conversion not supported. */
+ }
+
+ if(inlength % size)
+ return -1; /* Length inconsistent with character size. */
+ buf = malloc(4 * (inlength / size) + 1);
+ if(!buf)
+ return -1; /* Not enough memory. */
+
+ if(type == CURL_ASN1_UTF8_STRING) {
+ /* Just copy. */
+ outlength = inlength;
+ if(outlength)
+ memcpy(buf, from, outlength);
+ }
+ else {
+ for(outlength = 0; from < end;) {
+ wc = 0;
+ switch (size) {
+ case 4:
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ /* fallthrough */
+ case 2:
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ /* fallthrough */
+ default: /* case 1: */
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ }
+ charsize = 1;
+ if(wc >= 0x00000080) {
+ if(wc >= 0x00000800) {
+ if(wc >= 0x00010000) {
+ if(wc >= 0x00200000) {
+ free(buf);
+ return -1; /* Invalid char. size for target encoding. */
+ }
+ buf[outlength + 3] = (char) (0x80 | (wc & 0x3F));
+ wc = (wc >> 6) | 0x00010000;
+ charsize++;
+ }
+ buf[outlength + 2] = (char) (0x80 | (wc & 0x3F));
+ wc = (wc >> 6) | 0x00000800;
+ charsize++;
+ }
+ buf[outlength + 1] = (char) (0x80 | (wc & 0x3F));
+ wc = (wc >> 6) | 0x000000C0;
+ charsize++;
+ }
+ buf[outlength] = (char) wc;
+ outlength += charsize;
+ }
+ }
+ buf[outlength] = '\0';
+ *to = buf;
+ return outlength;
+}
+
+static const char * string2str(int type, const char * beg, const char * end)
+{
+ char * buf;
+
+ /* Convert an ASN.1 String into its UTF-8 string representation.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(utf8asn1str(&buf, type, beg, end) < 0)
+ return (const char *) NULL;
+ return buf;
+}
+
+static int encodeUint(char * buf, int n, unsigned int x)
+{
+ int i = 0;
+ unsigned int y = x / 10;
+
+ /* Decimal ASCII encode unsigned integer `x' in the `n'-byte buffer at `buf'.
+ Return the total number of encoded digits, even if larger than `n'. */
+
+ if(y) {
+ i += encodeUint(buf, n, y);
+ x -= y * 10;
+ }
+ if(i < n)
+ buf[i] = (char) ('0' + x);
+ i++;
+ if(i < n)
+ buf[i] = '\0'; /* Store a terminator if possible. */
+ return i;
+}
+
+static int encodeOID(char * buf, int n, const char * beg, const char * end)
+{
+ int i = 0;
+ unsigned int x;
+ unsigned int y;
+
+ /* Convert an ASN.1 OID into its dotted string representation.
+ Store the result in th `n'-byte buffer at `buf'.
+ Return the converted string length, or -1 if an error occurs. */
+
+ /* Process the first two numbers. */
+ y = *(const unsigned char *) beg++;
+ x = y / 40;
+ y -= x * 40;
+ i += encodeUint(buf + i, n - i, x);
+ if(i < n)
+ buf[i] = '.';
+ i++;
+ i += encodeUint(buf + i, n - i, y);
+
+ /* Process the trailing numbers. */
+ while(beg < end) {
+ if(i < n)
+ buf[i] = '.';
+ i++;
+ x = 0;
+ do {
+ if(x & 0xFF000000)
+ return -1;
+ y = *(const unsigned char *) beg++;
+ x = (x << 7) | (y & 0x7F);
+ } while(y & 0x80);
+ i += encodeUint(buf + i, n - i, x);
+ }
+ if(i < n)
+ buf[i] = '\0';
+ return i;
+}
+
+static const char * OID2str(const char * beg, const char * end, bool symbolic)
+{
+ char * buf = (char *) NULL;
+ const curl_OID * op;
+ int n;
+
+ /* Convert an ASN.1 OID into its dotted or symbolic string representation.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(beg < end) {
+ n = encodeOID((char *) NULL, -1, beg, end);
+ if(n >= 0) {
+ buf = malloc(n + 1);
+ if(buf) {
+ encodeOID(buf, n, beg, end);
+ buf[n] = '\0';
+
+ if(symbolic) {
+ op = searchOID(buf);
+ if(op) {
+ free(buf);
+ buf = strdup(op->textoid);
+ }
+ }
+ }
+ }
+ }
+ return buf;
+}
+
+static const char * GTime2str(const char * beg, const char * end)
+{
+ const char * tzp;
+ const char * fracp;
+ char sec1, sec2;
+ size_t fracl;
+ size_t tzl;
+ const char * sep = "";
+
+ /* Convert an ASN.1 Generalized time to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++)
+ ;
+
+ /* Get seconds digits. */
+ sec1 = '0';
+ switch (fracp - beg - 12) {
+ case 0:
+ sec2 = '0';
+ break;
+ case 2:
+ sec1 = fracp[-2];
+ case 1:
+ sec2 = fracp[-1];
+ break;
+ default:
+ return (const char *) NULL;
+ }
+
+ /* Scan for timezone, measure fractional seconds. */
+ tzp = fracp;
+ fracl = 0;
+ if(fracp < end && (*fracp == '.' || *fracp == ',')) {
+ fracp++;
+ do
+ tzp++;
+ while(tzp < end && *tzp >= '0' && *tzp <= '9');
+ /* Strip leading zeroes in fractional seconds. */
+ for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--)
+ ;
+ }
+
+ /* Process timezone. */
+ if(tzp >= end)
+ ; /* Nothing to do. */
+ else if(*tzp == 'Z') {
+ tzp = " GMT";
+ end = tzp + 4;
+ }
+ else {
+ sep = " ";
+ tzp++;
+ }
+
+ tzl = end - tzp;
+ return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
+ beg, beg + 4, beg + 6,
+ beg + 8, beg + 10, sec1, sec2,
+ fracl? ".": "", fracl, fracp,
+ sep, tzl, tzp);
+}
+
+static const char * UTime2str(const char * beg, const char * end)
+{
+ const char * tzp;
+ size_t tzl;
+ const char * sec;
+
+ /* Convert an ASN.1 UTC time to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++)
+ ;
+ /* Get the seconds. */
+ sec = beg + 10;
+ switch (tzp - sec) {
+ case 0:
+ sec = "00";
+ case 2:
+ break;
+ default:
+ return (const char *) NULL;
+ }
+
+ /* Process timezone. */
+ if(tzp >= end)
+ return (const char *) NULL;
+ if(*tzp == 'Z') {
+ tzp = "GMT";
+ end = tzp + 3;
+ }
+ else
+ tzp++;
+
+ tzl = end - tzp;
+ return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
+ 20 - (*beg >= '5'), beg, beg + 2, beg + 4,
+ beg + 6, beg + 8, sec,
+ tzl, tzp);
+}
+
+CURL_STATIC const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
+{
+ /* Convert an ASN.1 element to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(elem->constructed)
+ return (const char *) NULL; /* No conversion of structured elements. */
+
+ if(!type)
+ type = elem->tag; /* Type not forced: use element tag as type. */
+
+ switch (type) {
+ case CURL_ASN1_BOOLEAN:
+ return bool2str(elem->beg, elem->end);
+ case CURL_ASN1_INTEGER:
+ case CURL_ASN1_ENUMERATED:
+ return int2str(elem->beg, elem->end);
+ case CURL_ASN1_BIT_STRING:
+ return bit2str(elem->beg, elem->end);
+ case CURL_ASN1_OCTET_STRING:
+ return octet2str(elem->beg, elem->end);
+ case CURL_ASN1_NULL:
+ return strdup("");
+ case CURL_ASN1_OBJECT_IDENTIFIER:
+ return OID2str(elem->beg, elem->end, TRUE);
+ case CURL_ASN1_UTC_TIME:
+ return UTime2str(elem->beg, elem->end);
+ case CURL_ASN1_GENERALIZED_TIME:
+ return GTime2str(elem->beg, elem->end);
+ case CURL_ASN1_UTF8_STRING:
+ case CURL_ASN1_NUMERIC_STRING:
+ case CURL_ASN1_PRINTABLE_STRING:
+ case CURL_ASN1_TELETEX_STRING:
+ case CURL_ASN1_IA5_STRING:
+ case CURL_ASN1_VISIBLE_STRING:
+ case CURL_ASN1_UNIVERSAL_STRING:
+ case CURL_ASN1_BMP_STRING:
+ return string2str(type, elem->beg, elem->end);
+ }
+
+ return (const char *) NULL; /* Unsupported. */
+}
+
+static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
+{
+ curl_asn1Element rdn;
+ curl_asn1Element atv;
+ curl_asn1Element oid;
+ curl_asn1Element value;
+ size_t l = 0;
+ const char * p1;
+ const char * p2;
+ const char * p3;
+ const char * str;
+
+ /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'.
+ Return the total string length, even if larger than `n'. */
+
+ for(p1 = dn->beg; p1 < dn->end;) {
+ p1 = Curl_getASN1Element(&rdn, p1, dn->end);
+ for(p2 = rdn.beg; p2 < rdn.end;) {
+ p2 = Curl_getASN1Element(&atv, p2, rdn.end);
+ p3 = Curl_getASN1Element(&oid, atv.beg, atv.end);
+ Curl_getASN1Element(&value, p3, atv.end);
+ str = Curl_ASN1tostr(&oid, 0);
+ if(!str)
+ return -1;
+
+ /* Encode delimiter.
+ If attribute has a short uppercase name, delimiter is ", ". */
+ if(l) {
+ for(p3 = str; isupper(*p3); p3++)
+ ;
+ for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
+ if(l < n)
+ buf[l] = *p3;
+ l++;
+ }
+ }
+
+ /* Encode attribute name. */
+ for(p3 = str; *p3; p3++) {
+ if(l < n)
+ buf[l] = *p3;
+ l++;
+ }
+ free((char *) str);
+
+ /* Generate equal sign. */
+ if(l < n)
+ buf[l] = '=';
+ l++;
+
+ /* Generate value. */
+ str = Curl_ASN1tostr(&value, 0);
+ if(!str)
+ return -1;
+ for(p3 = str; *p3; p3++) {
+ if(l < n)
+ buf[l] = *p3;
+ l++;
+ }
+ free((char *) str);
+ }
+ }
+
+ return l;
+}
+
+CURL_STATIC const char * Curl_DNtostr(curl_asn1Element * dn)
+{
+ char * buf = (char *) NULL;
+ ssize_t n = encodeDN(buf, 0, dn);
+
+ /* Convert an ASN.1 distinguished name into a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(n >= 0) {
+ buf = malloc(n + 1);
+ if(buf) {
+ encodeDN(buf, n + 1, dn);
+ buf[n] = '\0';
+ }
+ }
+ return (const char *) buf;
+}
+
+/*
+ * X509 parser.
+ */
+
+CURL_STATIC void Curl_parseX509(curl_X509certificate * cert,
+ const char * beg, const char * end)
+{
+ curl_asn1Element elem;
+ curl_asn1Element tbsCertificate;
+ const char * ccp;
+ static const char defaultVersion = 0; /* v1. */
+
+ /* ASN.1 parse an X509 certificate into structure subfields.
+ Syntax is assumed to have already been checked by the SSL backend.
+ See RFC 5280. */
+
+ cert->certificate.header = NULL;
+ cert->certificate.beg = beg;
+ cert->certificate.end = end;
+
+ /* Get the sequence content. */
+ Curl_getASN1Element(&elem, beg, end);
+ beg = elem.beg;
+ end = elem.end;
+
+ /* Get tbsCertificate. */
+ beg = Curl_getASN1Element(&tbsCertificate, beg, end);
+ /* Skip the signatureAlgorithm. */
+ beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ /* Get the signatureValue. */
+ Curl_getASN1Element(&cert->signature, beg, end);
+
+ /* Parse TBSCertificate. */
+ beg = tbsCertificate.beg;
+ end = tbsCertificate.end;
+ /* Get optional version, get serialNumber. */
+ cert->version.header = NULL;
+ cert->version.beg = &defaultVersion;
+ cert->version.end = &defaultVersion + sizeof defaultVersion;;
+ beg = Curl_getASN1Element(&elem, beg, end);
+ if(elem.tag == 0) {
+ Curl_getASN1Element(&cert->version, elem.beg, elem.end);
+ beg = Curl_getASN1Element(&elem, beg, end);
+ }
+ cert->serialNumber = elem;
+ /* Get signature algorithm. */
+ beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ /* Get issuer. */
+ beg = Curl_getASN1Element(&cert->issuer, beg, end);
+ /* Get notBefore and notAfter. */
+ beg = Curl_getASN1Element(&elem, beg, end);
+ ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end);
+ Curl_getASN1Element(&cert->notAfter, ccp, elem.end);
+ /* Get subject. */
+ beg = Curl_getASN1Element(&cert->subject, beg, end);
+ /* Get subjectPublicKeyAlgorithm and subjectPublicKey. */
+ beg = Curl_getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
+ ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm,
+ cert->subjectPublicKeyInfo.beg,
+ cert->subjectPublicKeyInfo.end);
+ Curl_getASN1Element(&cert->subjectPublicKey, ccp,
+ cert->subjectPublicKeyInfo.end);
+ /* Get optional issuerUiqueID, subjectUniqueID and extensions. */
+ cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
+ cert->extensions.tag = elem.tag = 0;
+ cert->issuerUniqueID.header = cert->subjectUniqueID.header = NULL;
+ cert->issuerUniqueID.beg = cert->issuerUniqueID.end = "";
+ cert->subjectUniqueID.beg = cert->subjectUniqueID.end = "";
+ cert->extensions.header = NULL;
+ cert->extensions.beg = cert->extensions.end = "";
+ if(beg < end)
+ beg = Curl_getASN1Element(&elem, beg, end);
+ if(elem.tag == 1) {
+ cert->issuerUniqueID = elem;
+ if(beg < end)
+ beg = Curl_getASN1Element(&elem, beg, end);
+ }
+ if(elem.tag == 2) {
+ cert->subjectUniqueID = elem;
+ if(beg < end)
+ beg = Curl_getASN1Element(&elem, beg, end);
+ }
+ if(elem.tag == 3)
+ Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+}
+
+static size_t copySubstring(char * to, const char * from)
+{
+ size_t i;
+
+ /* Copy at most 64-characters, terminate with a newline and returns the
+ effective number of stored characters. */
+
+ for(i = 0; i < 64; i++) {
+ to[i] = *from;
+ if(!*from++)
+ break;
+ }
+
+ to[i++] = '\n';
+ return i;
+}
+
+static const char * dumpAlgo(curl_asn1Element * param,
+ const char * beg, const char * end)
+{
+ curl_asn1Element oid;
+
+ /* Get algorithm parameters and return algorithm name. */
+
+ beg = Curl_getASN1Element(&oid, beg, end);
+ param->header = NULL;
+ param->tag = 0;
+ param->beg = param->end = end;
+ if(beg < end)
+ Curl_getASN1Element(param, beg, end);
+ return OID2str(oid.beg, oid.end, TRUE);
+}
+
+static void do_pubkey_field(struct SessionHandle * data, int certnum,
+ const char * label, curl_asn1Element * elem)
+{
+ const char * output;
+
+ /* Generate a certificate information record for the public key. */
+
+ output = Curl_ASN1tostr(elem, 0);
+ if(output) {
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, label, output);
+ if(!certnum)
+ infof(data, " %s: %s\n", label, output);
+ free((char *) output);
+ }
+}
+
+static void do_pubkey(struct SessionHandle * data, int certnum,
+ const char * algo, curl_asn1Element * param,
+ curl_asn1Element * pubkey)
+{
+ curl_asn1Element elem;
+ curl_asn1Element pk;
+ const char * p;
+ const char * q;
+ unsigned long len;
+ unsigned int i;
+
+ /* Generate all information records for the public key. */
+
+ /* Get the public key (single element). */
+ Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
+
+ if(curl_strequal(algo, "rsaEncryption")) {
+ p = Curl_getASN1Element(&elem, pk.beg, pk.end);
+ /* Compute key length. */
+ for(q = elem.beg; !*q && q < elem.end; q++)
+ ;
+ len = (unsigned long)((elem.end - q) * 8);
+ if(len)
+ for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1)
+ len--;
+ if(len > 32)
+ elem.beg = q; /* Strip leading zero bytes. */
+ if(!certnum)
+ infof(data, " RSA Public Key (%lu bits)\n", len);
+ if(data->set.ssl.certinfo) {
+ q = curl_maprintf("%lu", len);
+ if(q) {
+ Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
+ free((char *) q);
+ }
+ }
+ /* Generate coefficients. */
+ do_pubkey_field(data, certnum, "rsa(n)", &elem);
+ Curl_getASN1Element(&elem, p, pk.end);
+ do_pubkey_field(data, certnum, "rsa(e)", &elem);
+ }
+ else if(curl_strequal(algo, "dsa")) {
+ p = Curl_getASN1Element(&elem, param->beg, param->end);
+ do_pubkey_field(data, certnum, "dsa(p)", &elem);
+ p = Curl_getASN1Element(&elem, p, param->end);
+ do_pubkey_field(data, certnum, "dsa(q)", &elem);
+ Curl_getASN1Element(&elem, p, param->end);
+ do_pubkey_field(data, certnum, "dsa(g)", &elem);
+ do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
+ }
+ else if(curl_strequal(algo, "dhpublicnumber")) {
+ p = Curl_getASN1Element(&elem, param->beg, param->end);
+ do_pubkey_field(data, certnum, "dh(p)", &elem);
+ Curl_getASN1Element(&elem, param->beg, param->end);
+ do_pubkey_field(data, certnum, "dh(g)", &elem);
+ do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
+ }
+#if 0 /* Patent-encumbered. */
+ else if(curl_strequal(algo, "ecPublicKey")) {
+ /* Left TODO. */
+ }
+#endif
+}
+
+CURL_STATIC CURLcode Curl_extract_certinfo(struct connectdata * conn,
+ int certnum,
+ const char * beg,
+ const char * end)
+{
+ curl_X509certificate cert;
+ struct SessionHandle * data = conn->data;
+ curl_asn1Element param;
+ const char * ccp;
+ char * cp1;
+ size_t cl1;
+ char * cp2;
+ CURLcode result;
+ unsigned long version;
+ size_t i;
+ size_t j;
+
+ if(!data->set.ssl.certinfo)
+ if(certnum)
+ return CURLE_OK;
+
+ /* Prepare the certificate information for curl_easy_getinfo(). */
+
+ /* Extract the certificate ASN.1 elements. */
+ Curl_parseX509(&cert, beg, end);
+
+ /* Subject. */
+ ccp = Curl_DNtostr(&cert.subject);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
+ if(!certnum)
+ infof(data, "%2d Subject: %s\n", certnum, ccp);
+ free((char *) ccp);
+
+ /* Issuer. */
+ ccp = Curl_DNtostr(&cert.issuer);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
+ if(!certnum)
+ infof(data, " Issuer: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Version (always fits in less than 32 bits). */
+ version = 0;
+ for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
+ version = (version << 8) | *(const unsigned char *) ccp;
+ if(data->set.ssl.certinfo) {
+ ccp = curl_maprintf("%lx", version);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
+ free((char *) ccp);
+ }
+ if(!certnum)
+ infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
+
+ /* Serial number. */
+ ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
+ if(!certnum)
+ infof(data, " Serial Number: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Signature algorithm .*/
+ ccp = dumpAlgo(&param, cert.signatureAlgorithm.beg,
+ cert.signatureAlgorithm.end);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
+ if(!certnum)
+ infof(data, " Signature Algorithm: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Start Date. */
+ ccp = Curl_ASN1tostr(&cert.notBefore, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
+ if(!certnum)
+ infof(data, " Start Date: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Expire Date. */
+ ccp = Curl_ASN1tostr(&cert.notAfter, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
+ if(!certnum)
+ infof(data, " Expire Date: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Public Key Algorithm. */
+ ccp = dumpAlgo(&param, cert.subjectPublicKeyAlgorithm.beg,
+ cert.subjectPublicKeyAlgorithm.end);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp);
+ if(!certnum)
+ infof(data, " Public Key Algorithm: %s\n", ccp);
+ do_pubkey(data, certnum, ccp, &param, &cert.subjectPublicKey);
+ free((char *) ccp);
+
+/* TODO: extensions. */
+
+ /* Signature. */
+ ccp = Curl_ASN1tostr(&cert.signature, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
+ if(!certnum)
+ infof(data, " Signature: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Generate PEM certificate. */
+ result = Curl_base64_encode(data, cert.certificate.beg,
+ cert.certificate.end - cert.certificate.beg,
+ &cp1, &cl1);
+ if(result)
+ return result;
+ /* Compute the number of characters in final certificate string. Format is:
+ -----BEGIN CERTIFICATE-----\n
+ <max 64 base64 characters>\n
+ .
+ .
+ .
+ -----END CERTIFICATE-----\n
+ */
+ i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26;
+ cp2 = malloc(i + 1);
+ if(!cp2) {
+ free(cp1);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ /* Build the certificate string. */
+ i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----");
+ for(j = 0; j < cl1; j += 64)
+ i += copySubstring(cp2 + i, cp1 + j);
+ i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
+ cp2[i] = '\0';
+ free(cp1);
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
+ if(!certnum)
+ infof(data, "%s\n", cp2);
+ free(cp2);
+ return CURLE_OK;
+}
+
+#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS */
+
+#if defined(USE_GSKIT)
+
+static const char * checkOID(const char * beg, const char * end,
+ const char * oid)
+{
+ curl_asn1Element e;
+ const char * ccp;
+ const char * p;
+ bool matched;
+
+ /* Check if first ASN.1 element at `beg' is the given OID.
+ Return a pointer in the source after the OID if found, else NULL. */
+
+ ccp = Curl_getASN1Element(&e, beg, end);
+ if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
+ return (const char *) NULL;
+
+ p = OID2str(e.beg, e.end, FALSE);
+ if(!p)
+ return (const char *) NULL;
+
+ matched = !strcmp(p, oid);
+ free((char *) p);
+ return matched? ccp: (const char *) NULL;
+}
+
+CURL_STATIC CURLcode Curl_verifyhost(struct connectdata * conn,
+ const char * beg, const char * end)
+{
+ struct SessionHandle * data = conn->data;
+ curl_X509certificate cert;
+ curl_asn1Element dn;
+ curl_asn1Element elem;
+ curl_asn1Element ext;
+ curl_asn1Element name;
+ int i;
+ const char * p;
+ const char * q;
+ char * dnsname;
+ int matched = -1;
+ size_t addrlen = (size_t) -1;
+ ssize_t len;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+
+ /* Verify that connection server matches info in X509 certificate at
+ `beg'..`end'. */
+
+ if(!data->set.ssl.verifyhost)
+ return CURLE_OK;
+
+ if(!beg)
+ return CURLE_PEER_FAILED_VERIFICATION;
+ Curl_parseX509(&cert, beg, end);
+
+ /* Get the server IP address. */
+#ifdef ENABLE_IPV6
+ if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+ addrlen = sizeof(struct in6_addr);
+ else
+#endif
+ if(Curl_inet_pton(AF_INET, conn->host.name, &addr))
+ addrlen = sizeof(struct in_addr);
+
+ /* Process extensions. */
+ for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
+ p = Curl_getASN1Element(&ext, p, cert.extensions.end);
+ /* Check if extension is a subjectAlternativeName. */
+ ext.beg = checkOID(ext.beg, ext.end, sanOID);
+ if(ext.beg) {
+ ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ /* Skip critical if present. */
+ if(elem.tag == CURL_ASN1_BOOLEAN)
+ ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ /* Parse the octet string contents: is a single sequence. */
+ Curl_getASN1Element(&elem, elem.beg, elem.end);
+ /* Check all GeneralNames. */
+ for(q = elem.beg; matched != 1 && q < elem.end;) {
+ q = Curl_getASN1Element(&name, q, elem.end);
+ switch (name.tag) {
+ case 2: /* DNS name. */
+ i = 0;
+ len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
+ name.beg, name.end);
+ if(len > 0)
+ if(strlen(dnsname) == (size_t) len)
+ i = Curl_cert_hostcheck((const char *) dnsname, conn->host.name);
+ free(dnsname);
+ if(!i)
+ return CURLE_PEER_FAILED_VERIFICATION;
+ matched = i;
+ break;
+
+ case 7: /* IP address. */
+ matched = (size_t) (name.end - q) == addrlen &&
+ !memcmp(&addr, q, addrlen);
+ break;
+ }
+ }
+ }
+ }
+
+ switch (matched) {
+ case 1:
+ /* an alternative name matched the server hostname */
+ infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
+ return CURLE_OK;
+ case 0:
+ /* an alternative name field existed, but didn't match and then
+ we MUST fail */
+ infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ /* Process subject. */
+ name.header = NULL;
+ name.beg = name.end = "";
+ q = cert.subject.beg;
+ /* we have to look to the last occurrence of a commonName in the
+ distinguished one to get the most significant one. */
+ while(q < cert.subject.end) {
+ q = Curl_getASN1Element(&dn, q, cert.subject.end);
+ for(p = dn.beg; p < dn.end;) {
+ p = Curl_getASN1Element(&elem, p, dn.end);
+ /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
+ elem.beg = checkOID(elem.beg, elem.end, cnOID);
+ if(elem.beg)
+ name = elem; /* Latch CN. */
+ }
+ }
+
+ /* Check the CN if found. */
+ if(!Curl_getASN1Element(&elem, name.beg, name.end))
+ failf(data, "SSL: unable to obtain common name from peer certificate");
+ else {
+ len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
+ if(len < 0) {
+ free(dnsname);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
+ failf(data, "SSL: illegal cert name field");
+ else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) {
+ infof(data, "\t common name: %s (matched)\n", dnsname);
+ free(dnsname);
+ return CURLE_OK;
+ }
+ else
+ failf(data, "SSL: certificate subject name '%s' does not match "
+ "target host name '%s'", dnsname, conn->host.dispname);
+ free(dnsname);
+ }
+
+ return CURLE_PEER_FAILED_VERIFICATION;
+}
+
+#endif /* USE_GSKIT */
diff --git a/libcurl/src/lib/x509asn1.h b/libcurl/src/lib/x509asn1.h
new file mode 100644
index 0000000..f874e07
--- /dev/null
+++ b/libcurl/src/lib/x509asn1.h
@@ -0,0 +1,131 @@
+#ifndef HEADER_CURL_X509ASN1_H
+#define HEADER_CURL_X509ASN1_H
+
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS)
+
+#include "urldata.h"
+
+/*
+ * Constants.
+ */
+
+/* ASN.1 classes. */
+#define CURL_ASN1_UNIVERSAL 0
+#define CURL_ASN1_APPLICATION 1
+#define CURL_ASN1_CONTEXT_SPECIFIC 2
+#define CURL_ASN1_PRIVATE 3
+
+/* ASN.1 types. */
+#define CURL_ASN1_BOOLEAN 1
+#define CURL_ASN1_INTEGER 2
+#define CURL_ASN1_BIT_STRING 3
+#define CURL_ASN1_OCTET_STRING 4
+#define CURL_ASN1_NULL 5
+#define CURL_ASN1_OBJECT_IDENTIFIER 6
+#define CURL_ASN1_OBJECT_DESCRIPTOR 7
+#define CURL_ASN1_INSTANCE_OF 8
+#define CURL_ASN1_REAL 9
+#define CURL_ASN1_ENUMERATED 10
+#define CURL_ASN1_EMBEDDED 11
+#define CURL_ASN1_UTF8_STRING 12
+#define CURL_ASN1_RELATIVE_OID 13
+#define CURL_ASN1_SEQUENCE 16
+#define CURL_ASN1_SET 17
+#define CURL_ASN1_NUMERIC_STRING 18
+#define CURL_ASN1_PRINTABLE_STRING 19
+#define CURL_ASN1_TELETEX_STRING 20
+#define CURL_ASN1_VIDEOTEX_STRING 21
+#define CURL_ASN1_IA5_STRING 22
+#define CURL_ASN1_UTC_TIME 23
+#define CURL_ASN1_GENERALIZED_TIME 24
+#define CURL_ASN1_GRAPHIC_STRING 25
+#define CURL_ASN1_VISIBLE_STRING 26
+#define CURL_ASN1_GENERAL_STRING 27
+#define CURL_ASN1_UNIVERSAL_STRING 28
+#define CURL_ASN1_CHARACTER_STRING 29
+#define CURL_ASN1_BMP_STRING 30
+
+
+/*
+ * Types.
+ */
+
+/* ASN.1 parsed element. */
+typedef struct {
+ const char * header; /* Pointer to header byte. */
+ const char * beg; /* Pointer to element data. */
+ const char * end; /* Pointer to 1st byte after element. */
+ unsigned char class; /* ASN.1 element class. */
+ unsigned char tag; /* ASN.1 element tag. */
+ bool constructed; /* Element is constructed. */
+} curl_asn1Element;
+
+
+/* ASN.1 OID table entry. */
+typedef struct {
+ const char * numoid; /* Dotted-numeric OID. */
+ const char * textoid; /* OID name. */
+} curl_OID;
+
+
+/* X509 certificate: RFC 5280. */
+typedef struct {
+ curl_asn1Element certificate;
+ curl_asn1Element version;
+ curl_asn1Element serialNumber;
+ curl_asn1Element signatureAlgorithm;
+ curl_asn1Element signature;
+ curl_asn1Element issuer;
+ curl_asn1Element notBefore;
+ curl_asn1Element notAfter;
+ curl_asn1Element subject;
+ curl_asn1Element subjectPublicKeyInfo;
+ curl_asn1Element subjectPublicKeyAlgorithm;
+ curl_asn1Element subjectPublicKey;
+ curl_asn1Element issuerUniqueID;
+ curl_asn1Element subjectUniqueID;
+ curl_asn1Element extensions;
+} curl_X509certificate;
+
+
+/*
+ * Prototypes.
+ */
+
+CURL_STATIC const char * Curl_getASN1Element(curl_asn1Element * elem,
+ const char * beg, const char * end);
+CURL_STATIC const char * Curl_ASN1tostr(curl_asn1Element * elem, int type);
+CURL_STATIC const char * Curl_DNtostr(curl_asn1Element * dn);
+CURL_STATIC void Curl_parseX509(curl_X509certificate * cert,
+ const char * beg, const char * end);
+CURL_STATIC CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
+ const char * beg, const char * end);
+CURL_STATIC CURLcode Curl_verifyhost(struct connectdata * conn,
+ const char * beg, const char * end);
+
+#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS */
+#endif /* HEADER_CURL_X509ASN1_H */
diff --git a/libcurl/src/libcurl_unified.c b/libcurl/src/libcurl_unified.c
new file mode 100644
index 0000000..c5dbf46
--- /dev/null
+++ b/libcurl/src/libcurl_unified.c
@@ -0,0 +1,172 @@
+# ifndef CURL_STATICLIB
+# define CURL_STATICLIB
+# endif
+
+# define BUILDING_LIBCURL
+# if !defined(CURL_STATICLIB)
+# define CURL_STATICLIB
+# endif
+
+// #include "InternalOverrides.h"
+
+# if defined(WINAPI_FAMILY)
+# include <winapifamily.h>
+# if WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_APP) || WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_PHONE_APP)
+# define CURL_WINRT
+# endif
+# endif
+
+# if !defined(CURL_DISABLE_TYPECHECK)
+# define CURL_DISABLE_TYPECHECK
+# endif
+# define CURL_DISABLE_CRYPTO_AUTH
+# define CURL_DISABLE_TFTP
+# define CURL_DISABLE_FTP
+# define CURL_DISABLE_LDAP
+# define CURL_DISABLE_TELNET
+# define CURL_DISABLE_DICT
+# define CURL_DISABLE_FILE
+# define CURL_DISABLE_RTSP
+# define CURL_DISABLE_POP3
+# define CURL_DISABLE_IMAP
+# define CURL_DISABLE_SMB
+# define CURL_DISABLE_SMTP
+# define CURL_DISABLE_RTMP
+# define CURL_DISABLE_GOPHER
+
+# define CURL_STATIC static __inline
+# define CURL_STATIC_VAR static
+# define CURL_STATIC_DEF(t,n,v)
+# define CURL_STATIC_DECL(t,n,v) static t n = v
+
+//# define USE_AXTLS
+# define USE_SCHANNEL
+# define USE_WINDOWS_SSPI // USE_SCHANNEL require this
+
+# include "lib/mprintf.c"
+
+# include "lib/urldata.h"
+
+static const struct Curl_handler Curl_handler_http;
+# if defined(USE_SSL)
+static const struct Curl_handler Curl_handler_https;
+# endif
+
+//# include "lib/vtls/axtls.c"
+//# include "lib/vtls/darwinssl.c"
+# include "lib/vtls/schannel.c"
+//# include "lib/vtls/cyassl.c"
+//# include "lib/vtls/gskit.c"
+//# include "lib/vtls/gtls.c"
+//# include "lib/vtls/nss.c"
+//# include "lib/vtls/openssl.c"
+//# include "lib/vtls/polarssl.c"
+//# include "lib/vtls/polarssl_threadlock.c"
+# include "lib/vtls/vtls.c"
+//# include "lib/amigaos.c"
+//# include "lib/asyn-ares.c"
+# include "lib/asyn-thread.c"
+# include "lib/base64.c"
+# include "lib/bundles.c"
+# include "lib/conncache.c"
+# include "lib/connect.c"
+//# include "lib/content_encoding.c"
+# include "lib/cookie.c"
+# include "lib/parsedate.c" // earlier so Curl_wkday and Curl_month will be defined
+//# include "lib/dict.c"
+# include "lib/dotdot.c"
+# include "lib/easy.c"
+# include "lib/escape.c"
+//# include "lib/file.c"
+# include "lib/fileinfo.c"
+# include "lib/formdata.c"
+//# include "lib/ftp.c"
+//# include "lib/ftplistparser.c"
+# include "lib/getenv.c"
+# include "lib/getinfo.c"
+//# include "lib/gopher.c"
+# include "lib/hash.c"
+//# include "lib/hmac.c"
+# include "lib/hostasyn.c"
+//# include "lib/hostcheck.c"
+# include "lib/hostip.c"
+# include "lib/hostip4.c"
+//# include "lib/hostip6.c"
+//# include "lib/hostsyn.c"
+# include "lib/http.c"
+# include "lib/http_chunks.c"
+//# include "lib/http_digest.c"
+//# include "lib/http_negotiate.c"
+//# include "lib/http_negotiate_sspi.c"
+# include "lib/http_proxy.c"
+//# include "lib/http2.c"
+//# include "lib/idn_win32.c"
+# include "lib/if2ip.c"
+//# include "lib/imap.c"
+# include "lib/inet_ntop.c"
+# include "lib/inet_pton.c"
+//# include "lib/krb5.c"
+//# include "lib/ldap.c"
+# include "lib/llist.c"
+//# include "lib/md4.c"
+//# include "lib/md5.c"
+//# include "lib/memdebug.c"
+# include "lib/multi.c"
+# include "lib/netrc.c"
+//# include "lib/non-ascii.c"
+# include "lib/nonblock.c"
+//# include "lib/nwlib.c"
+//# include "lib/nwos.c"
+//# include "lib/openldap.c"
+//# include "lib/pingpong.c"
+# include "lib/pipeline.c"
+//# include "lib/pop3.c"
+# include "lib/progress.c"
+# include "lib/rawstr.c"
+//# include "lib/rtsp.c"
+//# include "lib/security.c"
+# include "lib/select.c"
+# include "lib/sendf.c"
+# include "lib/share.c"
+# include "lib/slist.c"
+//# include "lib/smb.c"
+//# include "lib/smtp.c"
+# include "lib/socks.c"
+//# include "lib/socks_gssapi.c"
+# include "lib/socks_sspi.c"
+# include "lib/speedcheck.c"
+# include "lib/splay.c"
+//# include "lib/ssh.c"
+# include "lib/strdup.c"
+# include "lib/strequal.c"
+# include "lib/strerror.c"
+# include "lib/strtok.c"
+//# include "lib/strtoofft.c"
+//# include "lib/telnet.c"
+//# include "lib/tftp.c"
+# include "lib/timeval.c"
+# include "lib/transfer.c"
+# include "lib/url.c"
+//# include "lib/version.c"
+# include "lib/warnless.c"
+# include "lib/wildcard.c"
+//# include "lib/x509asn1.c"
+
+# include "lib/curl_addrinfo.c"
+//# include "lib/curl_des.c"
+//# include "lib/curl_endian.c"
+//# include "lib/curl_fnmatch.c"
+//# include "lib/curl_gethostname.c"
+//# include "lib/curl_gssapi.c"
+# include "lib/curl_memrchr.c"
+# include "lib/curl_multibyte.c"
+//# include "lib/curl_ntlm.c"
+//# include "lib/curl_ntlm_core.c"
+//# include "lib/curl_ntlm_msgs.c"
+//# include "lib/curl_ntlm_wb.c"
+//# include "lib/curl_rtmp.c"
+//# include "lib/curl_sasl.c"
+//# include "lib/curl_sasl_sspi.c"
+//# include "lib/curl_sasl_gssapi.c"
+# include "lib/curl_sspi.c"
+# include "lib/curl_threads.c"
diff --git a/libmad/configured/config.h b/libmad/configured/config.h
deleted file mode 100644
index 02683a5..0000000
--- a/libmad/configured/config.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* config.h. Generated by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to enable diagnostic debugging support. */
-/* #undef DEBUG */
-
-/* Define to enable experimental code. */
-/* #undef EXPERIMENTAL */
-
-/* Define to 1 if you have the <assert.h> header file. */
-#define HAVE_ASSERT_H 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-/* #undef HAVE_DLFCN_H */
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the `fcntl' function. */
-/* #undef HAVE_FCNTL */
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fork' function. */
-/* #undef HAVE_FORK */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define if your MIPS CPU supports a 2-operand MADD16 instruction. */
-/* #undef HAVE_MADD16_ASM */
-
-/* Define if your MIPS CPU supports a 2-operand MADD instruction. */
-/* #undef HAVE_MADD_ASM */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `pipe' function. */
-/* #undef HAVE_PIPE */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-/* #undef HAVE_SYS_WAIT_H */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
-
-/* Define to 1 if you have the `waitpid' function. */
-/* #undef HAVE_WAITPID */
-
-/* Define to disable debugging assertions. */
-/* #undef NDEBUG */
-
-/* Define to optimize for accuracy over speed. */
-/* #undef OPT_ACCURACY */
-
-/* Define to optimize for speed over accuracy. */
-/* #undef OPT_SPEED */
-
-/* Define to enable a fast subband synthesis approximation optimization. */
-/* #undef OPT_SSO */
-
-/* Define to influence a strict interpretation of the ISO/IEC standards, even
- if this is in opposition with best accepted practices. */
-/* #undef OPT_STRICT */
-
-/* Name of package */
-#define PACKAGE "libmad"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "support@underbit.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "MPEG Audio Decoder"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "MPEG Audio Decoder 0.15.1b"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libmad"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.15.1b"
-
-/* The size of a `int', as computed by sizeof. */
-#define SIZEOF_INT 4
-
-/* The size of a `long', as computed by sizeof. */
-#define SIZEOF_LONG 4
-
-/* The size of a `long long', as computed by sizeof. */
-#define SIZEOF_LONG_LONG 8
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.15.1b"
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define as `__inline' if that's what the C compiler calls it, or to nothing
- if it is not supported. */
-#define inline __inline
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
diff --git a/libmad/configured/mad.h b/libmad/configured/mad.h
deleted file mode 100644
index d483478..0000000
--- a/libmad/configured/mad.h
+++ /dev/null
@@ -1,948 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * If you would like to negotiate alternate licensing terms, you may do
- * so by contacting: Underbit Technologies, Inc. <info@underbit.com>
- */
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-# define FPM_INTEL
-
-
-
-# define SIZEOF_INT 4
-# define SIZEOF_LONG 4
-# define SIZEOF_LONG_LONG 8
-
-
-/* Id: version.h,v 1.24 2003/05/27 22:40:37 rob Exp */
-
-# ifndef LIBMAD_VERSION_H
-# define LIBMAD_VERSION_H
-
-# define MAD_VERSION_MAJOR 0
-# define MAD_VERSION_MINOR 15
-# define MAD_VERSION_PATCH 1
-# define MAD_VERSION_EXTRA " (beta)"
-
-# define MAD_VERSION_STRINGIZE(str) #str
-# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num)
-
-# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \
- MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \
- MAD_VERSION_STRING(MAD_VERSION_PATCH) \
- MAD_VERSION_EXTRA
-
-# define MAD_PUBLISHYEAR "2000-2003"
-# define MAD_AUTHOR "Underbit Technologies, Inc."
-# define MAD_EMAIL "info@underbit.com"
-
-extern char const mad_version[];
-extern char const mad_copyright[];
-extern char const mad_author[];
-extern char const mad_build[];
-
-# endif
-
-/* Id: fixed.h,v 1.36 2003/05/28 04:36:00 rob Exp */
-
-# ifndef LIBMAD_FIXED_H
-# define LIBMAD_FIXED_H
-
-# if SIZEOF_INT >= 4
-typedef signed int mad_fixed_t;
-
-typedef signed int mad_fixed64hi_t;
-typedef unsigned int mad_fixed64lo_t;
-# else
-typedef signed long mad_fixed_t;
-
-typedef signed long mad_fixed64hi_t;
-typedef unsigned long mad_fixed64lo_t;
-# endif
-
-# if defined(_MSC_VER)
-# define mad_fixed64_t signed __int64
-# elif 1 || defined(__GNUC__)
-# define mad_fixed64_t signed long long
-# endif
-
-# if defined(FPM_FLOAT)
-typedef double mad_sample_t;
-# else
-typedef mad_fixed_t mad_sample_t;
-# endif
-
-/*
- * Fixed-point format: 0xABBBBBBB
- * A == whole part (sign + 3 bits)
- * B == fractional part (28 bits)
- *
- * Values are signed two's complement, so the effective range is:
- * 0x80000000 to 0x7fffffff
- * -8.0 to +7.9999999962747097015380859375
- *
- * The smallest representable value is:
- * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9)
- *
- * 28 bits of fractional accuracy represent about
- * 8.6 digits of decimal accuracy.
- *
- * Fixed-point numbers can be added or subtracted as normal
- * integers, but multiplication requires shifting the 64-bit result
- * from 56 fractional bits back to 28 (and rounding.)
- *
- * Changing the definition of MAD_F_FRACBITS is only partially
- * supported, and must be done with care.
- */
-
-# define MAD_F_FRACBITS 28
-
-# if MAD_F_FRACBITS == 28
-# define MAD_F(x) ((mad_fixed_t) (x##L))
-# else
-# if MAD_F_FRACBITS < 28
-# warning "MAD_F_FRACBITS < 28"
-# define MAD_F(x) ((mad_fixed_t) \
- (((x##L) + \
- (1L << (28 - MAD_F_FRACBITS - 1))) >> \
- (28 - MAD_F_FRACBITS)))
-# elif MAD_F_FRACBITS > 28
-# error "MAD_F_FRACBITS > 28 not currently supported"
-# define MAD_F(x) ((mad_fixed_t) \
- ((x##L) << (MAD_F_FRACBITS - 28)))
-# endif
-# endif
-
-# define MAD_F_MIN ((mad_fixed_t) -0x80000000L)
-# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL)
-
-# define MAD_F_ONE MAD_F(0x10000000)
-
-# define mad_f_tofixed(x) ((mad_fixed_t) \
- ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5))
-# define mad_f_todouble(x) ((double) \
- ((x) / (double) (1L << MAD_F_FRACBITS)))
-
-# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS)
-# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1))
- /* (x should be positive) */
-
-# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS)
-
-# define mad_f_add(x, y) ((x) + (y))
-# define mad_f_sub(x, y) ((x) - (y))
-
-# if defined(FPM_FLOAT)
-# error "FPM_FLOAT not yet supported"
-
-# undef MAD_F
-# define MAD_F(x) mad_f_todouble(x)
-
-# define mad_f_mul(x, y) ((x) * (y))
-# define mad_f_scale64
-
-# undef ASO_ZEROCHECK
-
-# elif defined(FPM_64BIT)
-
-/*
- * This version should be the most accurate if 64-bit types are supported by
- * the compiler, although it may not be the most efficient.
- */
-# if defined(OPT_ACCURACY)
-# define mad_f_mul(x, y) \
- ((mad_fixed_t) \
- ((((mad_fixed64_t) (x) * (y)) + \
- (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS))
-# else
-# define mad_f_mul(x, y) \
- ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS))
-# endif
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-
-/* --- Intel --------------------------------------------------------------- */
-
-# elif defined(FPM_INTEL)
-
-# if defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning(disable: 4035) /* no return value */
-static __forceinline
-mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y)
-{
- enum {
- fracbits = MAD_F_FRACBITS
- };
-
- __asm {
- mov eax, x
- imul y
- shrd eax, edx, fracbits
- }
-
- /* implicit return of eax */
-}
-# pragma warning(pop)
-
-# define mad_f_mul mad_f_mul_inline
-# define mad_f_scale64
-# else
-/*
- * This Intel version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("imull %3" \
- : "=a" (lo), "=d" (hi) \
- : "%a" (x), "rm" (y) \
- : "cc")
-
-# if defined(OPT_ACCURACY)
-/*
- * This gives best accuracy but is not very fast.
- */
-# define MAD_F_MLA(hi, lo, x, y) \
- ({ mad_fixed64hi_t __hi; \
- mad_fixed64lo_t __lo; \
- MAD_F_MLX(__hi, __lo, (x), (y)); \
- asm ("addl %2,%0\n\t" \
- "adcl %3,%1" \
- : "=rm" (lo), "=rm" (hi) \
- : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \
- : "cc"); \
- })
-# endif /* OPT_ACCURACY */
-
-# if defined(OPT_ACCURACY)
-/*
- * Surprisingly, this is faster than SHRD followed by ADC.
- */
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed64hi_t __hi_; \
- mad_fixed64lo_t __lo_; \
- mad_fixed_t __result; \
- asm ("addl %4,%2\n\t" \
- "adcl %5,%3" \
- : "=rm" (__lo_), "=rm" (__hi_) \
- : "0" (lo), "1" (hi), \
- "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \
- : "cc"); \
- asm ("shrdl %3,%2,%1" \
- : "=rm" (__result) \
- : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-# else
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result; \
- asm ("shrdl %3,%2,%1" \
- : "=rm" (__result) \
- : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-# endif /* OPT_ACCURACY */
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-# endif
-
-/* --- ARM ----------------------------------------------------------------- */
-
-# elif defined(FPM_ARM)
-
-/*
- * This ARM V4 version is as accurate as FPM_64BIT but much faster. The
- * least significant bit is properly rounded at no CPU cycle cost!
- */
-# if 1
-/*
- * This is faster than the default implementation via MAD_F_MLX() and
- * mad_f_scale64().
- */
-# define mad_f_mul(x, y) \
- ({ mad_fixed64hi_t __hi; \
- mad_fixed64lo_t __lo; \
- mad_fixed_t __result; \
- asm ("smull %0, %1, %3, %4\n\t" \
- "movs %0, %0, lsr %5\n\t" \
- "adc %2, %0, %1, lsl %6" \
- : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \
- : "%r" (x), "r" (y), \
- "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-# endif
-
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("smull %0, %1, %2, %3" \
- : "=&r" (lo), "=&r" (hi) \
- : "%r" (x), "r" (y))
-
-# define MAD_F_MLA(hi, lo, x, y) \
- asm ("smlal %0, %1, %2, %3" \
- : "+r" (lo), "+r" (hi) \
- : "%r" (x), "r" (y))
-
-# define MAD_F_MLN(hi, lo) \
- asm ("rsbs %0, %2, #0\n\t" \
- "rsc %1, %3, #0" \
- : "=r" (lo), "=r" (hi) \
- : "0" (lo), "1" (hi) \
- : "cc")
-
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result; \
- asm ("movs %0, %1, lsr %3\n\t" \
- "adc %0, %0, %2, lsl %4" \
- : "=&r" (__result) \
- : "r" (lo), "r" (hi), \
- "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-
-/* --- MIPS ---------------------------------------------------------------- */
-
-# elif defined(FPM_MIPS)
-
-/*
- * This MIPS version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("mult %2,%3" \
- : "=l" (lo), "=h" (hi) \
- : "%r" (x), "r" (y))
-
-# if defined(HAVE_MADD_ASM)
-# define MAD_F_MLA(hi, lo, x, y) \
- asm ("madd %2,%3" \
- : "+l" (lo), "+h" (hi) \
- : "%r" (x), "r" (y))
-# elif defined(HAVE_MADD16_ASM)
-/*
- * This loses significant accuracy due to the 16-bit integer limit in the
- * multiply/accumulate instruction.
- */
-# define MAD_F_ML0(hi, lo, x, y) \
- asm ("mult %2,%3" \
- : "=l" (lo), "=h" (hi) \
- : "%r" ((x) >> 12), "r" ((y) >> 16))
-# define MAD_F_MLA(hi, lo, x, y) \
- asm ("madd16 %2,%3" \
- : "+l" (lo), "+h" (hi) \
- : "%r" ((x) >> 12), "r" ((y) >> 16))
-# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo))
-# endif
-
-# if defined(OPT_SPEED)
-# define mad_f_scale64(hi, lo) \
- ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS)))
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-# endif
-
-/* --- SPARC --------------------------------------------------------------- */
-
-# elif defined(FPM_SPARC)
-
-/*
- * This SPARC V8 version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("smul %2, %3, %0\n\t" \
- "rd %%y, %1" \
- : "=r" (lo), "=r" (hi) \
- : "%r" (x), "rI" (y))
-
-/* --- PowerPC ------------------------------------------------------------- */
-
-# elif defined(FPM_PPC)
-
-/*
- * This PowerPC version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- do { \
- asm ("mullw %0,%1,%2" \
- : "=r" (lo) \
- : "%r" (x), "r" (y)); \
- asm ("mulhw %0,%1,%2" \
- : "=r" (hi) \
- : "%r" (x), "r" (y)); \
- } \
- while (0)
-
-# if defined(OPT_ACCURACY)
-/*
- * This gives best accuracy but is not very fast.
- */
-# define MAD_F_MLA(hi, lo, x, y) \
- ({ mad_fixed64hi_t __hi; \
- mad_fixed64lo_t __lo; \
- MAD_F_MLX(__hi, __lo, (x), (y)); \
- asm ("addc %0,%2,%3\n\t" \
- "adde %1,%4,%5" \
- : "=r" (lo), "=r" (hi) \
- : "%r" (lo), "r" (__lo), \
- "%r" (hi), "r" (__hi) \
- : "xer"); \
- })
-# endif
-
-# if defined(OPT_ACCURACY)
-/*
- * This is slower than the truncating version below it.
- */
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result, __round; \
- asm ("rotrwi %0,%1,%2" \
- : "=r" (__result) \
- : "r" (lo), "i" (MAD_F_SCALEBITS)); \
- asm ("extrwi %0,%1,1,0" \
- : "=r" (__round) \
- : "r" (__result)); \
- asm ("insrwi %0,%1,%2,0" \
- : "+r" (__result) \
- : "r" (hi), "i" (MAD_F_SCALEBITS)); \
- asm ("add %0,%1,%2" \
- : "=r" (__result) \
- : "%r" (__result), "r" (__round)); \
- __result; \
- })
-# else
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result; \
- asm ("rotrwi %0,%1,%2" \
- : "=r" (__result) \
- : "r" (lo), "i" (MAD_F_SCALEBITS)); \
- asm ("insrwi %0,%1,%2,0" \
- : "+r" (__result) \
- : "r" (hi), "i" (MAD_F_SCALEBITS)); \
- __result; \
- })
-# endif
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-
-/* --- Default ------------------------------------------------------------- */
-
-# elif defined(FPM_DEFAULT)
-
-/*
- * This version is the most portable but it loses significant accuracy.
- * Furthermore, accuracy is biased against the second argument, so care
- * should be taken when ordering operands.
- *
- * The scale factors are constant as this is not used with SSO.
- *
- * Pre-rounding is required to stay within the limits of compliance.
- */
-# if defined(OPT_SPEED)
-# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16))
-# else
-# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \
- (((y) + (1L << 15)) >> 16))
-# endif
-
-/* ------------------------------------------------------------------------- */
-
-# else
-# error "no FPM selected"
-# endif
-
-/* default implementations */
-
-# if !defined(mad_f_mul)
-# define mad_f_mul(x, y) \
- ({ register mad_fixed64hi_t __hi; \
- register mad_fixed64lo_t __lo; \
- MAD_F_MLX(__hi, __lo, (x), (y)); \
- mad_f_scale64(__hi, __lo); \
- })
-# endif
-
-# if !defined(MAD_F_MLA)
-# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y)))
-# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y)))
-# define MAD_F_MLN(hi, lo) ((lo) = -(lo))
-# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo))
-# endif
-
-# if !defined(MAD_F_ML0)
-# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y))
-# endif
-
-# if !defined(MAD_F_MLN)
-# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi))
-# endif
-
-# if !defined(MAD_F_MLZ)
-# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo))
-# endif
-
-# if !defined(mad_f_scale64)
-# if defined(OPT_ACCURACY)
-# define mad_f_scale64(hi, lo) \
- ((((mad_fixed_t) \
- (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \
- ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1)
-# else
-# define mad_f_scale64(hi, lo) \
- ((mad_fixed_t) \
- (((hi) << (32 - MAD_F_SCALEBITS)) | \
- ((lo) >> MAD_F_SCALEBITS)))
-# endif
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-# endif
-
-/* C routines */
-
-mad_fixed_t mad_f_abs(mad_fixed_t);
-mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t);
-
-# endif
-
-/* Id: bit.h,v 1.11 2003/05/27 22:40:36 rob Exp */
-
-# ifndef LIBMAD_BIT_H
-# define LIBMAD_BIT_H
-
-struct mad_bitptr {
- unsigned char const *byte;
- unsigned short cache;
- unsigned short left;
-};
-
-void mad_bit_init(struct mad_bitptr *, unsigned char const *);
-
-# define mad_bit_finish(bitptr) /* nothing */
-
-unsigned int mad_bit_length(struct mad_bitptr const *,
- struct mad_bitptr const *);
-
-# define mad_bit_bitsleft(bitptr) ((bitptr)->left)
-unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *);
-
-void mad_bit_skip(struct mad_bitptr *, unsigned int);
-unsigned long mad_bit_read(struct mad_bitptr *, unsigned int);
-void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long);
-
-unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short);
-
-# endif
-
-/* Id: timer.h,v 1.15 2003/05/27 22:40:37 rob Exp */
-
-# ifndef LIBMAD_TIMER_H
-# define LIBMAD_TIMER_H
-
-typedef struct {
- signed long seconds; /* whole seconds */
- unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */
-} mad_timer_t;
-
-extern mad_timer_t const mad_timer_zero;
-
-# define MAD_TIMER_RESOLUTION 352800000UL
-
-enum mad_units {
- MAD_UNITS_HOURS = -2,
- MAD_UNITS_MINUTES = -1,
- MAD_UNITS_SECONDS = 0,
-
- /* metric units */
-
- MAD_UNITS_DECISECONDS = 10,
- MAD_UNITS_CENTISECONDS = 100,
- MAD_UNITS_MILLISECONDS = 1000,
-
- /* audio sample units */
-
- MAD_UNITS_8000_HZ = 8000,
- MAD_UNITS_11025_HZ = 11025,
- MAD_UNITS_12000_HZ = 12000,
-
- MAD_UNITS_16000_HZ = 16000,
- MAD_UNITS_22050_HZ = 22050,
- MAD_UNITS_24000_HZ = 24000,
-
- MAD_UNITS_32000_HZ = 32000,
- MAD_UNITS_44100_HZ = 44100,
- MAD_UNITS_48000_HZ = 48000,
-
- /* video frame/field units */
-
- MAD_UNITS_24_FPS = 24,
- MAD_UNITS_25_FPS = 25,
- MAD_UNITS_30_FPS = 30,
- MAD_UNITS_48_FPS = 48,
- MAD_UNITS_50_FPS = 50,
- MAD_UNITS_60_FPS = 60,
-
- /* CD audio frames */
-
- MAD_UNITS_75_FPS = 75,
-
- /* video drop-frame units */
-
- MAD_UNITS_23_976_FPS = -24,
- MAD_UNITS_24_975_FPS = -25,
- MAD_UNITS_29_97_FPS = -30,
- MAD_UNITS_47_952_FPS = -48,
- MAD_UNITS_49_95_FPS = -50,
- MAD_UNITS_59_94_FPS = -60
-};
-
-# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero))
-
-int mad_timer_compare(mad_timer_t, mad_timer_t);
-
-# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero)
-
-void mad_timer_negate(mad_timer_t *);
-mad_timer_t mad_timer_abs(mad_timer_t);
-
-void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long);
-void mad_timer_add(mad_timer_t *, mad_timer_t);
-void mad_timer_multiply(mad_timer_t *, signed long);
-
-signed long mad_timer_count(mad_timer_t, enum mad_units);
-unsigned long mad_timer_fraction(mad_timer_t, unsigned long);
-void mad_timer_string(mad_timer_t, char *, char const *,
- enum mad_units, enum mad_units, unsigned long);
-
-# endif
-
-/* Id: stream.h,v 1.18 2003/05/27 22:40:37 rob Exp */
-
-# ifndef LIBMAD_STREAM_H
-# define LIBMAD_STREAM_H
-
-
-# define MAD_BUFFER_GUARD 8
-# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD)
-
-enum mad_error {
- MAD_ERROR_NONE = 0x0000, /* no error */
-
- MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */
- MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */
-
- MAD_ERROR_NOMEM = 0x0031, /* not enough memory */
-
- MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */
- MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */
- MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */
- MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */
- MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */
-
- MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */
- MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */
- MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */
- MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */
- MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */
- MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */
- MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */
- MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */
- MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */
- MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */
- MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */
- MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */
-};
-
-# define MAD_RECOVERABLE(error) ((error) & 0xff00)
-
-struct mad_stream {
- unsigned char const *buffer; /* input bitstream buffer */
- unsigned char const *bufend; /* end of buffer */
- unsigned long skiplen; /* bytes to skip before next frame */
-
- int sync; /* stream sync found */
- unsigned long freerate; /* free bitrate (fixed) */
-
- unsigned char const *this_frame; /* start of current frame */
- unsigned char const *next_frame; /* start of next frame */
- struct mad_bitptr ptr; /* current processing bit pointer */
-
- struct mad_bitptr anc_ptr; /* ancillary bits pointer */
- unsigned int anc_bitlen; /* number of ancillary bits */
-
- unsigned char (*main_data)[MAD_BUFFER_MDLEN];
- /* Layer III main_data() */
- unsigned int md_len; /* bytes in main_data */
-
- int options; /* decoding options (see below) */
- enum mad_error error; /* error code (see above) */
-};
-
-enum {
- MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */
- MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */
-# if 0 /* not yet implemented */
- MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */
- MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */
- MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */
-# endif
-};
-
-void mad_stream_init(struct mad_stream *);
-void mad_stream_finish(struct mad_stream *);
-
-# define mad_stream_options(stream, opts) \
- ((void) ((stream)->options = (opts)))
-
-void mad_stream_buffer(struct mad_stream *,
- unsigned char const *, unsigned long);
-void mad_stream_skip(struct mad_stream *, unsigned long);
-
-int mad_stream_sync(struct mad_stream *);
-
-char const *mad_stream_errorstr(struct mad_stream const *);
-
-# endif
-
-/* Id: frame.h,v 1.19 2003/05/27 22:40:36 rob Exp */
-
-# ifndef LIBMAD_FRAME_H
-# define LIBMAD_FRAME_H
-
-
-enum mad_layer {
- MAD_LAYER_I = 1, /* Layer I */
- MAD_LAYER_II = 2, /* Layer II */
- MAD_LAYER_III = 3 /* Layer III */
-};
-
-enum mad_mode {
- MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */
- MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */
- MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */
- MAD_MODE_STEREO = 3 /* normal LR stereo */
-};
-
-enum mad_emphasis {
- MAD_EMPHASIS_NONE = 0, /* no emphasis */
- MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */
- MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */
- MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */
-};
-
-struct mad_header {
- enum mad_layer layer; /* audio layer (1, 2, or 3) */
- enum mad_mode mode; /* channel mode (see above) */
- int mode_extension; /* additional mode info */
- enum mad_emphasis emphasis; /* de-emphasis to use (see above) */
-
- unsigned long bitrate; /* stream bitrate (bps) */
- unsigned int samplerate; /* sampling frequency (Hz) */
-
- unsigned short crc_check; /* frame CRC accumulator */
- unsigned short crc_target; /* final target CRC checksum */
-
- int flags; /* flags (see below) */
- int private_bits; /* private bits (see below) */
-
- mad_timer_t duration; /* audio playing time of frame */
-};
-
-struct mad_frame {
- struct mad_header header; /* MPEG audio header */
-
- int options; /* decoding options (from stream) */
-
- mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */
- mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */
-};
-
-# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1)
-# define MAD_NSBSAMPLES(header) \
- ((header)->layer == MAD_LAYER_I ? 12 : \
- (((header)->layer == MAD_LAYER_III && \
- ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36))
-
-enum {
- MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */
- MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */
-
- MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */
- MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */
- MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */
- MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */
-
- MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */
- MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */
- MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */
-
- MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */
- MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */
- MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */
-};
-
-enum {
- MAD_PRIVATE_HEADER = 0x0100, /* header private bit */
- MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */
-};
-
-void mad_header_init(struct mad_header *);
-
-# define mad_header_finish(header) /* nothing */
-
-int mad_header_decode(struct mad_header *, struct mad_stream *);
-
-void mad_frame_init(struct mad_frame *);
-void mad_frame_finish(struct mad_frame *);
-
-int mad_frame_decode(struct mad_frame *, struct mad_stream *);
-
-void mad_frame_mute(struct mad_frame *);
-
-# endif
-
-/* Id: synth.h,v 1.14 2003/05/27 22:40:37 rob Exp */
-
-# ifndef LIBMAD_SYNTH_H
-# define LIBMAD_SYNTH_H
-
-
-struct mad_pcm {
- unsigned int samplerate; /* sampling frequency (Hz) */
- unsigned short channels; /* number of channels */
- unsigned short length; /* number of samples per channel */
- mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */
-};
-
-struct mad_synth {
- mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */
- /* [ch][eo][peo][s][v] */
-
- unsigned int phase; /* current processing phase */
-
- struct mad_pcm pcm; /* PCM output */
-};
-
-/* single channel PCM selector */
-enum {
- MAD_PCM_CHANNEL_SINGLE = 0
-};
-
-/* dual channel PCM selector */
-enum {
- MAD_PCM_CHANNEL_DUAL_1 = 0,
- MAD_PCM_CHANNEL_DUAL_2 = 1
-};
-
-/* stereo PCM selector */
-enum {
- MAD_PCM_CHANNEL_STEREO_LEFT = 0,
- MAD_PCM_CHANNEL_STEREO_RIGHT = 1
-};
-
-void mad_synth_init(struct mad_synth *);
-
-# define mad_synth_finish(synth) /* nothing */
-
-void mad_synth_mute(struct mad_synth *);
-
-void mad_synth_frame(struct mad_synth *, struct mad_frame const *);
-
-# endif
-
-/* Id: decoder.h,v 1.16 2003/05/27 22:40:36 rob Exp */
-
-# ifndef LIBMAD_DECODER_H
-# define LIBMAD_DECODER_H
-
-
-enum mad_decoder_mode {
- MAD_DECODER_MODE_SYNC = 0,
- MAD_DECODER_MODE_ASYNC
-};
-
-enum mad_flow {
- MAD_FLOW_CONTINUE = 0x0000, /* continue normally */
- MAD_FLOW_STOP = 0x0010, /* stop decoding normally */
- MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */
- MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */
-};
-
-struct mad_decoder {
- enum mad_decoder_mode mode;
-
- int options;
-
- struct {
- long pid;
- int in;
- int out;
- } async;
-
- struct {
- struct mad_stream stream;
- struct mad_frame frame;
- struct mad_synth synth;
- } *sync;
-
- void *cb_data;
-
- enum mad_flow (*input_func)(void *, struct mad_stream *);
- enum mad_flow (*header_func)(void *, struct mad_header const *);
- enum mad_flow (*filter_func)(void *,
- struct mad_stream const *, struct mad_frame *);
- enum mad_flow (*output_func)(void *,
- struct mad_header const *, struct mad_pcm *);
- enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *);
- enum mad_flow (*message_func)(void *, void *, unsigned int *);
-};
-
-void mad_decoder_init(struct mad_decoder *, void *,
- enum mad_flow (*)(void *, struct mad_stream *),
- enum mad_flow (*)(void *, struct mad_header const *),
- enum mad_flow (*)(void *,
- struct mad_stream const *,
- struct mad_frame *),
- enum mad_flow (*)(void *,
- struct mad_header const *,
- struct mad_pcm *),
- enum mad_flow (*)(void *,
- struct mad_stream *,
- struct mad_frame *),
- enum mad_flow (*)(void *, void *, unsigned int *));
-int mad_decoder_finish(struct mad_decoder *);
-
-# define mad_decoder_options(decoder, opts) \
- ((void) ((decoder)->options = (opts)))
-
-int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode);
-int mad_decoder_message(struct mad_decoder *, void *, unsigned int *);
-
-# endif
-
-# ifdef __cplusplus
-}
-# endif
diff --git a/libmad/libmad.vcxproj.filters b/libmad/libmad.vcxproj.filters
deleted file mode 100644
index ebc6bb9..0000000
--- a/libmad/libmad.vcxproj.filters
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Sources">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\bit.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\decoder.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\fixed.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\frame.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\huffman.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\layer12.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\layer3.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\stream.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\synth.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\timer.c">
- <Filter>Sources</Filter>
- </ClCompile>
- <ClCompile Include="src\version.c">
- <Filter>Sources</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\bit.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="configured\config.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\decoder.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\fixed.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\frame.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\global.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\huffman.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\layer12.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\layer3.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="configured\mad.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\stream.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\synth.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\timer.h">
- <Filter>Sources</Filter>
- </ClInclude>
- <ClInclude Include="src\version.h">
- <Filter>Sources</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <None Include="src\D.dat">
- <Filter>Sources</Filter>
- </None>
- <None Include="src\imdct_s.dat">
- <Filter>Sources</Filter>
- </None>
- <None Include="src\qc_table.dat">
- <Filter>Sources</Filter>
- </None>
- <None Include="src\rq_table.dat">
- <Filter>Sources</Filter>
- </None>
- <None Include="src\sf_table.dat">
- <Filter>Sources</Filter>
- </None>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/libmad/src/CHANGES b/libmad/src/CHANGES
deleted file mode 100644
index 9291760..0000000
--- a/libmad/src/CHANGES
+++ /dev/null
@@ -1,338 +0,0 @@
-
- libmad - MPEG audio decoder library
- Copyright (C) 2000-2004 Underbit Technologies, Inc.
-
- $Id: CHANGES,v 1.14 2004/02/17 02:02:03 rob Exp $
-
-===============================================================================
-
-Version 0.15.1 (beta)
-
- * Updated to autoconf 2.59, automake 1.8.2, libtool 1.5.2.
-
- * Replaced Layer III IMDCT routine with one based on a faster algorithm,
- improving both speed and accuracy.
-
- * Improved portability of the Huffman table initialization.
-
- * Fixed a problem that could result in an assertion failure in layer3.c
- due to an invalid Layer III free format bitrate.
-
- * Improved the robustness of Layer II bitrate/mode combinations, and added
- a new MAD_ERROR_BADMODE error enum. The allowability of low-bitrate
- stereo streams is influenced by the --enable-strict-iso option to
- `configure'.
-
-Version 0.15.0 (beta)
-
- * Updated to autoconf 2.57, automake 1.7.5, libtool 1.4.3.
-
- * Added new mad_f_div() API routine.
-
- * Added a 64th entry to the Layer I/Layer II scalefactor table, for better
- compatibility with existing streams. The --enable-strict-iso option to
- `configure' can be used to disable use of this entry.
-
- * Modified the header decoding routine to allow the reserved emphasis
- value, for better compatibility with existing streams. The
- --enable-strict-iso option to `configure' can be used to restore the
- previous behavior of reporting this value as an error.
-
- * Added new MAD_EMPHASIS_RESERVED enumeration constant.
-
- * Fixed a bug in the ARM version of mad_f_scale64() discovered by Andre
- McCurdy.
-
- * Rewrote PowerPC assembly for minor gains.
-
- * Modified mad_timer_fraction() to avoid the possibility of division by
- zero when 0 is passed as the second argument.
-
- * Fixed a non-fatal problem caused by attempting to designate ancillary
- bits in Layer III after a decoding error.
-
- * Changed to build a shared library by default.
-
- * Changed to use native Cygwin build by default; give --host=mingw32 to
- `configure' to use MinGW (and avoid a dependency on the Cygwin DLL).
-
-Version 0.14.2 (beta)
-
- * Changed Cygwin builds to use MinGW; resulting Win32 executables no
- longer have a dependency on Cygwin DLLs.
-
- * Added a new mad_stream_errorstr() API function to libmad for retrieving
- a string description of the current error condition.
-
-Version 0.14.1 (beta)
-
- * Updated config.guess and config.sub to latest upstream versions.
-
- * Enabled libtool versioning rather than release numbering.
-
- * Improved the documentation in minimad.c.
-
- * Several other small fixes.
-
-Version 0.14.0 (beta)
-
- * Added a 64-bit FPM negation operation to improve performance of subband
- synthesis on some platforms.
-
- * Improved MSVC++ portability and added MSVC++ project files.
-
- * Added rounding to Layer III requantization for slightly better accuracy.
-
-Version 0.13.0 (beta)
-
- * Ancillary data is now properly extracted from Layer III streams.
-
- * Rewrote the Layer III joint stereo decoding routine to correct a major
- MPEG-2 problem and a minor MPEG-1 problem decoding intensity stereo.
-
- * Eliminated the dependency on sign-extending right shifts for Layer I and
- Layer II.
-
- * Renamed `private' field to `private_bits' for better C++ compatibility.
-
- * Gratuitously renamed `sfreq' field to `samplerate' and
- MAD_ERROR_BADSAMPLEFREQ constant to MAD_ERROR_BADSAMPLERATE.
-
- * Added `samplerate' and `channels' fields to synth.pcm struct to allow
- these to be different from the decoded frame, and for simpler access.
-
- * Added new mad_stream_options() and mad_decoder_options() API entries for
- special runtime decoding options.
-
- * Added new MAD_OPTION_IGNORECRC and MAD_OPTION_HALFSAMPLERATE options.
-
- * Added new MAD_FLAG_FREEFORMAT indicator flag.
-
- * Fixed some bugs in the async decoder.
-
- * Added a new mad_timer_multiply() API routine.
-
- * Eliminated `+' from asm constraints under Intel for better compatibility
- with some compilers.
-
- * Fixed a PIC-related problem in imdct_l_arm.S.
-
- * Eliminated a static variable to make libmad thread-safe.
-
-Version 0.12.5 (beta)
-
- * Modified Layer III requantization to occur during Huffman decoding for
- significant performance gains.
-
- * Optimized short block IMDCT by eliminating redundant calculations.
-
- * Made several other Layer III performance improvements; added
- ASO_INTERLEAVE1, ASO_INTERLEAVE2, and ASO_ZEROCHECK
- architecture-specific options for best performance on various
- architectures.
-
- * Optimized synthesis DCT to store result values as soon as they are
- calculated.
-
-Version 0.12.4 (beta)
-
- * New PowerPC fixed-point assembly courtesy of David Blythe.
-
- * Reorganized fixed-point assembly routines for easier maintenance and
- better performance.
-
- * Improved performance of subband synthesis through better indexing and
- fewer local variables.
-
- * Added alias reduction for the lower two subbands of mixed short blocks,
- per a report of ambiguity with ISO/IEC 11172-3 and for uniformity with
- most other implementations. Also improved alias reduction performance
- using multiply/accumulate.
-
- * Added --enable-strict-iso option to `configure' to override best
- accepted practices such as the alias reduction for mixed short blocks.
-
- * Improved performance of Layer III IMDCT by using longer
- multiply/accumulate runs where possible.
-
-Version 0.12.3 (beta)
-
- * Added MPEG 2.5 support.
-
- * Added preliminary support for parameterizing the binary point position
- in the fixed-point representation.
-
- * Added multiply/accumulate optimization to the Layer III IMDCT for long
- blocks.
-
- * Fixed a bug in the handling of Layer III mixed_block_flag.
-
- * Fixed a configure problem when multiple -O CFLAGS are present.
-
-Version 0.12.2 (beta)
-
- * Rearranged the synthesis polyphase filterbank memory vector for better
- locality of reference, and rewrote mad_synth_frame() to accommodate,
- resulting in improved performance.
-
- * Discovered a combination of compiler optimization flags that further
- improve performance.
-
- * Changed some array references in layer3.c to pointer derefs.
-
-Version 0.12.1 (beta)
-
- * Resolved the intensity + MS joint stereo issue (a simple bug).
- OPT_ISKLUGE is no longer considered to be a kluge.
-
- * Fixed another, hopefully last main_data memory bug.
-
- * Split part of struct mad_frame into struct mad_header for convenience
- and size.
-
-Version 0.12.0 (alpha)
-
- * Changed the build environment to use automake and libtool. A libmad
- shared library can now be built using the --enable-shared option to
- `configure'.
-
- * Added another callback to MAD's high-level decoder API after the frame
- header has been read but before the frame's audio data is decoded.
-
- * Streamlined header processing so that mad_frame_decode() can be called
- with or without having already called mad_frame_header().
-
- * Fixed some other header reading miscellany, including CRC handling and
- free bitrate detection, and frame length verification with free
- bitrates.
-
- * Fixed a problem with Layer III free bitrates > 320 kbps. The main_data
- buffer size should now be large enough to handle any size frame, by
- virtue of the maximum possible part2_3_length.
-
- * Further developed the async API; arbitrary messages can now be passed to
- the subsidiary decoding process.
-
- * Streamlined timer.c and extended its interface. It now has support for
- video frame/field lengths, including output support for drop-frame
- encoding.
-
- * Replaced many constant integer preprocessor defines with enums.
-
-Version 0.11.4 (beta)
-
- * Fixed free format bitrate discovery.
-
- * Changed the timer implementation and extended its interface.
-
- * Integrated Nicolas Pitre's patch for pre-shifting at compile-time and
- for better multiply/accumulate code output.
-
- * Applied Simon Burge's patch to imdct_l_arm.S for a.out compatibility.
-
- * Added -mtune=strongarm for all ARM targets.
-
-Version 0.11.3 (beta)
-
- * Added new --enable-speed and --enable-accuracy options for `configure'
- to automatically select appropriate SSO/ASO options, et al.
-
- * Modified subband synthesis to use multiply/accumulate optimization (if
- available) for better speed and/or accuracy.
-
- * Incorporated Andre McCurdy's changes for further rounding optimizations
- in the rest of his code.
-
-Version 0.11.2 (beta)
-
- * Incorporated Nicolas Pitre's ARM assembly and parameterized scaling
- changes.
-
- * Incorporated Andre McCurdy's ARM assembly optimization (used only if
- --enable-aso is given to `configure' to enable architecture-specific
- optimizations.)
-
- * Reduced FPM_INTEL assembly to two instructions.
-
- * Fixed accuracy problems with certain FPM modes in synth.c.
-
- * Improved the accuracy of FPM_APPROX.
-
- * Improved the accuracy of SSO.
-
- * Improved sync discovery by checking for a sync word in the following
- frame.
-
- * Minor code clean-up.
-
- * Added experimental rules for generating a libmad.so shared library.
-
-Version 0.11.1 (beta)
-
- * Moved libmad code into a separate directory.
-
- * Changed SSO to be disabled by default, as output accuracy is deemed to
- be more important than speed in the general case.
-
- * Fixed a bug in Layer III sanity checking that could cause a crash on
- certain random data input.
-
- * Extended the Layer III requantization table from 8191 to 8206 as some
- encoders are known to use these values, even though ISO/IEC 11172-3
- suggests the maximum should be 8191.
-
-Version 0.11.0 (beta)
-
- * Implemented MPEG-2 extension to Lower Sampling Frequencies.
-
- * Improved Layer III performance by avoiding IMDCT calculation when all
- input samples are zero.
-
- * Significantly reduced size of Layer II tables.
-
-Version 0.10.3 (beta)
-
- * Improved SSO output quality.
-
- * Made portable to cygwin.
-
- * Localized memory references in III_huffdecode() for better performance.
-
-Version 0.10.2 (beta)
-
- * Rewrote Layer III long block 36-point IMDCT routine for better
- performance.
-
- * Improved subband synthesis fixed-point games somewhat.
-
-Version 0.10.1 (beta)
-
- * Added a subband synthesis optimization (SSO) which involves modifying
- the fixed-point multiplication method during windowing. This produces
- subtle differences in the output but improves performance greatly.
-
- * Added I_STEREO and MS_STEREO flags to frame struct.
-
- * Eliminated privately-used CRCFAILED flag.
-
- * Fixed a bug where Layer III decoding could crash on some badly-formatted
- (e.g. non-MPEG) bitstreams.
-
- * Miscellaneous code clean-up.
-
-Version 0.10.0 (beta)
-
- * Added SPARC fixed-point math support.
-
- * Revamped libmad API for better high- and low-level support.
-
- * Documented more of the code.
-
- * Changed sync semantics such that new stream buffers are assumed to be
- sync-aligned.
-
- * Changed Layer III to dynamically allocate static memory so as not to
- waste it (about 6.4K) when only decoding Layer I or Layer II.
-
-===============================================================================
-
diff --git a/libmad/src/COPYING b/libmad/src/COPYING
deleted file mode 100644
index d60c31a..0000000
--- a/libmad/src/COPYING
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/libmad/src/COPYRIGHT b/libmad/src/COPYRIGHT
deleted file mode 100644
index ed91d2b..0000000
--- a/libmad/src/COPYRIGHT
+++ /dev/null
@@ -1,21 +0,0 @@
-
- libmad - MPEG audio decoder library
- Copyright (C) 2000-2004 Underbit Technologies, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- If you would like to negotiate alternate licensing terms, you may do
- so by contacting: Underbit Technologies, Inc. <info@underbit.com>
-
diff --git a/libmad/src/CREDITS b/libmad/src/CREDITS
deleted file mode 100644
index 72ec72e..0000000
--- a/libmad/src/CREDITS
+++ /dev/null
@@ -1,116 +0,0 @@
-
- libmad - MPEG audio decoder library
- Copyright (C) 2000-2004 Underbit Technologies, Inc.
-
- $Id: CREDITS,v 1.5 2004/02/17 02:02:03 rob Exp $
-
-===============================================================================
-
-AUTHOR
-
- Except where otherwise noted, all code was authored by:
-
- Robert Leslie <rob@underbit.com>
-
-CONTRIBUTORS
-
- Significant contributions have been incorporated with thanks to:
-
- Anonymous
- 2002/03/15: frame.c
- - Reported problem with use of reserved emphasis value.
- 2003/08/31: layer12.c
- - Suggested support for certain disallowed bitrate/mode
- combinations.
-
- Niek Albers <info@daansystems.com>
- 2003/04/21: layer3.c
- - Reported runtime uninitialized use of `ptr' in designating
- ancillary bits after a decoding error.
-
- Christian Biere <cbiere@users.sourceforge.net>
- 2003/02/01: frame.c
- - Reported assertion failure in layer3.c due to an
- invalid/unsupported Layer III free format bitrate.
-
- David Blythe <blythe@routefree.com>
- 2001/01/30: fixed.h
- - Provided initial PowerPC fixed-point assembly.
-
- Simon Burge <simonb@wasabisystems.com>
- 2000/09/20: imdct_l_arm.S
- - Suggested patch for a.out compatibility.
-
- Brian Cameron <Brian.Cameron@sun.com>
- 2003/07/02: huffman.c
- - Suggested changes for improved portability.
-
- Joshua Haberman <joshua@haberman.com>
- 2001/08/10: decoder.c, huffman.c
- - Suggested portability fixes.
-
- Timothy King <lordzork@lordzork.com>
- 2002/05/04: sf_table.dat, layer12.c
- - Reported problem with use of (missing) scalefactor index 63.
-
- Felix von Leitner <felix-mad@fefe.de>
- 2003/01/21: fixed.h
- - Suggested Intel scaling alternative for possible speedup.
-
- Andre McCurdy <armccurdy@yahoo.co.uk>
- 2000/08/10: imdct_l_arm.S
- - ARM optimized assembly replacement for III_imdct_l().
- 2000/09/15: imdct_l_arm.S
- - Applied Nicolas Pitre's rounding optimisation in all remaining
- places.
- 2001/02/10: layer3.c
- - Inspiration for Huffman decoding and requantization rewrite, and
- other miscellany.
- 2001/03/24: imdct_l_arm.S
- - Corrected PIC unsafe code.
- 2002/02/16: fixed.h
- - Discovered bug in ARM version of mad_f_scale64().
-
- Haruhiko OGASAWARA <theta@m1.interq.or.jp>
- 2001/01/28: layer3.c
- - Reported discrepancy in alias reduction for mixed short blocks.
-
- Brett Paterson <brett@fmod.org>
- 2001/10/28: global.h
- - Reported missing <assert.h> et al. under MS Embedded Visual C.
-
- Sean 'Shaleh' Perry <shaleh@via.net>
- 2000/04/04: fixed.h
- - Suggested use of size-dependent typedefs.
- 2001/10/22: config.guess, config.sub
- - Keep up to date for proper Debian packaging.
-
- Bertrand Petit <eemad@phoe.frmug.org>
- 2001/11/05: synth.h
- - Suggested PCM channel enumeration constants.
- 2001/11/05: stream.h
- - Suggested MAD_ERROR_NONE enumeration constant.
- 2001/11/05: stream.c
- - Suggested mad_stream_errorstr() function.
-
- Nicolas Pitre <nico@cam.org>
- 2000/09/09: fixed.h
- - Parameterized all scaling for correct use of all multiplication
- methods within mad_synth_frame().
- - Rewrote the FPM_ARM version of mad_f_mul() so we have 64-bit
- multiplication result, rounding and scaling with 3 instructions.
- 2000/09/09: imdct_l_arm.S
- - Optimized rounding + scaling operations.
- 2000/09/17: synth.c
- - Changed D[] run-time shifts to compile-time.
- - Modified synthesis for better multiply/accumulate code output.
- 2001/08/11: fixed.h, synth.c
- - Suggested 64-bit FPM negation and negative term factorization
- during synthesis.
- 2001/08/11: fixed.h
- - Suggested unrounded behavior for FPM_DEFAULT when OPT_SPEED.
- 2001/11/19: fixed.c
- - Suggested computation of any resampling ratio.
-
-===============================================================================
-
diff --git a/libmad/src/D.dat b/libmad/src/D.dat
deleted file mode 100644
index 4a7fa4f..0000000
--- a/libmad/src/D.dat
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: D.dat,v 1.9 2004/01/23 09:41:32 rob Exp $
- */
-
-/*
- * These are the coefficients for the subband synthesis window. This is a
- * reordered version of Table B.3 from ISO/IEC 11172-3.
- *
- * Every value is parameterized so that shift optimizations can be made at
- * compile-time. For example, every value can be right-shifted 12 bits to
- * minimize multiply instruction times without any loss of accuracy.
- */
-
- { PRESHIFT(0x00000000) /* 0.000000000 */, /* 0 */
- -PRESHIFT(0x0001d000) /* -0.000442505 */,
- PRESHIFT(0x000d5000) /* 0.003250122 */,
- -PRESHIFT(0x001cb000) /* -0.007003784 */,
- PRESHIFT(0x007f5000) /* 0.031082153 */,
- -PRESHIFT(0x01421000) /* -0.078628540 */,
- PRESHIFT(0x019ae000) /* 0.100311279 */,
- -PRESHIFT(0x09271000) /* -0.572036743 */,
- PRESHIFT(0x1251e000) /* 1.144989014 */,
- PRESHIFT(0x09271000) /* 0.572036743 */,
- PRESHIFT(0x019ae000) /* 0.100311279 */,
- PRESHIFT(0x01421000) /* 0.078628540 */,
- PRESHIFT(0x007f5000) /* 0.031082153 */,
- PRESHIFT(0x001cb000) /* 0.007003784 */,
- PRESHIFT(0x000d5000) /* 0.003250122 */,
- PRESHIFT(0x0001d000) /* 0.000442505 */,
-
- PRESHIFT(0x00000000) /* 0.000000000 */,
- -PRESHIFT(0x0001d000) /* -0.000442505 */,
- PRESHIFT(0x000d5000) /* 0.003250122 */,
- -PRESHIFT(0x001cb000) /* -0.007003784 */,
- PRESHIFT(0x007f5000) /* 0.031082153 */,
- -PRESHIFT(0x01421000) /* -0.078628540 */,
- PRESHIFT(0x019ae000) /* 0.100311279 */,
- -PRESHIFT(0x09271000) /* -0.572036743 */,
- PRESHIFT(0x1251e000) /* 1.144989014 */,
- PRESHIFT(0x09271000) /* 0.572036743 */,
- PRESHIFT(0x019ae000) /* 0.100311279 */,
- PRESHIFT(0x01421000) /* 0.078628540 */,
- PRESHIFT(0x007f5000) /* 0.031082153 */,
- PRESHIFT(0x001cb000) /* 0.007003784 */,
- PRESHIFT(0x000d5000) /* 0.003250122 */,
- PRESHIFT(0x0001d000) /* 0.000442505 */ },
-
- { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 1 */
- -PRESHIFT(0x0001f000) /* -0.000473022 */,
- PRESHIFT(0x000da000) /* 0.003326416 */,
- -PRESHIFT(0x00207000) /* -0.007919312 */,
- PRESHIFT(0x007d0000) /* 0.030517578 */,
- -PRESHIFT(0x0158d000) /* -0.084182739 */,
- PRESHIFT(0x01747000) /* 0.090927124 */,
- -PRESHIFT(0x099a8000) /* -0.600219727 */,
- PRESHIFT(0x124f0000) /* 1.144287109 */,
- PRESHIFT(0x08b38000) /* 0.543823242 */,
- PRESHIFT(0x01bde000) /* 0.108856201 */,
- PRESHIFT(0x012b4000) /* 0.073059082 */,
- PRESHIFT(0x0080f000) /* 0.031478882 */,
- PRESHIFT(0x00191000) /* 0.006118774 */,
- PRESHIFT(0x000d0000) /* 0.003173828 */,
- PRESHIFT(0x0001a000) /* 0.000396729 */,
-
- -PRESHIFT(0x00001000) /* -0.000015259 */,
- -PRESHIFT(0x0001f000) /* -0.000473022 */,
- PRESHIFT(0x000da000) /* 0.003326416 */,
- -PRESHIFT(0x00207000) /* -0.007919312 */,
- PRESHIFT(0x007d0000) /* 0.030517578 */,
- -PRESHIFT(0x0158d000) /* -0.084182739 */,
- PRESHIFT(0x01747000) /* 0.090927124 */,
- -PRESHIFT(0x099a8000) /* -0.600219727 */,
- PRESHIFT(0x124f0000) /* 1.144287109 */,
- PRESHIFT(0x08b38000) /* 0.543823242 */,
- PRESHIFT(0x01bde000) /* 0.108856201 */,
- PRESHIFT(0x012b4000) /* 0.073059082 */,
- PRESHIFT(0x0080f000) /* 0.031478882 */,
- PRESHIFT(0x00191000) /* 0.006118774 */,
- PRESHIFT(0x000d0000) /* 0.003173828 */,
- PRESHIFT(0x0001a000) /* 0.000396729 */ },
-
- { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 2 */
- -PRESHIFT(0x00023000) /* -0.000534058 */,
- PRESHIFT(0x000de000) /* 0.003387451 */,
- -PRESHIFT(0x00245000) /* -0.008865356 */,
- PRESHIFT(0x007a0000) /* 0.029785156 */,
- -PRESHIFT(0x016f7000) /* -0.089706421 */,
- PRESHIFT(0x014a8000) /* 0.080688477 */,
- -PRESHIFT(0x0a0d8000) /* -0.628295898 */,
- PRESHIFT(0x12468000) /* 1.142211914 */,
- PRESHIFT(0x083ff000) /* 0.515609741 */,
- PRESHIFT(0x01dd8000) /* 0.116577148 */,
- PRESHIFT(0x01149000) /* 0.067520142 */,
- PRESHIFT(0x00820000) /* 0.031738281 */,
- PRESHIFT(0x0015b000) /* 0.005294800 */,
- PRESHIFT(0x000ca000) /* 0.003082275 */,
- PRESHIFT(0x00018000) /* 0.000366211 */,
-
- -PRESHIFT(0x00001000) /* -0.000015259 */,
- -PRESHIFT(0x00023000) /* -0.000534058 */,
- PRESHIFT(0x000de000) /* 0.003387451 */,
- -PRESHIFT(0x00245000) /* -0.008865356 */,
- PRESHIFT(0x007a0000) /* 0.029785156 */,
- -PRESHIFT(0x016f7000) /* -0.089706421 */,
- PRESHIFT(0x014a8000) /* 0.080688477 */,
- -PRESHIFT(0x0a0d8000) /* -0.628295898 */,
- PRESHIFT(0x12468000) /* 1.142211914 */,
- PRESHIFT(0x083ff000) /* 0.515609741 */,
- PRESHIFT(0x01dd8000) /* 0.116577148 */,
- PRESHIFT(0x01149000) /* 0.067520142 */,
- PRESHIFT(0x00820000) /* 0.031738281 */,
- PRESHIFT(0x0015b000) /* 0.005294800 */,
- PRESHIFT(0x000ca000) /* 0.003082275 */,
- PRESHIFT(0x00018000) /* 0.000366211 */ },
-
- { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 3 */
- -PRESHIFT(0x00026000) /* -0.000579834 */,
- PRESHIFT(0x000e1000) /* 0.003433228 */,
- -PRESHIFT(0x00285000) /* -0.009841919 */,
- PRESHIFT(0x00765000) /* 0.028884888 */,
- -PRESHIFT(0x0185d000) /* -0.095169067 */,
- PRESHIFT(0x011d1000) /* 0.069595337 */,
- -PRESHIFT(0x0a7fe000) /* -0.656219482 */,
- PRESHIFT(0x12386000) /* 1.138763428 */,
- PRESHIFT(0x07ccb000) /* 0.487472534 */,
- PRESHIFT(0x01f9c000) /* 0.123474121 */,
- PRESHIFT(0x00fdf000) /* 0.061996460 */,
- PRESHIFT(0x00827000) /* 0.031845093 */,
- PRESHIFT(0x00126000) /* 0.004486084 */,
- PRESHIFT(0x000c4000) /* 0.002990723 */,
- PRESHIFT(0x00015000) /* 0.000320435 */,
-
- -PRESHIFT(0x00001000) /* -0.000015259 */,
- -PRESHIFT(0x00026000) /* -0.000579834 */,
- PRESHIFT(0x000e1000) /* 0.003433228 */,
- -PRESHIFT(0x00285000) /* -0.009841919 */,
- PRESHIFT(0x00765000) /* 0.028884888 */,
- -PRESHIFT(0x0185d000) /* -0.095169067 */,
- PRESHIFT(0x011d1000) /* 0.069595337 */,
- -PRESHIFT(0x0a7fe000) /* -0.656219482 */,
- PRESHIFT(0x12386000) /* 1.138763428 */,
- PRESHIFT(0x07ccb000) /* 0.487472534 */,
- PRESHIFT(0x01f9c000) /* 0.123474121 */,
- PRESHIFT(0x00fdf000) /* 0.061996460 */,
- PRESHIFT(0x00827000) /* 0.031845093 */,
- PRESHIFT(0x00126000) /* 0.004486084 */,
- PRESHIFT(0x000c4000) /* 0.002990723 */,
- PRESHIFT(0x00015000) /* 0.000320435 */ },
-
- { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 4 */
- -PRESHIFT(0x00029000) /* -0.000625610 */,
- PRESHIFT(0x000e3000) /* 0.003463745 */,
- -PRESHIFT(0x002c7000) /* -0.010848999 */,
- PRESHIFT(0x0071e000) /* 0.027801514 */,
- -PRESHIFT(0x019bd000) /* -0.100540161 */,
- PRESHIFT(0x00ec0000) /* 0.057617187 */,
- -PRESHIFT(0x0af15000) /* -0.683914185 */,
- PRESHIFT(0x12249000) /* 1.133926392 */,
- PRESHIFT(0x075a0000) /* 0.459472656 */,
- PRESHIFT(0x0212c000) /* 0.129577637 */,
- PRESHIFT(0x00e79000) /* 0.056533813 */,
- PRESHIFT(0x00825000) /* 0.031814575 */,
- PRESHIFT(0x000f4000) /* 0.003723145 */,
- PRESHIFT(0x000be000) /* 0.002899170 */,
- PRESHIFT(0x00013000) /* 0.000289917 */,
-
- -PRESHIFT(0x00001000) /* -0.000015259 */,
- -PRESHIFT(0x00029000) /* -0.000625610 */,
- PRESHIFT(0x000e3000) /* 0.003463745 */,
- -PRESHIFT(0x002c7000) /* -0.010848999 */,
- PRESHIFT(0x0071e000) /* 0.027801514 */,
- -PRESHIFT(0x019bd000) /* -0.100540161 */,
- PRESHIFT(0x00ec0000) /* 0.057617187 */,
- -PRESHIFT(0x0af15000) /* -0.683914185 */,
- PRESHIFT(0x12249000) /* 1.133926392 */,
- PRESHIFT(0x075a0000) /* 0.459472656 */,
- PRESHIFT(0x0212c000) /* 0.129577637 */,
- PRESHIFT(0x00e79000) /* 0.056533813 */,
- PRESHIFT(0x00825000) /* 0.031814575 */,
- PRESHIFT(0x000f4000) /* 0.003723145 */,
- PRESHIFT(0x000be000) /* 0.002899170 */,
- PRESHIFT(0x00013000) /* 0.000289917 */ },
-
- { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 5 */
- -PRESHIFT(0x0002d000) /* -0.000686646 */,
- PRESHIFT(0x000e4000) /* 0.003479004 */,
- -PRESHIFT(0x0030b000) /* -0.011886597 */,
- PRESHIFT(0x006cb000) /* 0.026535034 */,
- -PRESHIFT(0x01b17000) /* -0.105819702 */,
- PRESHIFT(0x00b77000) /* 0.044784546 */,
- -PRESHIFT(0x0b619000) /* -0.711318970 */,
- PRESHIFT(0x120b4000) /* 1.127746582 */,
- PRESHIFT(0x06e81000) /* 0.431655884 */,
- PRESHIFT(0x02288000) /* 0.134887695 */,
- PRESHIFT(0x00d17000) /* 0.051132202 */,
- PRESHIFT(0x0081b000) /* 0.031661987 */,
- PRESHIFT(0x000c5000) /* 0.003005981 */,
- PRESHIFT(0x000b7000) /* 0.002792358 */,
- PRESHIFT(0x00011000) /* 0.000259399 */,
-
- -PRESHIFT(0x00001000) /* -0.000015259 */,
- -PRESHIFT(0x0002d000) /* -0.000686646 */,
- PRESHIFT(0x000e4000) /* 0.003479004 */,
- -PRESHIFT(0x0030b000) /* -0.011886597 */,
- PRESHIFT(0x006cb000) /* 0.026535034 */,
- -PRESHIFT(0x01b17000) /* -0.105819702 */,
- PRESHIFT(0x00b77000) /* 0.044784546 */,
- -PRESHIFT(0x0b619000) /* -0.711318970 */,
- PRESHIFT(0x120b4000) /* 1.127746582 */,
- PRESHIFT(0x06e81000) /* 0.431655884 */,
- PRESHIFT(0x02288000) /* 0.134887695 */,
- PRESHIFT(0x00d17000) /* 0.051132202 */,
- PRESHIFT(0x0081b000) /* 0.031661987 */,
- PRESHIFT(0x000c5000) /* 0.003005981 */,
- PRESHIFT(0x000b7000) /* 0.002792358 */,
- PRESHIFT(0x00011000) /* 0.000259399 */ },
-
- { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 6 */
- -PRESHIFT(0x00031000) /* -0.000747681 */,
- PRESHIFT(0x000e4000) /* 0.003479004 */,
- -PRESHIFT(0x00350000) /* -0.012939453 */,
- PRESHIFT(0x0066c000) /* 0.025085449 */,
- -PRESHIFT(0x01c67000) /* -0.110946655 */,
- PRESHIFT(0x007f5000) /* 0.031082153 */,
- -PRESHIFT(0x0bd06000) /* -0.738372803 */,
- PRESHIFT(0x11ec7000) /* 1.120223999 */,
- PRESHIFT(0x06772000) /* 0.404083252 */,
- PRESHIFT(0x023b3000) /* 0.139450073 */,
- PRESHIFT(0x00bbc000) /* 0.045837402 */,
- PRESHIFT(0x00809000) /* 0.031387329 */,
- PRESHIFT(0x00099000) /* 0.002334595 */,
- PRESHIFT(0x000b0000) /* 0.002685547 */,
- PRESHIFT(0x00010000) /* 0.000244141 */,
-
- -PRESHIFT(0x00001000) /* -0.000015259 */,
- -PRESHIFT(0x00031000) /* -0.000747681 */,
- PRESHIFT(0x000e4000) /* 0.003479004 */,
- -PRESHIFT(0x00350000) /* -0.012939453 */,
- PRESHIFT(0x0066c000) /* 0.025085449 */,
- -PRESHIFT(0x01c67000) /* -0.110946655 */,
- PRESHIFT(0x007f5000) /* 0.031082153 */,
- -PRESHIFT(0x0bd06000) /* -0.738372803 */,
- PRESHIFT(0x11ec7000) /* 1.120223999 */,
- PRESHIFT(0x06772000) /* 0.404083252 */,
- PRESHIFT(0x023b3000) /* 0.139450073 */,
- PRESHIFT(0x00bbc000) /* 0.045837402 */,
- PRESHIFT(0x00809000) /* 0.031387329 */,
- PRESHIFT(0x00099000) /* 0.002334595 */,
- PRESHIFT(0x000b0000) /* 0.002685547 */,
- PRESHIFT(0x00010000) /* 0.000244141 */ },
-
- { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 7 */
- -PRESHIFT(0x00035000) /* -0.000808716 */,
- PRESHIFT(0x000e3000) /* 0.003463745 */,
- -PRESHIFT(0x00397000) /* -0.014022827 */,
- PRESHIFT(0x005ff000) /* 0.023422241 */,
- -PRESHIFT(0x01dad000) /* -0.115921021 */,
- PRESHIFT(0x0043a000) /* 0.016510010 */,
- -PRESHIFT(0x0c3d9000) /* -0.765029907 */,
- PRESHIFT(0x11c83000) /* 1.111373901 */,
- PRESHIFT(0x06076000) /* 0.376800537 */,
- PRESHIFT(0x024ad000) /* 0.143264771 */,
- PRESHIFT(0x00a67000) /* 0.040634155 */,
- PRESHIFT(0x007f0000) /* 0.031005859 */,
- PRESHIFT(0x0006f000) /* 0.001693726 */,
- PRESHIFT(0x000a9000) /* 0.002578735 */,
- PRESHIFT(0x0000e000) /* 0.000213623 */,
-
- -PRESHIFT(0x00002000) /* -0.000030518 */,
- -PRESHIFT(0x00035000) /* -0.000808716 */,
- PRESHIFT(0x000e3000) /* 0.003463745 */,
- -PRESHIFT(0x00397000) /* -0.014022827 */,
- PRESHIFT(0x005ff000) /* 0.023422241 */,
- -PRESHIFT(0x01dad000) /* -0.115921021 */,
- PRESHIFT(0x0043a000) /* 0.016510010 */,
- -PRESHIFT(0x0c3d9000) /* -0.765029907 */,
- PRESHIFT(0x11c83000) /* 1.111373901 */,
- PRESHIFT(0x06076000) /* 0.376800537 */,
- PRESHIFT(0x024ad000) /* 0.143264771 */,
- PRESHIFT(0x00a67000) /* 0.040634155 */,
- PRESHIFT(0x007f0000) /* 0.031005859 */,
- PRESHIFT(0x0006f000) /* 0.001693726 */,
- PRESHIFT(0x000a9000) /* 0.002578735 */,
- PRESHIFT(0x0000e000) /* 0.000213623 */ },
-
- { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 8 */
- -PRESHIFT(0x0003a000) /* -0.000885010 */,
- PRESHIFT(0x000e0000) /* 0.003417969 */,
- -PRESHIFT(0x003df000) /* -0.015121460 */,
- PRESHIFT(0x00586000) /* 0.021575928 */,
- -PRESHIFT(0x01ee6000) /* -0.120697021 */,
- PRESHIFT(0x00046000) /* 0.001068115 */,
- -PRESHIFT(0x0ca8d000) /* -0.791213989 */,
- PRESHIFT(0x119e9000) /* 1.101211548 */,
- PRESHIFT(0x05991000) /* 0.349868774 */,
- PRESHIFT(0x02578000) /* 0.146362305 */,
- PRESHIFT(0x0091a000) /* 0.035552979 */,
- PRESHIFT(0x007d1000) /* 0.030532837 */,
- PRESHIFT(0x00048000) /* 0.001098633 */,
- PRESHIFT(0x000a1000) /* 0.002456665 */,
- PRESHIFT(0x0000d000) /* 0.000198364 */,
-
- -PRESHIFT(0x00002000) /* -0.000030518 */,
- -PRESHIFT(0x0003a000) /* -0.000885010 */,
- PRESHIFT(0x000e0000) /* 0.003417969 */,
- -PRESHIFT(0x003df000) /* -0.015121460 */,
- PRESHIFT(0x00586000) /* 0.021575928 */,
- -PRESHIFT(0x01ee6000) /* -0.120697021 */,
- PRESHIFT(0x00046000) /* 0.001068115 */,
- -PRESHIFT(0x0ca8d000) /* -0.791213989 */,
- PRESHIFT(0x119e9000) /* 1.101211548 */,
- PRESHIFT(0x05991000) /* 0.349868774 */,
- PRESHIFT(0x02578000) /* 0.146362305 */,
- PRESHIFT(0x0091a000) /* 0.035552979 */,
- PRESHIFT(0x007d1000) /* 0.030532837 */,
- PRESHIFT(0x00048000) /* 0.001098633 */,
- PRESHIFT(0x000a1000) /* 0.002456665 */,
- PRESHIFT(0x0000d000) /* 0.000198364 */ },
-
- { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 9 */
- -PRESHIFT(0x0003f000) /* -0.000961304 */,
- PRESHIFT(0x000dd000) /* 0.003372192 */,
- -PRESHIFT(0x00428000) /* -0.016235352 */,
- PRESHIFT(0x00500000) /* 0.019531250 */,
- -PRESHIFT(0x02011000) /* -0.125259399 */,
- -PRESHIFT(0x003e6000) /* -0.015228271 */,
- -PRESHIFT(0x0d11e000) /* -0.816864014 */,
- PRESHIFT(0x116fc000) /* 1.089782715 */,
- PRESHIFT(0x052c5000) /* 0.323318481 */,
- PRESHIFT(0x02616000) /* 0.148773193 */,
- PRESHIFT(0x007d6000) /* 0.030609131 */,
- PRESHIFT(0x007aa000) /* 0.029937744 */,
- PRESHIFT(0x00024000) /* 0.000549316 */,
- PRESHIFT(0x0009a000) /* 0.002349854 */,
- PRESHIFT(0x0000b000) /* 0.000167847 */,
-
- -PRESHIFT(0x00002000) /* -0.000030518 */,
- -PRESHIFT(0x0003f000) /* -0.000961304 */,
- PRESHIFT(0x000dd000) /* 0.003372192 */,
- -PRESHIFT(0x00428000) /* -0.016235352 */,
- PRESHIFT(0x00500000) /* 0.019531250 */,
- -PRESHIFT(0x02011000) /* -0.125259399 */,
- -PRESHIFT(0x003e6000) /* -0.015228271 */,
- -PRESHIFT(0x0d11e000) /* -0.816864014 */,
- PRESHIFT(0x116fc000) /* 1.089782715 */,
- PRESHIFT(0x052c5000) /* 0.323318481 */,
- PRESHIFT(0x02616000) /* 0.148773193 */,
- PRESHIFT(0x007d6000) /* 0.030609131 */,
- PRESHIFT(0x007aa000) /* 0.029937744 */,
- PRESHIFT(0x00024000) /* 0.000549316 */,
- PRESHIFT(0x0009a000) /* 0.002349854 */,
- PRESHIFT(0x0000b000) /* 0.000167847 */ },
-
- { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 10 */
- -PRESHIFT(0x00044000) /* -0.001037598 */,
- PRESHIFT(0x000d7000) /* 0.003280640 */,
- -PRESHIFT(0x00471000) /* -0.017349243 */,
- PRESHIFT(0x0046b000) /* 0.017257690 */,
- -PRESHIFT(0x0212b000) /* -0.129562378 */,
- -PRESHIFT(0x0084a000) /* -0.032379150 */,
- -PRESHIFT(0x0d78a000) /* -0.841949463 */,
- PRESHIFT(0x113be000) /* 1.077117920 */,
- PRESHIFT(0x04c16000) /* 0.297210693 */,
- PRESHIFT(0x02687000) /* 0.150497437 */,
- PRESHIFT(0x0069c000) /* 0.025817871 */,
- PRESHIFT(0x0077f000) /* 0.029281616 */,
- PRESHIFT(0x00002000) /* 0.000030518 */,
- PRESHIFT(0x00093000) /* 0.002243042 */,
- PRESHIFT(0x0000a000) /* 0.000152588 */,
-
- -PRESHIFT(0x00002000) /* -0.000030518 */,
- -PRESHIFT(0x00044000) /* -0.001037598 */,
- PRESHIFT(0x000d7000) /* 0.003280640 */,
- -PRESHIFT(0x00471000) /* -0.017349243 */,
- PRESHIFT(0x0046b000) /* 0.017257690 */,
- -PRESHIFT(0x0212b000) /* -0.129562378 */,
- -PRESHIFT(0x0084a000) /* -0.032379150 */,
- -PRESHIFT(0x0d78a000) /* -0.841949463 */,
- PRESHIFT(0x113be000) /* 1.077117920 */,
- PRESHIFT(0x04c16000) /* 0.297210693 */,
- PRESHIFT(0x02687000) /* 0.150497437 */,
- PRESHIFT(0x0069c000) /* 0.025817871 */,
- PRESHIFT(0x0077f000) /* 0.029281616 */,
- PRESHIFT(0x00002000) /* 0.000030518 */,
- PRESHIFT(0x00093000) /* 0.002243042 */,
- PRESHIFT(0x0000a000) /* 0.000152588 */ },
-
- { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 11 */
- -PRESHIFT(0x00049000) /* -0.001113892 */,
- PRESHIFT(0x000d0000) /* 0.003173828 */,
- -PRESHIFT(0x004ba000) /* -0.018463135 */,
- PRESHIFT(0x003ca000) /* 0.014801025 */,
- -PRESHIFT(0x02233000) /* -0.133590698 */,
- -PRESHIFT(0x00ce4000) /* -0.050354004 */,
- -PRESHIFT(0x0ddca000) /* -0.866363525 */,
- PRESHIFT(0x1102f000) /* 1.063217163 */,
- PRESHIFT(0x04587000) /* 0.271591187 */,
- PRESHIFT(0x026cf000) /* 0.151596069 */,
- PRESHIFT(0x0056c000) /* 0.021179199 */,
- PRESHIFT(0x0074e000) /* 0.028533936 */,
- -PRESHIFT(0x0001d000) /* -0.000442505 */,
- PRESHIFT(0x0008b000) /* 0.002120972 */,
- PRESHIFT(0x00009000) /* 0.000137329 */,
-
- -PRESHIFT(0x00003000) /* -0.000045776 */,
- -PRESHIFT(0x00049000) /* -0.001113892 */,
- PRESHIFT(0x000d0000) /* 0.003173828 */,
- -PRESHIFT(0x004ba000) /* -0.018463135 */,
- PRESHIFT(0x003ca000) /* 0.014801025 */,
- -PRESHIFT(0x02233000) /* -0.133590698 */,
- -PRESHIFT(0x00ce4000) /* -0.050354004 */,
- -PRESHIFT(0x0ddca000) /* -0.866363525 */,
- PRESHIFT(0x1102f000) /* 1.063217163 */,
- PRESHIFT(0x04587000) /* 0.271591187 */,
- PRESHIFT(0x026cf000) /* 0.151596069 */,
- PRESHIFT(0x0056c000) /* 0.021179199 */,
- PRESHIFT(0x0074e000) /* 0.028533936 */,
- -PRESHIFT(0x0001d000) /* -0.000442505 */,
- PRESHIFT(0x0008b000) /* 0.002120972 */,
- PRESHIFT(0x00009000) /* 0.000137329 */ },
-
- { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 12 */
- -PRESHIFT(0x0004f000) /* -0.001205444 */,
- PRESHIFT(0x000c8000) /* 0.003051758 */,
- -PRESHIFT(0x00503000) /* -0.019577026 */,
- PRESHIFT(0x0031a000) /* 0.012115479 */,
- -PRESHIFT(0x02326000) /* -0.137298584 */,
- -PRESHIFT(0x011b5000) /* -0.069168091 */,
- -PRESHIFT(0x0e3dd000) /* -0.890090942 */,
- PRESHIFT(0x10c54000) /* 1.048156738 */,
- PRESHIFT(0x03f1b000) /* 0.246505737 */,
- PRESHIFT(0x026ee000) /* 0.152069092 */,
- PRESHIFT(0x00447000) /* 0.016708374 */,
- PRESHIFT(0x00719000) /* 0.027725220 */,
- -PRESHIFT(0x00039000) /* -0.000869751 */,
- PRESHIFT(0x00084000) /* 0.002014160 */,
- PRESHIFT(0x00008000) /* 0.000122070 */,
-
- -PRESHIFT(0x00003000) /* -0.000045776 */,
- -PRESHIFT(0x0004f000) /* -0.001205444 */,
- PRESHIFT(0x000c8000) /* 0.003051758 */,
- -PRESHIFT(0x00503000) /* -0.019577026 */,
- PRESHIFT(0x0031a000) /* 0.012115479 */,
- -PRESHIFT(0x02326000) /* -0.137298584 */,
- -PRESHIFT(0x011b5000) /* -0.069168091 */,
- -PRESHIFT(0x0e3dd000) /* -0.890090942 */,
- PRESHIFT(0x10c54000) /* 1.048156738 */,
- PRESHIFT(0x03f1b000) /* 0.246505737 */,
- PRESHIFT(0x026ee000) /* 0.152069092 */,
- PRESHIFT(0x00447000) /* 0.016708374 */,
- PRESHIFT(0x00719000) /* 0.027725220 */,
- -PRESHIFT(0x00039000) /* -0.000869751 */,
- PRESHIFT(0x00084000) /* 0.002014160 */,
- PRESHIFT(0x00008000) /* 0.000122070 */ },
-
- { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 13 */
- -PRESHIFT(0x00055000) /* -0.001296997 */,
- PRESHIFT(0x000bd000) /* 0.002883911 */,
- -PRESHIFT(0x0054c000) /* -0.020690918 */,
- PRESHIFT(0x0025d000) /* 0.009231567 */,
- -PRESHIFT(0x02403000) /* -0.140670776 */,
- -PRESHIFT(0x016ba000) /* -0.088775635 */,
- -PRESHIFT(0x0e9be000) /* -0.913055420 */,
- PRESHIFT(0x1082d000) /* 1.031936646 */,
- PRESHIFT(0x038d4000) /* 0.221984863 */,
- PRESHIFT(0x026e7000) /* 0.151962280 */,
- PRESHIFT(0x0032e000) /* 0.012420654 */,
- PRESHIFT(0x006df000) /* 0.026840210 */,
- -PRESHIFT(0x00053000) /* -0.001266479 */,
- PRESHIFT(0x0007d000) /* 0.001907349 */,
- PRESHIFT(0x00007000) /* 0.000106812 */,
-
- -PRESHIFT(0x00004000) /* -0.000061035 */,
- -PRESHIFT(0x00055000) /* -0.001296997 */,
- PRESHIFT(0x000bd000) /* 0.002883911 */,
- -PRESHIFT(0x0054c000) /* -0.020690918 */,
- PRESHIFT(0x0025d000) /* 0.009231567 */,
- -PRESHIFT(0x02403000) /* -0.140670776 */,
- -PRESHIFT(0x016ba000) /* -0.088775635 */,
- -PRESHIFT(0x0e9be000) /* -0.913055420 */,
- PRESHIFT(0x1082d000) /* 1.031936646 */,
- PRESHIFT(0x038d4000) /* 0.221984863 */,
- PRESHIFT(0x026e7000) /* 0.151962280 */,
- PRESHIFT(0x0032e000) /* 0.012420654 */,
- PRESHIFT(0x006df000) /* 0.026840210 */,
- -PRESHIFT(0x00053000) /* -0.001266479 */,
- PRESHIFT(0x0007d000) /* 0.001907349 */,
- PRESHIFT(0x00007000) /* 0.000106812 */ },
-
- { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 14 */
- -PRESHIFT(0x0005b000) /* -0.001388550 */,
- PRESHIFT(0x000b1000) /* 0.002700806 */,
- -PRESHIFT(0x00594000) /* -0.021789551 */,
- PRESHIFT(0x00192000) /* 0.006134033 */,
- -PRESHIFT(0x024c8000) /* -0.143676758 */,
- -PRESHIFT(0x01bf2000) /* -0.109161377 */,
- -PRESHIFT(0x0ef69000) /* -0.935195923 */,
- PRESHIFT(0x103be000) /* 1.014617920 */,
- PRESHIFT(0x032b4000) /* 0.198059082 */,
- PRESHIFT(0x026bc000) /* 0.151306152 */,
- PRESHIFT(0x00221000) /* 0.008316040 */,
- PRESHIFT(0x006a2000) /* 0.025909424 */,
- -PRESHIFT(0x0006a000) /* -0.001617432 */,
- PRESHIFT(0x00075000) /* 0.001785278 */,
- PRESHIFT(0x00007000) /* 0.000106812 */,
-
- -PRESHIFT(0x00004000) /* -0.000061035 */,
- -PRESHIFT(0x0005b000) /* -0.001388550 */,
- PRESHIFT(0x000b1000) /* 0.002700806 */,
- -PRESHIFT(0x00594000) /* -0.021789551 */,
- PRESHIFT(0x00192000) /* 0.006134033 */,
- -PRESHIFT(0x024c8000) /* -0.143676758 */,
- -PRESHIFT(0x01bf2000) /* -0.109161377 */,
- -PRESHIFT(0x0ef69000) /* -0.935195923 */,
- PRESHIFT(0x103be000) /* 1.014617920 */,
- PRESHIFT(0x032b4000) /* 0.198059082 */,
- PRESHIFT(0x026bc000) /* 0.151306152 */,
- PRESHIFT(0x00221000) /* 0.008316040 */,
- PRESHIFT(0x006a2000) /* 0.025909424 */,
- -PRESHIFT(0x0006a000) /* -0.001617432 */,
- PRESHIFT(0x00075000) /* 0.001785278 */,
- PRESHIFT(0x00007000) /* 0.000106812 */ },
-
- { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 15 */
- -PRESHIFT(0x00061000) /* -0.001480103 */,
- PRESHIFT(0x000a3000) /* 0.002487183 */,
- -PRESHIFT(0x005da000) /* -0.022857666 */,
- PRESHIFT(0x000b9000) /* 0.002822876 */,
- -PRESHIFT(0x02571000) /* -0.146255493 */,
- -PRESHIFT(0x0215c000) /* -0.130310059 */,
- -PRESHIFT(0x0f4dc000) /* -0.956481934 */,
- PRESHIFT(0x0ff0a000) /* 0.996246338 */,
- PRESHIFT(0x02cbf000) /* 0.174789429 */,
- PRESHIFT(0x0266e000) /* 0.150115967 */,
- PRESHIFT(0x00120000) /* 0.004394531 */,
- PRESHIFT(0x00662000) /* 0.024932861 */,
- -PRESHIFT(0x0007f000) /* -0.001937866 */,
- PRESHIFT(0x0006f000) /* 0.001693726 */,
- PRESHIFT(0x00006000) /* 0.000091553 */,
-
- -PRESHIFT(0x00005000) /* -0.000076294 */,
- -PRESHIFT(0x00061000) /* -0.001480103 */,
- PRESHIFT(0x000a3000) /* 0.002487183 */,
- -PRESHIFT(0x005da000) /* -0.022857666 */,
- PRESHIFT(0x000b9000) /* 0.002822876 */,
- -PRESHIFT(0x02571000) /* -0.146255493 */,
- -PRESHIFT(0x0215c000) /* -0.130310059 */,
- -PRESHIFT(0x0f4dc000) /* -0.956481934 */,
- PRESHIFT(0x0ff0a000) /* 0.996246338 */,
- PRESHIFT(0x02cbf000) /* 0.174789429 */,
- PRESHIFT(0x0266e000) /* 0.150115967 */,
- PRESHIFT(0x00120000) /* 0.004394531 */,
- PRESHIFT(0x00662000) /* 0.024932861 */,
- -PRESHIFT(0x0007f000) /* -0.001937866 */,
- PRESHIFT(0x0006f000) /* 0.001693726 */,
- PRESHIFT(0x00006000) /* 0.000091553 */ },
-
- { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 16 */
- -PRESHIFT(0x00068000) /* -0.001586914 */,
- PRESHIFT(0x00092000) /* 0.002227783 */,
- -PRESHIFT(0x0061f000) /* -0.023910522 */,
- -PRESHIFT(0x0002d000) /* -0.000686646 */,
- -PRESHIFT(0x025ff000) /* -0.148422241 */,
- -PRESHIFT(0x026f7000) /* -0.152206421 */,
- -PRESHIFT(0x0fa13000) /* -0.976852417 */,
- PRESHIFT(0x0fa13000) /* 0.976852417 */,
- PRESHIFT(0x026f7000) /* 0.152206421 */,
- PRESHIFT(0x025ff000) /* 0.148422241 */,
- PRESHIFT(0x0002d000) /* 0.000686646 */,
- PRESHIFT(0x0061f000) /* 0.023910522 */,
- -PRESHIFT(0x00092000) /* -0.002227783 */,
- PRESHIFT(0x00068000) /* 0.001586914 */,
- PRESHIFT(0x00005000) /* 0.000076294 */,
-
- -PRESHIFT(0x00005000) /* -0.000076294 */,
- -PRESHIFT(0x00068000) /* -0.001586914 */,
- PRESHIFT(0x00092000) /* 0.002227783 */,
- -PRESHIFT(0x0061f000) /* -0.023910522 */,
- -PRESHIFT(0x0002d000) /* -0.000686646 */,
- -PRESHIFT(0x025ff000) /* -0.148422241 */,
- -PRESHIFT(0x026f7000) /* -0.152206421 */,
- -PRESHIFT(0x0fa13000) /* -0.976852417 */,
- PRESHIFT(0x0fa13000) /* 0.976852417 */,
- PRESHIFT(0x026f7000) /* 0.152206421 */,
- PRESHIFT(0x025ff000) /* 0.148422241 */,
- PRESHIFT(0x0002d000) /* 0.000686646 */,
- PRESHIFT(0x0061f000) /* 0.023910522 */,
- -PRESHIFT(0x00092000) /* -0.002227783 */,
- PRESHIFT(0x00068000) /* 0.001586914 */,
- PRESHIFT(0x00005000) /* 0.000076294 */ }
diff --git a/libmad/src/README b/libmad/src/README
deleted file mode 100644
index b3f15ea..0000000
--- a/libmad/src/README
+++ /dev/null
@@ -1,241 +0,0 @@
-
- libmad - MPEG audio decoder library
- Copyright (C) 2000-2004 Underbit Technologies, Inc.
-
- $Id: README,v 1.4 2004/01/23 09:41:32 rob Exp $
-
-===============================================================================
-
-INTRODUCTION
-
- MAD (libmad) is a high-quality MPEG audio decoder. It currently supports
- MPEG-1 and the MPEG-2 extension to Lower Sampling Frequencies, as well as
- the so-called MPEG 2.5 format. All three audio layers (Layer I, Layer II,
- and Layer III a.k.a. MP3) are fully implemented.
-
- MAD does not yet support MPEG-2 multichannel audio (although it should be
- backward compatible with such streams) nor does it currently support AAC.
-
- MAD has the following special features:
-
- - 24-bit PCM output
- - 100% fixed-point (integer) computation
- - completely new implementation based on the ISO/IEC standards
- - distributed under the terms of the GNU General Public License (GPL)
-
- Because MAD provides full 24-bit PCM output, applications using MAD are
- able to produce high quality audio. Even when the output device supports
- only 16-bit PCM, applications can use the extra resolution to increase the
- audible dynamic range through the use of dithering or noise shaping.
-
- Because MAD uses integer computation rather than floating point, it is
- well suited for architectures without a floating point unit. All
- calculations are performed with a 32-bit fixed-point integer
- representation.
-
- Because MAD is a new implementation of the ISO/IEC standards, it is
- unencumbered by the errors of other implementations. MAD is NOT a
- derivation of the ISO reference source or any other code. Considerable
- effort has been expended to ensure a correct implementation, even in cases
- where the standards are ambiguous or misleading.
-
- Because MAD is distributed under the terms of the GPL, its redistribution
- is not generally restricted, so long as the terms of the GPL are followed.
- This means MAD can be incorporated into other software as long as that
- software is also distributed under the GPL. (Should this be undesirable,
- alternate arrangements may be possible by contacting Underbit.)
-
-===============================================================================
-
-ABOUT THE CODE
-
- The code is optimized and performs very well, although specific
- improvements can still be made. The output from the decoder library
- consists of 32-bit signed linear fixed-point values that can be easily
- scaled for any size PCM output, up to 24 bits per sample.
-
- The API for libmad can be found in the `mad.h' header file. Note that this
- file is automatically generated, and will not exist until after you have
- built the library.
-
- There are two APIs available, one high-level, and the other low-level.
- With the low-level API, each step of the decoding process must be handled
- explicitly, offering the greatest amount of control. With the high-level
- API, after callbacks are configured, a single routine will decode an
- entire bitstream.
-
- The high-level API may either be used synchronously or asynchronously. If
- used asynchronously, decoding will occur in a separate process.
- Communication is possible with the decoding process by passing control
- messages.
-
- The file `minimad.c' contains an example usage of the libmad API that
- shows only the bare minimum required to implement a useful decoder. It
- expects a regular file to be redirected to standard input, and it sends
- decoded 16-bit signed little-endian PCM samples to standard output. If a
- decoding error occurs, it is reported to standard error and decoding
- continues. Note that the scale() routine in this code is only provided as
- an example; it rounds MAD's high-resolution samples down to 16 bits, but
- does not perform any dithering or noise shaping. It is therefore not
- recommended to use this routine as-is in your own code if sound quality is
- important.
-
-Integer Performance
-
- To get the best possible performance, it is recommended that an assembly
- version of the fixed-point multiply and related routines be selected.
- Several such assembly routines have been written for various CPUs.
-
- If an assembly version is not available, a fast approximation version will
- be used. This will result in reduced accuracy of the decoder.
-
- Alternatively, if 64-bit integers are supported as a datatype by the
- compiler, another version can be used that is much more accurate.
- However, using an assembly version is generally much faster and just as
- accurate.
-
- More information can be gathered from the `fixed.h' header file.
-
- MAD's CPU-intensive subband synthesis routine can be further optimized at
- the expense of a slight loss in output accuracy due to a modified method
- for fixed-point multiplication with a small windowing constant. While this
- is helpful for performance and the output accuracy loss is generally
- undetectable, it is disabled by default and must be explicitly enabled.
-
- Under some architectures, other special optimizations may also be
- available.
-
-Audio Quality
-
- The output from MAD has been found to satisfy the ISO/IEC 11172-4
- computational accuracy requirements for compliance. In most
- configurations, MAD is a Full Layer III ISO/IEC 11172-3 audio decoder as
- defined by the standard.
-
- When the approximation version of the fixed-point multiply is used, MAD is
- a limited accuracy ISO/IEC 11172-3 audio decoder as defined by the
- standard.
-
- MAD can alternatively be configured to produce output with less or more
- accuracy than the default, as a tradeoff with performance.
-
- MAD produces output samples with a precision greater than 24 bits. Because
- most output formats use fewer bits, typically 16, it is recommended that a
- dithering algorithm be used (rather than rounding or truncating) to obtain
- the highest quality audio. However, dithering may unfavorably affect an
- analytic examination of the output (such as compliance testing); you may
- therefore wish to use rounding in this case instead.
-
-Portability Issues
-
- GCC is preferred to compile the code, but other compilers may also work.
- The assembly code in `fixed.h' depends on the inline assembly features of
- your compiler. If you're not using GCC or MSVC++, you can either write
- your own assembly macros or use the default (low quality output) version.
-
- The union initialization of `huffman.c' may not be portable to all
- platforms when GCC is not used.
-
- The code should not be sensitive to word sizes or byte ordering, however
- it does assume A % B has the same sign as A.
-
-===============================================================================
-
-BUILDING AND INSTALLING
-
-Windows Platforms
-
- MAD can be built under Windows using either MSVC++ or Cygwin. A MSVC++
- project file can be found under the `msvc++' subdirectory.
-
- To build libmad using Cygwin, you will first need to install the Cygwin
- tools:
-
- http://www.cygwin.com/
-
- You may then proceed with the following POSIX instructions within the
- Cygwin shell.
-
- Note that by default Cygwin will build a library that depends on the
- Cygwin DLL. You can use MinGW to build a library that does not depend on
- the Cygwin DLL. To do so, give the option --host=mingw32 to `configure'.
-
-POSIX Platforms (including Cygwin)
-
- The code is distributed with a `configure' script that will generate for
- you a `Makefile' and a `config.h' for your platform. See the file
- `INSTALL' for generic instructions.
-
- The specific options you may want to give `configure' are:
-
- --enable-speed optimize for speed over accuracy
-
- --enable-accuracy optimize for accuracy over speed
-
- --disable-debugging do not compile with debugging support, and
- use more optimizations
-
- --disable-shared do not build a shared library
-
- Note that you need not specify one of --enable-speed or --enable-accuracy;
- in its default configuration, MAD is optimized for both. You should only
- use one of these options if you wish to compromise speed or accuracy for
- the other.
-
- By default the package will build a shared library if possible for your
- platform. If you want only a static library, use --disable-shared.
-
- It is not normally necessary to use the following options, but you may
- fine-tune the configuration with them if desired:
-
- --enable-fpm=ARCH use the ARCH-specific version of the
- fixed-point math assembly routines
- (current options are: intel, arm, mips,
- sparc, ppc; also allowed are: 64bit, approx)
-
- --enable-sso use the subband synthesis optimization,
- with reduced accuracy
-
- --disable-aso do not use certain architecture-specific
- optimizations
-
- By default an appropriate fixed-point assembly routine will be selected
- for the configured host type, if it can be determined. Thus if you are
- cross-compiling for another architecture, you should be sure either to
- give `configure' a host type argument (--host) or to use an explicit
- --enable-fpm option.
-
- If an appropriate assembly routine cannot be determined, the default
- approximation version will be used. In this case, use of an alternate
- --enable-fpm is highly recommended.
-
-Experimenting and Developing
-
- Further options for `configure' that may be useful to developers and
- experimenters are:
-
- --enable-debugging enable diagnostic debugging support and
- debugging symbols
-
- --enable-profiling generate `gprof' profiling code
-
- --enable-experimental enable code using the EXPERIMENTAL
- preprocessor define
-
-===============================================================================
-
-COPYRIGHT
-
- Please read the `COPYRIGHT' file for copyright and warranty information.
- Also, the file `COPYING' contains the full text of the GNU GPL.
-
- Send inquiries, comments, bug reports, suggestions, patches, etc. to:
-
- Underbit Technologies, Inc. <support@underbit.com>
-
- See also the MAD home page on the Web:
-
- http://www.underbit.com/products/mad/
-
-===============================================================================
-
diff --git a/libmad/src/bit.c b/libmad/src/bit.c
deleted file mode 100644
index c2bfb24..0000000
--- a/libmad/src/bit.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: bit.c,v 1.12 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# ifdef HAVE_LIMITS_H
-# include <limits.h>
-# else
-# define CHAR_BIT 8
-# endif
-
-# include "bit.h"
-
-/*
- * This is the lookup table for computing the CRC-check word.
- * As described in section 2.4.3.1 and depicted in Figure A.9
- * of ISO/IEC 11172-3, the generator polynomial is:
- *
- * G(X) = X^16 + X^15 + X^2 + 1
- */
-static
-unsigned short const crc_table[256] = {
- 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
- 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
- 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
- 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
- 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
- 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
- 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
- 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
-
- 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
- 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
- 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
- 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
- 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
- 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
- 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
- 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
-
- 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
- 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
- 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
- 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
- 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
- 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
- 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
- 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
-
- 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
- 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
- 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
- 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
- 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
- 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
- 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
- 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
-};
-
-# define CRC_POLY 0x8005
-
-/*
- * NAME: bit->init()
- * DESCRIPTION: initialize bit pointer struct
- */
-void mad_bit_init(struct mad_bitptr *bitptr, unsigned char const *byte)
-{
- bitptr->byte = byte;
- bitptr->cache = 0;
- bitptr->left = CHAR_BIT;
-}
-
-/*
- * NAME: bit->length()
- * DESCRIPTION: return number of bits between start and end points
- */
-unsigned int mad_bit_length(struct mad_bitptr const *begin,
- struct mad_bitptr const *end)
-{
- return begin->left +
- CHAR_BIT * (end->byte - (begin->byte + 1)) + (CHAR_BIT - end->left);
-}
-
-/*
- * NAME: bit->nextbyte()
- * DESCRIPTION: return pointer to next unprocessed byte
- */
-unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *bitptr)
-{
- return bitptr->left == CHAR_BIT ? bitptr->byte : bitptr->byte + 1;
-}
-
-/*
- * NAME: bit->skip()
- * DESCRIPTION: advance bit pointer
- */
-void mad_bit_skip(struct mad_bitptr *bitptr, unsigned int len)
-{
- bitptr->byte += len / CHAR_BIT;
- bitptr->left -= len % CHAR_BIT;
-
- if (bitptr->left > CHAR_BIT) {
- bitptr->byte++;
- bitptr->left += CHAR_BIT;
- }
-
- if (bitptr->left < CHAR_BIT)
- bitptr->cache = *bitptr->byte;
-}
-
-/*
- * NAME: bit->read()
- * DESCRIPTION: read an arbitrary number of bits and return their UIMSBF value
- */
-unsigned long mad_bit_read(struct mad_bitptr *bitptr, unsigned int len)
-{
- register unsigned long value;
-
- if (bitptr->left == CHAR_BIT)
- bitptr->cache = *bitptr->byte;
-
- if (len < bitptr->left) {
- value = (bitptr->cache & ((1 << bitptr->left) - 1)) >>
- (bitptr->left - len);
- bitptr->left -= len;
-
- return value;
- }
-
- /* remaining bits in current byte */
-
- value = bitptr->cache & ((1 << bitptr->left) - 1);
- len -= bitptr->left;
-
- bitptr->byte++;
- bitptr->left = CHAR_BIT;
-
- /* more bytes */
-
- while (len >= CHAR_BIT) {
- value = (value << CHAR_BIT) | *bitptr->byte++;
- len -= CHAR_BIT;
- }
-
- if (len > 0) {
- bitptr->cache = *bitptr->byte;
-
- value = (value << len) | (bitptr->cache >> (CHAR_BIT - len));
- bitptr->left -= len;
- }
-
- return value;
-}
-
-# if 0
-/*
- * NAME: bit->write()
- * DESCRIPTION: write an arbitrary number of bits
- */
-void mad_bit_write(struct mad_bitptr *bitptr, unsigned int len,
- unsigned long value)
-{
- unsigned char *ptr;
-
- ptr = (unsigned char *) bitptr->byte;
-
- /* ... */
-}
-# endif
-
-/*
- * NAME: bit->crc()
- * DESCRIPTION: compute CRC-check word
- */
-unsigned short mad_bit_crc(struct mad_bitptr bitptr, unsigned int len,
- unsigned short init)
-{
- register unsigned int crc;
-
- for (crc = init; len >= 32; len -= 32) {
- register unsigned long data;
-
- data = mad_bit_read(&bitptr, 32);
-
- crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 24)) & 0xff];
- crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 16)) & 0xff];
- crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 8)) & 0xff];
- crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 0)) & 0xff];
- }
-
- switch (len / 8) {
- case 3: crc = (crc << 8) ^
- crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff];
- case 2: crc = (crc << 8) ^
- crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff];
- case 1: crc = (crc << 8) ^
- crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff];
-
- len %= 8;
-
- case 0: break;
- }
-
- while (len--) {
- register unsigned int msb;
-
- msb = mad_bit_read(&bitptr, 1) ^ (crc >> 15);
-
- crc <<= 1;
- if (msb & 1)
- crc ^= CRC_POLY;
- }
-
- return crc & 0xffff;
-}
diff --git a/libmad/src/bit.h b/libmad/src/bit.h
deleted file mode 100644
index 5a51570..0000000
--- a/libmad/src/bit.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: bit.h,v 1.12 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBMAD_BIT_H
-# define LIBMAD_BIT_H
-
-struct mad_bitptr {
- unsigned char const *byte;
- unsigned short cache;
- unsigned short left;
-};
-
-void mad_bit_init(struct mad_bitptr *, unsigned char const *);
-
-# define mad_bit_finish(bitptr) /* nothing */
-
-unsigned int mad_bit_length(struct mad_bitptr const *,
- struct mad_bitptr const *);
-
-# define mad_bit_bitsleft(bitptr) ((bitptr)->left)
-unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *);
-
-void mad_bit_skip(struct mad_bitptr *, unsigned int);
-unsigned long mad_bit_read(struct mad_bitptr *, unsigned int);
-void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long);
-
-unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short);
-
-# endif
diff --git a/libmad/src/decoder.c b/libmad/src/decoder.c
deleted file mode 100644
index 6d6df0d..0000000
--- a/libmad/src/decoder.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: decoder.c,v 1.22 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-# endif
-
-# ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-# endif
-
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-
-# ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-# endif
-
-# include <stdlib.h>
-
-# ifdef HAVE_ERRNO_H
-# include <errno.h>
-# endif
-
-# include "stream.h"
-# include "frame.h"
-# include "synth.h"
-# include "decoder.h"
-
-/*
- * NAME: decoder->init()
- * DESCRIPTION: initialize a decoder object with callback routines
- */
-void mad_decoder_init(struct mad_decoder *decoder, void *data,
- enum mad_flow (*input_func)(void *,
- struct mad_stream *),
- enum mad_flow (*header_func)(void *,
- struct mad_header const *),
- enum mad_flow (*filter_func)(void *,
- struct mad_stream const *,
- struct mad_frame *),
- enum mad_flow (*output_func)(void *,
- struct mad_header const *,
- struct mad_pcm *),
- enum mad_flow (*error_func)(void *,
- struct mad_stream *,
- struct mad_frame *),
- enum mad_flow (*message_func)(void *,
- void *, unsigned int *))
-{
- decoder->mode = -1;
-
- decoder->options = 0;
-
- decoder->async.pid = 0;
- decoder->async.in = -1;
- decoder->async.out = -1;
-
- decoder->sync = 0;
-
- decoder->cb_data = data;
-
- decoder->input_func = input_func;
- decoder->header_func = header_func;
- decoder->filter_func = filter_func;
- decoder->output_func = output_func;
- decoder->error_func = error_func;
- decoder->message_func = message_func;
-}
-
-int mad_decoder_finish(struct mad_decoder *decoder)
-{
-# if defined(USE_ASYNC)
- if (decoder->mode == MAD_DECODER_MODE_ASYNC && decoder->async.pid) {
- pid_t pid;
- int status;
-
- close(decoder->async.in);
-
- do
- pid = waitpid(decoder->async.pid, &status, 0);
- while (pid == -1 && errno == EINTR);
-
- decoder->mode = -1;
-
- close(decoder->async.out);
-
- decoder->async.pid = 0;
- decoder->async.in = -1;
- decoder->async.out = -1;
-
- if (pid == -1)
- return -1;
-
- return (!WIFEXITED(status) || WEXITSTATUS(status)) ? -1 : 0;
- }
-# endif
-
- return 0;
-}
-
-# if defined(USE_ASYNC)
-static
-enum mad_flow send_io(int fd, void const *data, size_t len)
-{
- char const *ptr = data;
- ssize_t count;
-
- while (len) {
- do
- count = write(fd, ptr, len);
- while (count == -1 && errno == EINTR);
-
- if (count == -1)
- return MAD_FLOW_BREAK;
-
- len -= count;
- ptr += count;
- }
-
- return MAD_FLOW_CONTINUE;
-}
-
-static
-enum mad_flow receive_io(int fd, void *buffer, size_t len)
-{
- char *ptr = buffer;
- ssize_t count;
-
- while (len) {
- do
- count = read(fd, ptr, len);
- while (count == -1 && errno == EINTR);
-
- if (count == -1)
- return (errno == EAGAIN) ? MAD_FLOW_IGNORE : MAD_FLOW_BREAK;
- else if (count == 0)
- return MAD_FLOW_STOP;
-
- len -= count;
- ptr += count;
- }
-
- return MAD_FLOW_CONTINUE;
-}
-
-static
-enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len)
-{
- int flags, blocking;
- enum mad_flow result;
-
- flags = fcntl(fd, F_GETFL);
- if (flags == -1)
- return MAD_FLOW_BREAK;
-
- blocking = flags & ~O_NONBLOCK;
-
- if (blocking != flags &&
- fcntl(fd, F_SETFL, blocking) == -1)
- return MAD_FLOW_BREAK;
-
- result = receive_io(fd, buffer, len);
-
- if (flags != blocking &&
- fcntl(fd, F_SETFL, flags) == -1)
- return MAD_FLOW_BREAK;
-
- return result;
-}
-
-static
-enum mad_flow send(int fd, void const *message, unsigned int size)
-{
- enum mad_flow result;
-
- /* send size */
-
- result = send_io(fd, &size, sizeof(size));
-
- /* send message */
-
- if (result == MAD_FLOW_CONTINUE)
- result = send_io(fd, message, size);
-
- return result;
-}
-
-static
-enum mad_flow receive(int fd, void **message, unsigned int *size)
-{
- enum mad_flow result;
- unsigned int actual;
-
- if (*message == 0)
- *size = 0;
-
- /* receive size */
-
- result = receive_io(fd, &actual, sizeof(actual));
-
- /* receive message */
-
- if (result == MAD_FLOW_CONTINUE) {
- if (actual > *size)
- actual -= *size;
- else {
- *size = actual;
- actual = 0;
- }
-
- if (*size > 0) {
- if (*message == 0) {
- *message = malloc(*size);
- if (*message == 0)
- return MAD_FLOW_BREAK;
- }
-
- result = receive_io_blocking(fd, *message, *size);
- }
-
- /* throw away remainder of message */
-
- while (actual && result == MAD_FLOW_CONTINUE) {
- char sink[256];
- unsigned int len;
-
- len = actual > sizeof(sink) ? sizeof(sink) : actual;
-
- result = receive_io_blocking(fd, sink, len);
-
- actual -= len;
- }
- }
-
- return result;
-}
-
-static
-enum mad_flow check_message(struct mad_decoder *decoder)
-{
- enum mad_flow result;
- void *message = 0;
- unsigned int size;
-
- result = receive(decoder->async.in, &message, &size);
-
- if (result == MAD_FLOW_CONTINUE) {
- if (decoder->message_func == 0)
- size = 0;
- else {
- result = decoder->message_func(decoder->cb_data, message, &size);
-
- if (result == MAD_FLOW_IGNORE ||
- result == MAD_FLOW_BREAK)
- size = 0;
- }
-
- if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE)
- result = MAD_FLOW_BREAK;
- }
-
- if (message)
- free(message);
-
- return result;
-}
-# endif
-
-static
-enum mad_flow error_default(void *data, struct mad_stream *stream,
- struct mad_frame *frame)
-{
- int *bad_last_frame = data;
-
- switch (stream->error) {
- case MAD_ERROR_BADCRC:
- if (*bad_last_frame)
- mad_frame_mute(frame);
- else
- *bad_last_frame = 1;
-
- return MAD_FLOW_IGNORE;
-
- default:
- return MAD_FLOW_CONTINUE;
- }
-}
-
-static
-int run_sync(struct mad_decoder *decoder)
-{
- enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *);
- void *error_data;
- int bad_last_frame = 0;
- struct mad_stream *stream;
- struct mad_frame *frame;
- struct mad_synth *synth;
- int result = 0;
-
- if (decoder->input_func == 0)
- return 0;
-
- if (decoder->error_func) {
- error_func = decoder->error_func;
- error_data = decoder->cb_data;
- }
- else {
- error_func = error_default;
- error_data = &bad_last_frame;
- }
-
- stream = &decoder->sync->stream;
- frame = &decoder->sync->frame;
- synth = &decoder->sync->synth;
-
- mad_stream_init(stream);
- mad_frame_init(frame);
- mad_synth_init(synth);
-
- mad_stream_options(stream, decoder->options);
-
- do {
- switch (decoder->input_func(decoder->cb_data, stream)) {
- case MAD_FLOW_STOP:
- goto done;
- case MAD_FLOW_BREAK:
- goto fail;
- case MAD_FLOW_IGNORE:
- continue;
- case MAD_FLOW_CONTINUE:
- break;
- }
-
- while (1) {
-# if defined(USE_ASYNC)
- if (decoder->mode == MAD_DECODER_MODE_ASYNC) {
- switch (check_message(decoder)) {
- case MAD_FLOW_IGNORE:
- case MAD_FLOW_CONTINUE:
- break;
- case MAD_FLOW_BREAK:
- goto fail;
- case MAD_FLOW_STOP:
- goto done;
- }
- }
-# endif
-
- if (decoder->header_func) {
- if (mad_header_decode(&frame->header, stream) == -1) {
- if (!MAD_RECOVERABLE(stream->error))
- break;
-
- switch (error_func(error_data, stream, frame)) {
- case MAD_FLOW_STOP:
- goto done;
- case MAD_FLOW_BREAK:
- goto fail;
- case MAD_FLOW_IGNORE:
- case MAD_FLOW_CONTINUE:
- default:
- continue;
- }
- }
-
- switch (decoder->header_func(decoder->cb_data, &frame->header)) {
- case MAD_FLOW_STOP:
- goto done;
- case MAD_FLOW_BREAK:
- goto fail;
- case MAD_FLOW_IGNORE:
- continue;
- case MAD_FLOW_CONTINUE:
- break;
- }
- }
-
- if (mad_frame_decode(frame, stream) == -1) {
- if (!MAD_RECOVERABLE(stream->error))
- break;
-
- switch (error_func(error_data, stream, frame)) {
- case MAD_FLOW_STOP:
- goto done;
- case MAD_FLOW_BREAK:
- goto fail;
- case MAD_FLOW_IGNORE:
- break;
- case MAD_FLOW_CONTINUE:
- default:
- continue;
- }
- }
- else
- bad_last_frame = 0;
-
- if (decoder->filter_func) {
- switch (decoder->filter_func(decoder->cb_data, stream, frame)) {
- case MAD_FLOW_STOP:
- goto done;
- case MAD_FLOW_BREAK:
- goto fail;
- case MAD_FLOW_IGNORE:
- continue;
- case MAD_FLOW_CONTINUE:
- break;
- }
- }
-
- mad_synth_frame(synth, frame);
-
- if (decoder->output_func) {
- switch (decoder->output_func(decoder->cb_data,
- &frame->header, &synth->pcm)) {
- case MAD_FLOW_STOP:
- goto done;
- case MAD_FLOW_BREAK:
- goto fail;
- case MAD_FLOW_IGNORE:
- case MAD_FLOW_CONTINUE:
- break;
- }
- }
- }
- }
- while (stream->error == MAD_ERROR_BUFLEN);
-
- fail:
- result = -1;
-
- done:
- mad_synth_finish(synth);
- mad_frame_finish(frame);
- mad_stream_finish(stream);
-
- return result;
-}
-
-# if defined(USE_ASYNC)
-static
-int run_async(struct mad_decoder *decoder)
-{
- pid_t pid;
- int ptoc[2], ctop[2], flags;
-
- if (pipe(ptoc) == -1)
- return -1;
-
- if (pipe(ctop) == -1) {
- close(ptoc[0]);
- close(ptoc[1]);
- return -1;
- }
-
- flags = fcntl(ptoc[0], F_GETFL);
- if (flags == -1 ||
- fcntl(ptoc[0], F_SETFL, flags | O_NONBLOCK) == -1) {
- close(ctop[0]);
- close(ctop[1]);
- close(ptoc[0]);
- close(ptoc[1]);
- return -1;
- }
-
- pid = fork();
- if (pid == -1) {
- close(ctop[0]);
- close(ctop[1]);
- close(ptoc[0]);
- close(ptoc[1]);
- return -1;
- }
-
- decoder->async.pid = pid;
-
- if (pid) {
- /* parent */
-
- close(ptoc[0]);
- close(ctop[1]);
-
- decoder->async.in = ctop[0];
- decoder->async.out = ptoc[1];
-
- return 0;
- }
-
- /* child */
-
- close(ptoc[1]);
- close(ctop[0]);
-
- decoder->async.in = ptoc[0];
- decoder->async.out = ctop[1];
-
- _exit(run_sync(decoder));
-
- /* not reached */
- return -1;
-}
-# endif
-
-/*
- * NAME: decoder->run()
- * DESCRIPTION: run the decoder thread either synchronously or asynchronously
- */
-int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode)
-{
- int result;
- int (*run)(struct mad_decoder *) = 0;
-
- switch (decoder->mode = mode) {
- case MAD_DECODER_MODE_SYNC:
- run = run_sync;
- break;
-
- case MAD_DECODER_MODE_ASYNC:
-# if defined(USE_ASYNC)
- run = run_async;
-# endif
- break;
- }
-
- if (run == 0)
- return -1;
-
- decoder->sync = malloc(sizeof(*decoder->sync));
- if (decoder->sync == 0)
- return -1;
-
- result = run(decoder);
-
- free(decoder->sync);
- decoder->sync = 0;
-
- return result;
-}
-
-/*
- * NAME: decoder->message()
- * DESCRIPTION: send a message to and receive a reply from the decoder process
- */
-int mad_decoder_message(struct mad_decoder *decoder,
- void *message, unsigned int *len)
-{
-# if defined(USE_ASYNC)
- if (decoder->mode != MAD_DECODER_MODE_ASYNC ||
- send(decoder->async.out, message, *len) != MAD_FLOW_CONTINUE ||
- receive(decoder->async.in, &message, len) != MAD_FLOW_CONTINUE)
- return -1;
-
- return 0;
-# else
- return -1;
-# endif
-}
diff --git a/libmad/src/decoder.h b/libmad/src/decoder.h
deleted file mode 100644
index f0ad758..0000000
--- a/libmad/src/decoder.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: decoder.h,v 1.17 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBMAD_DECODER_H
-# define LIBMAD_DECODER_H
-
-# include "stream.h"
-# include "frame.h"
-# include "synth.h"
-
-enum mad_decoder_mode {
- MAD_DECODER_MODE_SYNC = 0,
- MAD_DECODER_MODE_ASYNC
-};
-
-enum mad_flow {
- MAD_FLOW_CONTINUE = 0x0000, /* continue normally */
- MAD_FLOW_STOP = 0x0010, /* stop decoding normally */
- MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */
- MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */
-};
-
-struct mad_decoder {
- enum mad_decoder_mode mode;
-
- int options;
-
- struct {
- long pid;
- int in;
- int out;
- } async;
-
- struct {
- struct mad_stream stream;
- struct mad_frame frame;
- struct mad_synth synth;
- } *sync;
-
- void *cb_data;
-
- enum mad_flow (*input_func)(void *, struct mad_stream *);
- enum mad_flow (*header_func)(void *, struct mad_header const *);
- enum mad_flow (*filter_func)(void *,
- struct mad_stream const *, struct mad_frame *);
- enum mad_flow (*output_func)(void *,
- struct mad_header const *, struct mad_pcm *);
- enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *);
- enum mad_flow (*message_func)(void *, void *, unsigned int *);
-};
-
-void mad_decoder_init(struct mad_decoder *, void *,
- enum mad_flow (*)(void *, struct mad_stream *),
- enum mad_flow (*)(void *, struct mad_header const *),
- enum mad_flow (*)(void *,
- struct mad_stream const *,
- struct mad_frame *),
- enum mad_flow (*)(void *,
- struct mad_header const *,
- struct mad_pcm *),
- enum mad_flow (*)(void *,
- struct mad_stream *,
- struct mad_frame *),
- enum mad_flow (*)(void *, void *, unsigned int *));
-int mad_decoder_finish(struct mad_decoder *);
-
-# define mad_decoder_options(decoder, opts) \
- ((void) ((decoder)->options = (opts)))
-
-int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode);
-int mad_decoder_message(struct mad_decoder *, void *, unsigned int *);
-
-# endif
diff --git a/libmad/src/fixed.c b/libmad/src/fixed.c
deleted file mode 100644
index 081d3bc..0000000
--- a/libmad/src/fixed.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: fixed.c,v 1.13 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include "fixed.h"
-
-# ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4244 4018 4146)
-# endif
-
-/*
- * NAME: fixed->abs()
- * DESCRIPTION: return absolute value of a fixed-point number
- */
-mad_fixed_t mad_f_abs(mad_fixed_t x)
-{
- return x < 0 ? -x : x;
-}
-
-/*
- * NAME: fixed->div()
- * DESCRIPTION: perform division using fixed-point math
- */
-mad_fixed_t mad_f_div(mad_fixed_t x, mad_fixed_t y)
-{
- mad_fixed_t q, r;
- unsigned int bits;
-
- q = mad_f_abs(x / y);
-
- if (x < 0) {
- x = -x;
- y = -y;
- }
-
- r = x % y;
-
- if (y < 0) {
- x = -x;
- y = -y;
- }
-
- if (q > mad_f_intpart(MAD_F_MAX) &&
- !(q == -mad_f_intpart(MAD_F_MIN) && r == 0 && (x < 0) != (y < 0)))
- return 0;
-
- for (bits = MAD_F_FRACBITS; bits && r; --bits) {
- q <<= 1, r <<= 1;
- if (r >= y)
- r -= y, ++q;
- }
-
- /* round */
- if (2 * r >= y)
- ++q;
-
- /* fix sign */
- if ((x < 0) != (y < 0))
- q = -q;
-
- return q << bits;
-}
-
-# ifdef _MSC_VER
-# pragma warning(pop)
-# endif
diff --git a/libmad/src/fixed.h b/libmad/src/fixed.h
deleted file mode 100644
index 4b58abf..0000000
--- a/libmad/src/fixed.h
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: fixed.h,v 1.38 2004/02/17 02:02:03 rob Exp $
- */
-
-# ifndef LIBMAD_FIXED_H
-# define LIBMAD_FIXED_H
-
-# if SIZEOF_INT >= 4
-typedef signed int mad_fixed_t;
-
-typedef signed int mad_fixed64hi_t;
-typedef unsigned int mad_fixed64lo_t;
-# else
-typedef signed long mad_fixed_t;
-
-typedef signed long mad_fixed64hi_t;
-typedef unsigned long mad_fixed64lo_t;
-# endif
-
-# if defined(_MSC_VER)
-# define mad_fixed64_t signed __int64
-# elif 1 || defined(__GNUC__)
-# define mad_fixed64_t signed long long
-# endif
-
-# if defined(FPM_FLOAT)
-typedef double mad_sample_t;
-# else
-typedef mad_fixed_t mad_sample_t;
-# endif
-
-/*
- * Fixed-point format: 0xABBBBBBB
- * A == whole part (sign + 3 bits)
- * B == fractional part (28 bits)
- *
- * Values are signed two's complement, so the effective range is:
- * 0x80000000 to 0x7fffffff
- * -8.0 to +7.9999999962747097015380859375
- *
- * The smallest representable value is:
- * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9)
- *
- * 28 bits of fractional accuracy represent about
- * 8.6 digits of decimal accuracy.
- *
- * Fixed-point numbers can be added or subtracted as normal
- * integers, but multiplication requires shifting the 64-bit result
- * from 56 fractional bits back to 28 (and rounding.)
- *
- * Changing the definition of MAD_F_FRACBITS is only partially
- * supported, and must be done with care.
- */
-
-# define MAD_F_FRACBITS 28
-
-# if MAD_F_FRACBITS == 28
-# define MAD_F(x) ((mad_fixed_t) (x##L))
-# else
-# if MAD_F_FRACBITS < 28
-# warning "MAD_F_FRACBITS < 28"
-# define MAD_F(x) ((mad_fixed_t) \
- (((x##L) + \
- (1L << (28 - MAD_F_FRACBITS - 1))) >> \
- (28 - MAD_F_FRACBITS)))
-# elif MAD_F_FRACBITS > 28
-# error "MAD_F_FRACBITS > 28 not currently supported"
-# define MAD_F(x) ((mad_fixed_t) \
- ((x##L) << (MAD_F_FRACBITS - 28)))
-# endif
-# endif
-
-# define MAD_F_MIN ((mad_fixed_t) -0x80000000L)
-# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL)
-
-# define MAD_F_ONE MAD_F(0x10000000)
-
-# define mad_f_tofixed(x) ((mad_fixed_t) \
- ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5))
-# define mad_f_todouble(x) ((double) \
- ((x) / (double) (1L << MAD_F_FRACBITS)))
-
-# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS)
-# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1))
- /* (x should be positive) */
-
-# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS)
-
-# define mad_f_add(x, y) ((x) + (y))
-# define mad_f_sub(x, y) ((x) - (y))
-
-# if defined(FPM_FLOAT)
-# error "FPM_FLOAT not yet supported"
-
-# undef MAD_F
-# define MAD_F(x) mad_f_todouble(x)
-
-# define mad_f_mul(x, y) ((x) * (y))
-# define mad_f_scale64
-
-# undef ASO_ZEROCHECK
-
-# elif defined(FPM_64BIT)
-
-/*
- * This version should be the most accurate if 64-bit types are supported by
- * the compiler, although it may not be the most efficient.
- */
-# if defined(OPT_ACCURACY)
-# define mad_f_mul(x, y) \
- ((mad_fixed_t) \
- ((((mad_fixed64_t) (x) * (y)) + \
- (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS))
-# else
-# define mad_f_mul(x, y) \
- ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS))
-# endif
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-
-/* --- Intel --------------------------------------------------------------- */
-
-# elif defined(FPM_INTEL)
-
-# if defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning(disable: 4035) /* no return value */
-static __forceinline
-mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y)
-{
- enum {
- fracbits = MAD_F_FRACBITS
- };
-
- __asm {
- mov eax, x
- imul y
- shrd eax, edx, fracbits
- }
-
- /* implicit return of eax */
-}
-# pragma warning(pop)
-
-# define mad_f_mul mad_f_mul_inline
-# define mad_f_scale64
-# else
-/*
- * This Intel version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("imull %3" \
- : "=a" (lo), "=d" (hi) \
- : "%a" (x), "rm" (y) \
- : "cc")
-
-# if defined(OPT_ACCURACY)
-/*
- * This gives best accuracy but is not very fast.
- */
-# define MAD_F_MLA(hi, lo, x, y) \
- ({ mad_fixed64hi_t __hi; \
- mad_fixed64lo_t __lo; \
- MAD_F_MLX(__hi, __lo, (x), (y)); \
- asm ("addl %2,%0\n\t" \
- "adcl %3,%1" \
- : "=rm" (lo), "=rm" (hi) \
- : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \
- : "cc"); \
- })
-# endif /* OPT_ACCURACY */
-
-# if defined(OPT_ACCURACY)
-/*
- * Surprisingly, this is faster than SHRD followed by ADC.
- */
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed64hi_t __hi_; \
- mad_fixed64lo_t __lo_; \
- mad_fixed_t __result; \
- asm ("addl %4,%2\n\t" \
- "adcl %5,%3" \
- : "=rm" (__lo_), "=rm" (__hi_) \
- : "0" (lo), "1" (hi), \
- "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \
- : "cc"); \
- asm ("shrdl %3,%2,%1" \
- : "=rm" (__result) \
- : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-# elif defined(OPT_INTEL)
-/*
- * Alternate Intel scaling that may or may not perform better.
- */
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result; \
- asm ("shrl %3,%1\n\t" \
- "shll %4,%2\n\t" \
- "orl %2,%1" \
- : "=rm" (__result) \
- : "0" (lo), "r" (hi), \
- "I" (MAD_F_SCALEBITS), "I" (32 - MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-# else
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result; \
- asm ("shrdl %3,%2,%1" \
- : "=rm" (__result) \
- : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-# endif /* OPT_ACCURACY */
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-# endif
-
-/* --- ARM ----------------------------------------------------------------- */
-
-# elif defined(FPM_ARM)
-
-/*
- * This ARM V4 version is as accurate as FPM_64BIT but much faster. The
- * least significant bit is properly rounded at no CPU cycle cost!
- */
-# if 1
-/*
- * This is faster than the default implementation via MAD_F_MLX() and
- * mad_f_scale64().
- */
-# define mad_f_mul(x, y) \
- ({ mad_fixed64hi_t __hi; \
- mad_fixed64lo_t __lo; \
- mad_fixed_t __result; \
- asm ("smull %0, %1, %3, %4\n\t" \
- "movs %0, %0, lsr %5\n\t" \
- "adc %2, %0, %1, lsl %6" \
- : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \
- : "%r" (x), "r" (y), \
- "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-# endif
-
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("smull %0, %1, %2, %3" \
- : "=&r" (lo), "=&r" (hi) \
- : "%r" (x), "r" (y))
-
-# define MAD_F_MLA(hi, lo, x, y) \
- asm ("smlal %0, %1, %2, %3" \
- : "+r" (lo), "+r" (hi) \
- : "%r" (x), "r" (y))
-
-# define MAD_F_MLN(hi, lo) \
- asm ("rsbs %0, %2, #0\n\t" \
- "rsc %1, %3, #0" \
- : "=r" (lo), "=r" (hi) \
- : "0" (lo), "1" (hi) \
- : "cc")
-
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result; \
- asm ("movs %0, %1, lsr %3\n\t" \
- "adc %0, %0, %2, lsl %4" \
- : "=&r" (__result) \
- : "r" (lo), "r" (hi), \
- "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \
- : "cc"); \
- __result; \
- })
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-
-/* --- MIPS ---------------------------------------------------------------- */
-
-# elif defined(FPM_MIPS)
-
-/*
- * This MIPS version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("mult %2,%3" \
- : "=l" (lo), "=h" (hi) \
- : "%r" (x), "r" (y))
-
-# if defined(HAVE_MADD_ASM)
-# define MAD_F_MLA(hi, lo, x, y) \
- asm ("madd %2,%3" \
- : "+l" (lo), "+h" (hi) \
- : "%r" (x), "r" (y))
-# elif defined(HAVE_MADD16_ASM)
-/*
- * This loses significant accuracy due to the 16-bit integer limit in the
- * multiply/accumulate instruction.
- */
-# define MAD_F_ML0(hi, lo, x, y) \
- asm ("mult %2,%3" \
- : "=l" (lo), "=h" (hi) \
- : "%r" ((x) >> 12), "r" ((y) >> 16))
-# define MAD_F_MLA(hi, lo, x, y) \
- asm ("madd16 %2,%3" \
- : "+l" (lo), "+h" (hi) \
- : "%r" ((x) >> 12), "r" ((y) >> 16))
-# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo))
-# endif
-
-# if defined(OPT_SPEED)
-# define mad_f_scale64(hi, lo) \
- ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS)))
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-# endif
-
-/* --- SPARC --------------------------------------------------------------- */
-
-# elif defined(FPM_SPARC)
-
-/*
- * This SPARC V8 version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- asm ("smul %2, %3, %0\n\t" \
- "rd %%y, %1" \
- : "=r" (lo), "=r" (hi) \
- : "%r" (x), "rI" (y))
-
-/* --- PowerPC ------------------------------------------------------------- */
-
-# elif defined(FPM_PPC)
-
-/*
- * This PowerPC version is fast and accurate; the disposition of the least
- * significant bit depends on OPT_ACCURACY via mad_f_scale64().
- */
-# define MAD_F_MLX(hi, lo, x, y) \
- do { \
- asm ("mullw %0,%1,%2" \
- : "=r" (lo) \
- : "%r" (x), "r" (y)); \
- asm ("mulhw %0,%1,%2" \
- : "=r" (hi) \
- : "%r" (x), "r" (y)); \
- } \
- while (0)
-
-# if defined(OPT_ACCURACY)
-/*
- * This gives best accuracy but is not very fast.
- */
-# define MAD_F_MLA(hi, lo, x, y) \
- ({ mad_fixed64hi_t __hi; \
- mad_fixed64lo_t __lo; \
- MAD_F_MLX(__hi, __lo, (x), (y)); \
- asm ("addc %0,%2,%3\n\t" \
- "adde %1,%4,%5" \
- : "=r" (lo), "=r" (hi) \
- : "%r" (lo), "r" (__lo), \
- "%r" (hi), "r" (__hi) \
- : "xer"); \
- })
-# endif
-
-# if defined(OPT_ACCURACY)
-/*
- * This is slower than the truncating version below it.
- */
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result, __round; \
- asm ("rotrwi %0,%1,%2" \
- : "=r" (__result) \
- : "r" (lo), "i" (MAD_F_SCALEBITS)); \
- asm ("extrwi %0,%1,1,0" \
- : "=r" (__round) \
- : "r" (__result)); \
- asm ("insrwi %0,%1,%2,0" \
- : "+r" (__result) \
- : "r" (hi), "i" (MAD_F_SCALEBITS)); \
- asm ("add %0,%1,%2" \
- : "=r" (__result) \
- : "%r" (__result), "r" (__round)); \
- __result; \
- })
-# else
-# define mad_f_scale64(hi, lo) \
- ({ mad_fixed_t __result; \
- asm ("rotrwi %0,%1,%2" \
- : "=r" (__result) \
- : "r" (lo), "i" (MAD_F_SCALEBITS)); \
- asm ("insrwi %0,%1,%2,0" \
- : "+r" (__result) \
- : "r" (hi), "i" (MAD_F_SCALEBITS)); \
- __result; \
- })
-# endif
-
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-
-/* --- Default ------------------------------------------------------------- */
-
-# elif defined(FPM_DEFAULT)
-
-/*
- * This version is the most portable but it loses significant accuracy.
- * Furthermore, accuracy is biased against the second argument, so care
- * should be taken when ordering operands.
- *
- * The scale factors are constant as this is not used with SSO.
- *
- * Pre-rounding is required to stay within the limits of compliance.
- */
-# if defined(OPT_SPEED)
-# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16))
-# else
-# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \
- (((y) + (1L << 15)) >> 16))
-# endif
-
-/* ------------------------------------------------------------------------- */
-
-# else
-# error "no FPM selected"
-# endif
-
-/* default implementations */
-
-# if !defined(mad_f_mul)
-# define mad_f_mul(x, y) \
- ({ register mad_fixed64hi_t __hi; \
- register mad_fixed64lo_t __lo; \
- MAD_F_MLX(__hi, __lo, (x), (y)); \
- mad_f_scale64(__hi, __lo); \
- })
-# endif
-
-# if !defined(MAD_F_MLA)
-# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y)))
-# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y)))
-# define MAD_F_MLN(hi, lo) ((lo) = -(lo))
-# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo))
-# endif
-
-# if !defined(MAD_F_ML0)
-# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y))
-# endif
-
-# if !defined(MAD_F_MLN)
-# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi))
-# endif
-
-# if !defined(MAD_F_MLZ)
-# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo))
-# endif
-
-# if !defined(mad_f_scale64)
-# if defined(OPT_ACCURACY)
-# define mad_f_scale64(hi, lo) \
- ((((mad_fixed_t) \
- (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \
- ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1)
-# else
-# define mad_f_scale64(hi, lo) \
- ((mad_fixed_t) \
- (((hi) << (32 - MAD_F_SCALEBITS)) | \
- ((lo) >> MAD_F_SCALEBITS)))
-# endif
-# define MAD_F_SCALEBITS MAD_F_FRACBITS
-# endif
-
-/* C routines */
-
-mad_fixed_t mad_f_abs(mad_fixed_t);
-mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t);
-
-# endif
diff --git a/libmad/src/frame.c b/libmad/src/frame.c
deleted file mode 100644
index 37acbfa..0000000
--- a/libmad/src/frame.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: frame.c,v 1.29 2004/02/04 22:59:19 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-
-# include "bit.h"
-# include "stream.h"
-# include "frame.h"
-# include "timer.h"
-# include "layer12.h"
-# include "layer3.h"
-
-# ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4244 4018)
-# endif
-
-static
-unsigned long const bitrate_table[5][15] = {
- /* MPEG-1 */
- { 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, /* Layer I */
- 256000, 288000, 320000, 352000, 384000, 416000, 448000 },
- { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer II */
- 128000, 160000, 192000, 224000, 256000, 320000, 384000 },
- { 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, /* Layer III */
- 112000, 128000, 160000, 192000, 224000, 256000, 320000 },
-
- /* MPEG-2 LSF */
- { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer I */
- 128000, 144000, 160000, 176000, 192000, 224000, 256000 },
- { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, /* Layers */
- 64000, 80000, 96000, 112000, 128000, 144000, 160000 } /* II & III */
-};
-
-static
-unsigned int const samplerate_table[3] = { 44100, 48000, 32000 };
-
-static
-int (*const decoder_table[3])(struct mad_stream *, struct mad_frame *) = {
- mad_layer_I,
- mad_layer_II,
- mad_layer_III
-};
-
-/*
- * NAME: header->init()
- * DESCRIPTION: initialize header struct
- */
-void mad_header_init(struct mad_header *header)
-{
- header->layer = 0;
- header->mode = 0;
- header->mode_extension = 0;
- header->emphasis = 0;
-
- header->bitrate = 0;
- header->samplerate = 0;
-
- header->crc_check = 0;
- header->crc_target = 0;
-
- header->flags = 0;
- header->private_bits = 0;
-
- header->duration = mad_timer_zero;
-}
-
-/*
- * NAME: frame->init()
- * DESCRIPTION: initialize frame struct
- */
-void mad_frame_init(struct mad_frame *frame)
-{
- mad_header_init(&frame->header);
-
- frame->options = 0;
-
- frame->overlap = 0;
- mad_frame_mute(frame);
-}
-
-/*
- * NAME: frame->finish()
- * DESCRIPTION: deallocate any dynamic memory associated with frame
- */
-void mad_frame_finish(struct mad_frame *frame)
-{
- mad_header_finish(&frame->header);
-
- if (frame->overlap) {
- free(frame->overlap);
- frame->overlap = 0;
- }
-}
-
-/*
- * NAME: decode_header()
- * DESCRIPTION: read header data and following CRC word
- */
-static
-int decode_header(struct mad_header *header, struct mad_stream *stream)
-{
- unsigned int index;
-
- header->flags = 0;
- header->private_bits = 0;
-
- /* header() */
-
- /* syncword */
- mad_bit_skip(&stream->ptr, 11);
-
- /* MPEG 2.5 indicator (really part of syncword) */
- if (mad_bit_read(&stream->ptr, 1) == 0)
- header->flags |= MAD_FLAG_MPEG_2_5_EXT;
-
- /* ID */
- if (mad_bit_read(&stream->ptr, 1) == 0)
- header->flags |= MAD_FLAG_LSF_EXT;
- else if (header->flags & MAD_FLAG_MPEG_2_5_EXT) {
- stream->error = MAD_ERROR_LOSTSYNC;
- return -1;
- }
-
- /* layer */
- header->layer = 4 - mad_bit_read(&stream->ptr, 2);
-
- if (header->layer == 4) {
- stream->error = MAD_ERROR_BADLAYER;
- return -1;
- }
-
- /* protection_bit */
- if (mad_bit_read(&stream->ptr, 1) == 0) {
- header->flags |= MAD_FLAG_PROTECTION;
- header->crc_check = mad_bit_crc(stream->ptr, 16, 0xffff);
- }
-
- /* bitrate_index */
- index = mad_bit_read(&stream->ptr, 4);
-
- if (index == 15) {
- stream->error = MAD_ERROR_BADBITRATE;
- return -1;
- }
-
- if (header->flags & MAD_FLAG_LSF_EXT)
- header->bitrate = bitrate_table[3 + (header->layer >> 1)][index];
- else
- header->bitrate = bitrate_table[header->layer - 1][index];
-
- /* sampling_frequency */
- index = mad_bit_read(&stream->ptr, 2);
-
- if (index == 3) {
- stream->error = MAD_ERROR_BADSAMPLERATE;
- return -1;
- }
-
- header->samplerate = samplerate_table[index];
-
- if (header->flags & MAD_FLAG_LSF_EXT) {
- header->samplerate /= 2;
-
- if (header->flags & MAD_FLAG_MPEG_2_5_EXT)
- header->samplerate /= 2;
- }
-
- /* padding_bit */
- if (mad_bit_read(&stream->ptr, 1))
- header->flags |= MAD_FLAG_PADDING;
-
- /* private_bit */
- if (mad_bit_read(&stream->ptr, 1))
- header->private_bits |= MAD_PRIVATE_HEADER;
-
- /* mode */
- header->mode = 3 - mad_bit_read(&stream->ptr, 2);
-
- /* mode_extension */
- header->mode_extension = mad_bit_read(&stream->ptr, 2);
-
- /* copyright */
- if (mad_bit_read(&stream->ptr, 1))
- header->flags |= MAD_FLAG_COPYRIGHT;
-
- /* original/copy */
- if (mad_bit_read(&stream->ptr, 1))
- header->flags |= MAD_FLAG_ORIGINAL;
-
- /* emphasis */
- header->emphasis = mad_bit_read(&stream->ptr, 2);
-
-# if defined(OPT_STRICT)
- /*
- * ISO/IEC 11172-3 says this is a reserved emphasis value, but
- * streams exist which use it anyway. Since the value is not important
- * to the decoder proper, we allow it unless OPT_STRICT is defined.
- */
- if (header->emphasis == MAD_EMPHASIS_RESERVED) {
- stream->error = MAD_ERROR_BADEMPHASIS;
- return -1;
- }
-# endif
-
- /* error_check() */
-
- /* crc_check */
- if (header->flags & MAD_FLAG_PROTECTION)
- header->crc_target = mad_bit_read(&stream->ptr, 16);
-
- return 0;
-}
-
-/*
- * NAME: free_bitrate()
- * DESCRIPTION: attempt to discover the bitstream's free bitrate
- */
-static
-int free_bitrate(struct mad_stream *stream, struct mad_header const *header)
-{
- struct mad_bitptr keep_ptr;
- unsigned long rate = 0;
- unsigned int pad_slot, slots_per_frame;
- unsigned char const *ptr = 0;
-
- keep_ptr = stream->ptr;
-
- pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0;
- slots_per_frame = (header->layer == MAD_LAYER_III &&
- (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144;
-
- while (mad_stream_sync(stream) == 0) {
- struct mad_stream peek_stream;
- struct mad_header peek_header;
-
- peek_stream = *stream;
- peek_header = *header;
-
- if (decode_header(&peek_header, &peek_stream) == 0 &&
- peek_header.layer == header->layer &&
- peek_header.samplerate == header->samplerate) {
- unsigned int N;
-
- ptr = mad_bit_nextbyte(&stream->ptr);
-
- N = ptr - stream->this_frame;
-
- if (header->layer == MAD_LAYER_I) {
- rate = (unsigned long) header->samplerate *
- (N - 4 * pad_slot + 4) / 48 / 1000;
- }
- else {
- rate = (unsigned long) header->samplerate *
- (N - pad_slot + 1) / slots_per_frame / 1000;
- }
-
- if (rate >= 8)
- break;
- }
-
- mad_bit_skip(&stream->ptr, 8);
- }
-
- stream->ptr = keep_ptr;
-
- if (rate < 8 || (header->layer == MAD_LAYER_III && rate > 640)) {
- stream->error = MAD_ERROR_LOSTSYNC;
- return -1;
- }
-
- stream->freerate = rate * 1000;
-
- return 0;
-}
-
-/*
- * NAME: header->decode()
- * DESCRIPTION: read the next frame header from the stream
- */
-int mad_header_decode(struct mad_header *header, struct mad_stream *stream)
-{
- register unsigned char const *ptr, *end;
- unsigned int pad_slot, N;
-
- ptr = stream->next_frame;
- end = stream->bufend;
-
- if (ptr == 0) {
- stream->error = MAD_ERROR_BUFPTR;
- goto fail;
- }
-
- /* stream skip */
- if (stream->skiplen) {
- if (!stream->sync)
- ptr = stream->this_frame;
-
- if (end - ptr < stream->skiplen) {
- stream->skiplen -= end - ptr;
- stream->next_frame = end;
-
- stream->error = MAD_ERROR_BUFLEN;
- goto fail;
- }
-
- ptr += stream->skiplen;
- stream->skiplen = 0;
-
- stream->sync = 1;
- }
-
- sync:
- /* synchronize */
- if (stream->sync) {
- if (end - ptr < MAD_BUFFER_GUARD) {
- stream->next_frame = ptr;
-
- stream->error = MAD_ERROR_BUFLEN;
- goto fail;
- }
- else if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) {
- /* mark point where frame sync word was expected */
- stream->this_frame = ptr;
- stream->next_frame = ptr + 1;
-
- stream->error = MAD_ERROR_LOSTSYNC;
- goto fail;
- }
- }
- else {
- mad_bit_init(&stream->ptr, ptr);
-
- if (mad_stream_sync(stream) == -1) {
- if (end - stream->next_frame >= MAD_BUFFER_GUARD)
- stream->next_frame = end - MAD_BUFFER_GUARD;
-
- stream->error = MAD_ERROR_BUFLEN;
- goto fail;
- }
-
- ptr = mad_bit_nextbyte(&stream->ptr);
- }
-
- /* begin processing */
- stream->this_frame = ptr;
- stream->next_frame = ptr + 1; /* possibly bogus sync word */
-
- mad_bit_init(&stream->ptr, stream->this_frame);
-
- if (decode_header(header, stream) == -1)
- goto fail;
-
- /* calculate frame duration */
- mad_timer_set(&header->duration, 0,
- 32 * MAD_NSBSAMPLES(header), header->samplerate);
-
- /* calculate free bit rate */
- if (header->bitrate == 0) {
- if ((stream->freerate == 0 || !stream->sync ||
- (header->layer == MAD_LAYER_III && stream->freerate > 640000)) &&
- free_bitrate(stream, header) == -1)
- goto fail;
-
- header->bitrate = stream->freerate;
- header->flags |= MAD_FLAG_FREEFORMAT;
- }
-
- /* calculate beginning of next frame */
- pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0;
-
- if (header->layer == MAD_LAYER_I)
- N = ((12 * header->bitrate / header->samplerate) + pad_slot) * 4;
- else {
- unsigned int slots_per_frame;
-
- slots_per_frame = (header->layer == MAD_LAYER_III &&
- (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144;
-
- N = (slots_per_frame * header->bitrate / header->samplerate) + pad_slot;
- }
-
- /* verify there is enough data left in buffer to decode this frame */
- if (N + MAD_BUFFER_GUARD > end - stream->this_frame) {
- stream->next_frame = stream->this_frame;
-
- stream->error = MAD_ERROR_BUFLEN;
- goto fail;
- }
-
- stream->next_frame = stream->this_frame + N;
-
- if (!stream->sync) {
- /* check that a valid frame header follows this frame */
-
- ptr = stream->next_frame;
- if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) {
- ptr = stream->next_frame = stream->this_frame + 1;
- goto sync;
- }
-
- stream->sync = 1;
- }
-
- header->flags |= MAD_FLAG_INCOMPLETE;
-
- return 0;
-
- fail:
- stream->sync = 0;
-
- return -1;
-}
-
-/*
- * NAME: frame->decode()
- * DESCRIPTION: decode a single frame from a bitstream
- */
-int mad_frame_decode(struct mad_frame *frame, struct mad_stream *stream)
-{
- frame->options = stream->options;
-
- /* header() */
- /* error_check() */
-
- if (!(frame->header.flags & MAD_FLAG_INCOMPLETE) &&
- mad_header_decode(&frame->header, stream) == -1)
- goto fail;
-
- /* audio_data() */
-
- frame->header.flags &= ~MAD_FLAG_INCOMPLETE;
-
- if (decoder_table[frame->header.layer - 1](stream, frame) == -1) {
- if (!MAD_RECOVERABLE(stream->error))
- stream->next_frame = stream->this_frame;
-
- goto fail;
- }
-
- /* ancillary_data() */
-
- if (frame->header.layer != MAD_LAYER_III) {
- struct mad_bitptr next_frame;
-
- mad_bit_init(&next_frame, stream->next_frame);
-
- stream->anc_ptr = stream->ptr;
- stream->anc_bitlen = mad_bit_length(&stream->ptr, &next_frame);
-
- mad_bit_finish(&next_frame);
- }
-
- return 0;
-
- fail:
- stream->anc_bitlen = 0;
- return -1;
-}
-
-/*
- * NAME: frame->mute()
- * DESCRIPTION: zero all subband values so the frame becomes silent
- */
-void mad_frame_mute(struct mad_frame *frame)
-{
- unsigned int s, sb;
-
- for (s = 0; s < 36; ++s) {
- for (sb = 0; sb < 32; ++sb) {
- frame->sbsample[0][s][sb] =
- frame->sbsample[1][s][sb] = 0;
- }
- }
-
- if (frame->overlap) {
- for (s = 0; s < 18; ++s) {
- for (sb = 0; sb < 32; ++sb) {
- (*frame->overlap)[0][sb][s] =
- (*frame->overlap)[1][sb][s] = 0;
- }
- }
- }
-}
-
-# ifdef _MSC_VER
-# pragma warning(pop)
-# endif
diff --git a/libmad/src/frame.h b/libmad/src/frame.h
deleted file mode 100644
index 3f5bf37..0000000
--- a/libmad/src/frame.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: frame.h,v 1.20 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBMAD_FRAME_H
-# define LIBMAD_FRAME_H
-
-# include "fixed.h"
-# include "timer.h"
-# include "stream.h"
-
-enum mad_layer {
- MAD_LAYER_I = 1, /* Layer I */
- MAD_LAYER_II = 2, /* Layer II */
- MAD_LAYER_III = 3 /* Layer III */
-};
-
-enum mad_mode {
- MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */
- MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */
- MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */
- MAD_MODE_STEREO = 3 /* normal LR stereo */
-};
-
-enum mad_emphasis {
- MAD_EMPHASIS_NONE = 0, /* no emphasis */
- MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */
- MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */
- MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */
-};
-
-struct mad_header {
- enum mad_layer layer; /* audio layer (1, 2, or 3) */
- enum mad_mode mode; /* channel mode (see above) */
- int mode_extension; /* additional mode info */
- enum mad_emphasis emphasis; /* de-emphasis to use (see above) */
-
- unsigned long bitrate; /* stream bitrate (bps) */
- unsigned int samplerate; /* sampling frequency (Hz) */
-
- unsigned short crc_check; /* frame CRC accumulator */
- unsigned short crc_target; /* final target CRC checksum */
-
- int flags; /* flags (see below) */
- int private_bits; /* private bits (see below) */
-
- mad_timer_t duration; /* audio playing time of frame */
-};
-
-struct mad_frame {
- struct mad_header header; /* MPEG audio header */
-
- int options; /* decoding options (from stream) */
-
- mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */
- mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */
-};
-
-# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1)
-# define MAD_NSBSAMPLES(header) \
- ((header)->layer == MAD_LAYER_I ? 12 : \
- (((header)->layer == MAD_LAYER_III && \
- ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36))
-
-enum {
- MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */
- MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */
-
- MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */
- MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */
- MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */
- MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */
-
- MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */
- MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */
- MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */
-
- MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */
- MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */
- MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */
-};
-
-enum {
- MAD_PRIVATE_HEADER = 0x0100, /* header private bit */
- MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */
-};
-
-void mad_header_init(struct mad_header *);
-
-# define mad_header_finish(header) /* nothing */
-
-int mad_header_decode(struct mad_header *, struct mad_stream *);
-
-void mad_frame_init(struct mad_frame *);
-void mad_frame_finish(struct mad_frame *);
-
-int mad_frame_decode(struct mad_frame *, struct mad_stream *);
-
-void mad_frame_mute(struct mad_frame *);
-
-# endif
diff --git a/libmad/src/global.h b/libmad/src/global.h
deleted file mode 100644
index a6debfd..0000000
--- a/libmad/src/global.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: global.h,v 1.11 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBMAD_GLOBAL_H
-# define LIBMAD_GLOBAL_H
-
-/* conditional debugging */
-
-# if defined(DEBUG) && defined(NDEBUG)
-# error "cannot define both DEBUG and NDEBUG"
-# endif
-
-# if defined(DEBUG)
-# include <stdio.h>
-# endif
-
-/* conditional features */
-
-# if defined(OPT_SPEED) && defined(OPT_ACCURACY)
-# error "cannot optimize for both speed and accuracy"
-# endif
-
-# if defined(OPT_SPEED) && !defined(OPT_SSO)
-# define OPT_SSO
-# endif
-
-# if defined(HAVE_UNISTD_H) && defined(HAVE_WAITPID) && \
- defined(HAVE_FCNTL) && defined(HAVE_PIPE) && defined(HAVE_FORK)
-# define USE_ASYNC
-# endif
-
-# if !defined(HAVE_ASSERT_H)
-# if defined(NDEBUG)
-# define assert(x) /* nothing */
-# else
-# define assert(x) do { if (!(x)) abort(); } while (0)
-# endif
-# endif
-
-# endif
diff --git a/libmad/src/huffman.c b/libmad/src/huffman.c
deleted file mode 100644
index a230a9c..0000000
--- a/libmad/src/huffman.c
+++ /dev/null
@@ -1,3109 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: huffman.c,v 1.10 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include "huffman.h"
-
-/*
- * These are the Huffman code words for Layer III.
- * The data for these tables are derived from Table B.7 of ISO/IEC 11172-3.
- *
- * These tables support decoding up to 4 Huffman code bits at a time.
- */
-
-# if defined(__GNUC__) || \
- (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901)
-# define PTR(offs, bits) { .ptr = { 0, bits, offs } }
-# define V(v, w, x, y, hlen) { .value = { 1, hlen, v, w, x, y } }
-# else
-# define PTR(offs, bits) { { 0, bits, offs } }
-# if defined(WORDS_BIGENDIAN)
-# define V(v, w, x, y, hlen) { { 1, hlen, (v << 11) | (w << 10) | \
- (x << 9) | (y << 8) } }
-# else
-# define V(v, w, x, y, hlen) { { 1, hlen, (v << 0) | (w << 1) | \
- (x << 2) | (y << 3) } }
-# endif
-# endif
-
-static
-union huffquad const hufftabA[] = {
- /* 0000 */ PTR(16, 2),
- /* 0001 */ PTR(20, 2),
- /* 0010 */ PTR(24, 1),
- /* 0011 */ PTR(26, 1),
- /* 0100 */ V(0, 0, 1, 0, 4),
- /* 0101 */ V(0, 0, 0, 1, 4),
- /* 0110 */ V(0, 1, 0, 0, 4),
- /* 0111 */ V(1, 0, 0, 0, 4),
- /* 1000 */ V(0, 0, 0, 0, 1),
- /* 1001 */ V(0, 0, 0, 0, 1),
- /* 1010 */ V(0, 0, 0, 0, 1),
- /* 1011 */ V(0, 0, 0, 0, 1),
- /* 1100 */ V(0, 0, 0, 0, 1),
- /* 1101 */ V(0, 0, 0, 0, 1),
- /* 1110 */ V(0, 0, 0, 0, 1),
- /* 1111 */ V(0, 0, 0, 0, 1),
-
- /* 0000 ... */
- /* 00 */ V(1, 0, 1, 1, 2), /* 16 */
- /* 01 */ V(1, 1, 1, 1, 2),
- /* 10 */ V(1, 1, 0, 1, 2),
- /* 11 */ V(1, 1, 1, 0, 2),
-
- /* 0001 ... */
- /* 00 */ V(0, 1, 1, 1, 2), /* 20 */
- /* 01 */ V(0, 1, 0, 1, 2),
- /* 10 */ V(1, 0, 0, 1, 1),
- /* 11 */ V(1, 0, 0, 1, 1),
-
- /* 0010 ... */
- /* 0 */ V(0, 1, 1, 0, 1), /* 24 */
- /* 1 */ V(0, 0, 1, 1, 1),
-
- /* 0011 ... */
- /* 0 */ V(1, 0, 1, 0, 1), /* 26 */
- /* 1 */ V(1, 1, 0, 0, 1)
-};
-
-static
-union huffquad const hufftabB[] = {
- /* 0000 */ V(1, 1, 1, 1, 4),
- /* 0001 */ V(1, 1, 1, 0, 4),
- /* 0010 */ V(1, 1, 0, 1, 4),
- /* 0011 */ V(1, 1, 0, 0, 4),
- /* 0100 */ V(1, 0, 1, 1, 4),
- /* 0101 */ V(1, 0, 1, 0, 4),
- /* 0110 */ V(1, 0, 0, 1, 4),
- /* 0111 */ V(1, 0, 0, 0, 4),
- /* 1000 */ V(0, 1, 1, 1, 4),
- /* 1001 */ V(0, 1, 1, 0, 4),
- /* 1010 */ V(0, 1, 0, 1, 4),
- /* 1011 */ V(0, 1, 0, 0, 4),
- /* 1100 */ V(0, 0, 1, 1, 4),
- /* 1101 */ V(0, 0, 1, 0, 4),
- /* 1110 */ V(0, 0, 0, 1, 4),
- /* 1111 */ V(0, 0, 0, 0, 4)
-};
-
-# undef V
-# undef PTR
-
-# if defined(__GNUC__) || \
- (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901)
-# define PTR(offs, bits) { .ptr = { 0, bits, offs } }
-# define V(x, y, hlen) { .value = { 1, hlen, x, y } }
-# else
-# define PTR(offs, bits) { { 0, bits, offs } }
-# if defined(WORDS_BIGENDIAN)
-# define V(x, y, hlen) { { 1, hlen, (x << 8) | (y << 4) } }
-# else
-# define V(x, y, hlen) { { 1, hlen, (x << 0) | (y << 4) } }
-# endif
-# endif
-
-static
-union huffpair const hufftab0[] = {
- /* */ V(0, 0, 0)
-};
-
-static
-union huffpair const hufftab1[] = {
- /* 000 */ V(1, 1, 3),
- /* 001 */ V(0, 1, 3),
- /* 010 */ V(1, 0, 2),
- /* 011 */ V(1, 0, 2),
- /* 100 */ V(0, 0, 1),
- /* 101 */ V(0, 0, 1),
- /* 110 */ V(0, 0, 1),
- /* 111 */ V(0, 0, 1)
-};
-
-static
-union huffpair const hufftab2[] = {
- /* 000 */ PTR(8, 3),
- /* 001 */ V(1, 1, 3),
- /* 010 */ V(0, 1, 3),
- /* 011 */ V(1, 0, 3),
- /* 100 */ V(0, 0, 1),
- /* 101 */ V(0, 0, 1),
- /* 110 */ V(0, 0, 1),
- /* 111 */ V(0, 0, 1),
-
- /* 000 ... */
- /* 000 */ V(2, 2, 3), /* 8 */
- /* 001 */ V(0, 2, 3),
- /* 010 */ V(1, 2, 2),
- /* 011 */ V(1, 2, 2),
- /* 100 */ V(2, 1, 2),
- /* 101 */ V(2, 1, 2),
- /* 110 */ V(2, 0, 2),
- /* 111 */ V(2, 0, 2)
-};
-
-static
-union huffpair const hufftab3[] = {
- /* 000 */ PTR(8, 3),
- /* 001 */ V(1, 0, 3),
- /* 010 */ V(1, 1, 2),
- /* 011 */ V(1, 1, 2),
- /* 100 */ V(0, 1, 2),
- /* 101 */ V(0, 1, 2),
- /* 110 */ V(0, 0, 2),
- /* 111 */ V(0, 0, 2),
-
- /* 000 ... */
- /* 000 */ V(2, 2, 3), /* 8 */
- /* 001 */ V(0, 2, 3),
- /* 010 */ V(1, 2, 2),
- /* 011 */ V(1, 2, 2),
- /* 100 */ V(2, 1, 2),
- /* 101 */ V(2, 1, 2),
- /* 110 */ V(2, 0, 2),
- /* 111 */ V(2, 0, 2)
-};
-
-static
-union huffpair const hufftab5[] = {
- /* 000 */ PTR(8, 4),
- /* 001 */ V(1, 1, 3),
- /* 010 */ V(0, 1, 3),
- /* 011 */ V(1, 0, 3),
- /* 100 */ V(0, 0, 1),
- /* 101 */ V(0, 0, 1),
- /* 110 */ V(0, 0, 1),
- /* 111 */ V(0, 0, 1),
-
- /* 000 ... */
- /* 0000 */ PTR(24, 1), /* 8 */
- /* 0001 */ V(3, 2, 4),
- /* 0010 */ V(3, 1, 3),
- /* 0011 */ V(3, 1, 3),
- /* 0100 */ V(1, 3, 4),
- /* 0101 */ V(0, 3, 4),
- /* 0110 */ V(3, 0, 4),
- /* 0111 */ V(2, 2, 4),
- /* 1000 */ V(1, 2, 3),
- /* 1001 */ V(1, 2, 3),
- /* 1010 */ V(2, 1, 3),
- /* 1011 */ V(2, 1, 3),
- /* 1100 */ V(0, 2, 3),
- /* 1101 */ V(0, 2, 3),
- /* 1110 */ V(2, 0, 3),
- /* 1111 */ V(2, 0, 3),
-
- /* 000 0000 ... */
- /* 0 */ V(3, 3, 1), /* 24 */
- /* 1 */ V(2, 3, 1)
-};
-
-static
-union huffpair const hufftab6[] = {
- /* 0000 */ PTR(16, 3),
- /* 0001 */ PTR(24, 1),
- /* 0010 */ PTR(26, 1),
- /* 0011 */ V(1, 2, 4),
- /* 0100 */ V(2, 1, 4),
- /* 0101 */ V(2, 0, 4),
- /* 0110 */ V(0, 1, 3),
- /* 0111 */ V(0, 1, 3),
- /* 1000 */ V(1, 1, 2),
- /* 1001 */ V(1, 1, 2),
- /* 1010 */ V(1, 1, 2),
- /* 1011 */ V(1, 1, 2),
- /* 1100 */ V(1, 0, 3),
- /* 1101 */ V(1, 0, 3),
- /* 1110 */ V(0, 0, 3),
- /* 1111 */ V(0, 0, 3),
-
- /* 0000 ... */
- /* 000 */ V(3, 3, 3), /* 16 */
- /* 001 */ V(0, 3, 3),
- /* 010 */ V(2, 3, 2),
- /* 011 */ V(2, 3, 2),
- /* 100 */ V(3, 2, 2),
- /* 101 */ V(3, 2, 2),
- /* 110 */ V(3, 0, 2),
- /* 111 */ V(3, 0, 2),
-
- /* 0001 ... */
- /* 0 */ V(1, 3, 1), /* 24 */
- /* 1 */ V(3, 1, 1),
-
- /* 0010 ... */
- /* 0 */ V(2, 2, 1), /* 26 */
- /* 1 */ V(0, 2, 1)
-};
-
-static
-union huffpair const hufftab7[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 2),
- /* 0011 */ V(1, 1, 4),
- /* 0100 */ V(0, 1, 3),
- /* 0101 */ V(0, 1, 3),
- /* 0110 */ V(1, 0, 3),
- /* 0111 */ V(1, 0, 3),
- /* 1000 */ V(0, 0, 1),
- /* 1001 */ V(0, 0, 1),
- /* 1010 */ V(0, 0, 1),
- /* 1011 */ V(0, 0, 1),
- /* 1100 */ V(0, 0, 1),
- /* 1101 */ V(0, 0, 1),
- /* 1110 */ V(0, 0, 1),
- /* 1111 */ V(0, 0, 1),
-
- /* 0000 ... */
- /* 0000 */ PTR(52, 2), /* 16 */
- /* 0001 */ PTR(56, 1),
- /* 0010 */ PTR(58, 1),
- /* 0011 */ V(1, 5, 4),
- /* 0100 */ V(5, 1, 4),
- /* 0101 */ PTR(60, 1),
- /* 0110 */ V(5, 0, 4),
- /* 0111 */ PTR(62, 1),
- /* 1000 */ V(2, 4, 4),
- /* 1001 */ V(4, 2, 4),
- /* 1010 */ V(1, 4, 3),
- /* 1011 */ V(1, 4, 3),
- /* 1100 */ V(4, 1, 3),
- /* 1101 */ V(4, 1, 3),
- /* 1110 */ V(4, 0, 3),
- /* 1111 */ V(4, 0, 3),
-
- /* 0001 ... */
- /* 0000 */ V(0, 4, 4), /* 32 */
- /* 0001 */ V(2, 3, 4),
- /* 0010 */ V(3, 2, 4),
- /* 0011 */ V(0, 3, 4),
- /* 0100 */ V(1, 3, 3),
- /* 0101 */ V(1, 3, 3),
- /* 0110 */ V(3, 1, 3),
- /* 0111 */ V(3, 1, 3),
- /* 1000 */ V(3, 0, 3),
- /* 1001 */ V(3, 0, 3),
- /* 1010 */ V(2, 2, 3),
- /* 1011 */ V(2, 2, 3),
- /* 1100 */ V(1, 2, 2),
- /* 1101 */ V(1, 2, 2),
- /* 1110 */ V(1, 2, 2),
- /* 1111 */ V(1, 2, 2),
-
- /* 0010 ... */
- /* 00 */ V(2, 1, 1), /* 48 */
- /* 01 */ V(2, 1, 1),
- /* 10 */ V(0, 2, 2),
- /* 11 */ V(2, 0, 2),
-
- /* 0000 0000 ... */
- /* 00 */ V(5, 5, 2), /* 52 */
- /* 01 */ V(4, 5, 2),
- /* 10 */ V(5, 4, 2),
- /* 11 */ V(5, 3, 2),
-
- /* 0000 0001 ... */
- /* 0 */ V(3, 5, 1), /* 56 */
- /* 1 */ V(4, 4, 1),
-
- /* 0000 0010 ... */
- /* 0 */ V(2, 5, 1), /* 58 */
- /* 1 */ V(5, 2, 1),
-
- /* 0000 0101 ... */
- /* 0 */ V(0, 5, 1), /* 60 */
- /* 1 */ V(3, 4, 1),
-
- /* 0000 0111 ... */
- /* 0 */ V(4, 3, 1), /* 62 */
- /* 1 */ V(3, 3, 1)
-};
-
-# if 0
-/* this version saves 8 entries (16 bytes) at the expense of
- an extra lookup in 4 out of 36 cases */
-static
-union huffpair const hufftab8[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 2),
- /* 0010 */ V(1, 2, 4),
- /* 0011 */ V(2, 1, 4),
- /* 0100 */ V(1, 1, 2),
- /* 0101 */ V(1, 1, 2),
- /* 0110 */ V(1, 1, 2),
- /* 0111 */ V(1, 1, 2),
- /* 1000 */ V(0, 1, 3),
- /* 1001 */ V(0, 1, 3),
- /* 1010 */ V(1, 0, 3),
- /* 1011 */ V(1, 0, 3),
- /* 1100 */ V(0, 0, 2),
- /* 1101 */ V(0, 0, 2),
- /* 1110 */ V(0, 0, 2),
- /* 1111 */ V(0, 0, 2),
-
- /* 0000 ... */
- /* 0000 */ PTR(36, 3), /* 16 */
- /* 0001 */ PTR(44, 2),
- /* 0010 */ PTR(48, 1),
- /* 0011 */ V(1, 5, 4),
- /* 0100 */ V(5, 1, 4),
- /* 0101 */ PTR(50, 1),
- /* 0110 */ PTR(52, 1),
- /* 0111 */ V(2, 4, 4),
- /* 1000 */ V(4, 2, 4),
- /* 1001 */ V(1, 4, 4),
- /* 1010 */ V(4, 1, 3),
- /* 1011 */ V(4, 1, 3),
- /* 1100 */ V(0, 4, 4),
- /* 1101 */ V(4, 0, 4),
- /* 1110 */ V(2, 3, 4),
- /* 1111 */ V(3, 2, 4),
-
- /* 0001 ... */
- /* 00 */ PTR(54, 2), /* 32 */
- /* 01 */ V(2, 2, 2),
- /* 10 */ V(0, 2, 2),
- /* 11 */ V(2, 0, 2),
-
- /* 0000 0000 ... */
- /* 000 */ V(5, 5, 3), /* 36 */
- /* 001 */ V(5, 4, 3),
- /* 010 */ V(4, 5, 2),
- /* 011 */ V(4, 5, 2),
- /* 100 */ V(5, 3, 1),
- /* 101 */ V(5, 3, 1),
- /* 110 */ V(5, 3, 1),
- /* 111 */ V(5, 3, 1),
-
- /* 0000 0001 ... */
- /* 00 */ V(3, 5, 2), /* 44 */
- /* 01 */ V(4, 4, 2),
- /* 10 */ V(2, 5, 1),
- /* 11 */ V(2, 5, 1),
-
- /* 0000 0010 ... */
- /* 0 */ V(5, 2, 1), /* 48 */
- /* 1 */ V(0, 5, 1),
-
- /* 0000 0101 ... */
- /* 0 */ V(3, 4, 1), /* 50 */
- /* 1 */ V(4, 3, 1),
-
- /* 0000 0110 ... */
- /* 0 */ V(5, 0, 1), /* 52 */
- /* 1 */ V(3, 3, 1),
-
- /* 0001 00 ... */
- /* 00 */ V(1, 3, 2), /* 54 */
- /* 01 */ V(3, 1, 2),
- /* 10 */ V(0, 3, 2),
- /* 11 */ V(3, 0, 2),
-};
-# else
-static
-union huffpair const hufftab8[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ V(1, 2, 4),
- /* 0011 */ V(2, 1, 4),
- /* 0100 */ V(1, 1, 2),
- /* 0101 */ V(1, 1, 2),
- /* 0110 */ V(1, 1, 2),
- /* 0111 */ V(1, 1, 2),
- /* 1000 */ V(0, 1, 3),
- /* 1001 */ V(0, 1, 3),
- /* 1010 */ V(1, 0, 3),
- /* 1011 */ V(1, 0, 3),
- /* 1100 */ V(0, 0, 2),
- /* 1101 */ V(0, 0, 2),
- /* 1110 */ V(0, 0, 2),
- /* 1111 */ V(0, 0, 2),
-
- /* 0000 ... */
- /* 0000 */ PTR(48, 3), /* 16 */
- /* 0001 */ PTR(56, 2),
- /* 0010 */ PTR(60, 1),
- /* 0011 */ V(1, 5, 4),
- /* 0100 */ V(5, 1, 4),
- /* 0101 */ PTR(62, 1),
- /* 0110 */ PTR(64, 1),
- /* 0111 */ V(2, 4, 4),
- /* 1000 */ V(4, 2, 4),
- /* 1001 */ V(1, 4, 4),
- /* 1010 */ V(4, 1, 3),
- /* 1011 */ V(4, 1, 3),
- /* 1100 */ V(0, 4, 4),
- /* 1101 */ V(4, 0, 4),
- /* 1110 */ V(2, 3, 4),
- /* 1111 */ V(3, 2, 4),
-
- /* 0001 ... */
- /* 0000 */ V(1, 3, 4), /* 32 */
- /* 0001 */ V(3, 1, 4),
- /* 0010 */ V(0, 3, 4),
- /* 0011 */ V(3, 0, 4),
- /* 0100 */ V(2, 2, 2),
- /* 0101 */ V(2, 2, 2),
- /* 0110 */ V(2, 2, 2),
- /* 0111 */ V(2, 2, 2),
- /* 1000 */ V(0, 2, 2),
- /* 1001 */ V(0, 2, 2),
- /* 1010 */ V(0, 2, 2),
- /* 1011 */ V(0, 2, 2),
- /* 1100 */ V(2, 0, 2),
- /* 1101 */ V(2, 0, 2),
- /* 1110 */ V(2, 0, 2),
- /* 1111 */ V(2, 0, 2),
-
- /* 0000 0000 ... */
- /* 000 */ V(5, 5, 3), /* 48 */
- /* 001 */ V(5, 4, 3),
- /* 010 */ V(4, 5, 2),
- /* 011 */ V(4, 5, 2),
- /* 100 */ V(5, 3, 1),
- /* 101 */ V(5, 3, 1),
- /* 110 */ V(5, 3, 1),
- /* 111 */ V(5, 3, 1),
-
- /* 0000 0001 ... */
- /* 00 */ V(3, 5, 2), /* 56 */
- /* 01 */ V(4, 4, 2),
- /* 10 */ V(2, 5, 1),
- /* 11 */ V(2, 5, 1),
-
- /* 0000 0010 ... */
- /* 0 */ V(5, 2, 1), /* 60 */
- /* 1 */ V(0, 5, 1),
-
- /* 0000 0101 ... */
- /* 0 */ V(3, 4, 1), /* 62 */
- /* 1 */ V(4, 3, 1),
-
- /* 0000 0110 ... */
- /* 0 */ V(5, 0, 1), /* 64 */
- /* 1 */ V(3, 3, 1)
-};
-# endif
-
-static
-union huffpair const hufftab9[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 3),
- /* 0010 */ PTR(40, 2),
- /* 0011 */ PTR(44, 2),
- /* 0100 */ PTR(48, 1),
- /* 0101 */ V(1, 2, 4),
- /* 0110 */ V(2, 1, 4),
- /* 0111 */ V(2, 0, 4),
- /* 1000 */ V(1, 1, 3),
- /* 1001 */ V(1, 1, 3),
- /* 1010 */ V(0, 1, 3),
- /* 1011 */ V(0, 1, 3),
- /* 1100 */ V(1, 0, 3),
- /* 1101 */ V(1, 0, 3),
- /* 1110 */ V(0, 0, 3),
- /* 1111 */ V(0, 0, 3),
-
- /* 0000 ... */
- /* 0000 */ PTR(50, 1), /* 16 */
- /* 0001 */ V(3, 5, 4),
- /* 0010 */ V(5, 3, 4),
- /* 0011 */ PTR(52, 1),
- /* 0100 */ V(4, 4, 4),
- /* 0101 */ V(2, 5, 4),
- /* 0110 */ V(5, 2, 4),
- /* 0111 */ V(1, 5, 4),
- /* 1000 */ V(5, 1, 3),
- /* 1001 */ V(5, 1, 3),
- /* 1010 */ V(3, 4, 3),
- /* 1011 */ V(3, 4, 3),
- /* 1100 */ V(4, 3, 3),
- /* 1101 */ V(4, 3, 3),
- /* 1110 */ V(5, 0, 4),
- /* 1111 */ V(0, 4, 4),
-
- /* 0001 ... */
- /* 000 */ V(2, 4, 3), /* 32 */
- /* 001 */ V(4, 2, 3),
- /* 010 */ V(3, 3, 3),
- /* 011 */ V(4, 0, 3),
- /* 100 */ V(1, 4, 2),
- /* 101 */ V(1, 4, 2),
- /* 110 */ V(4, 1, 2),
- /* 111 */ V(4, 1, 2),
-
- /* 0010 ... */
- /* 00 */ V(2, 3, 2), /* 40 */
- /* 01 */ V(3, 2, 2),
- /* 10 */ V(1, 3, 1),
- /* 11 */ V(1, 3, 1),
-
- /* 0011 ... */
- /* 00 */ V(3, 1, 1), /* 44 */
- /* 01 */ V(3, 1, 1),
- /* 10 */ V(0, 3, 2),
- /* 11 */ V(3, 0, 2),
-
- /* 0100 ... */
- /* 0 */ V(2, 2, 1), /* 48 */
- /* 1 */ V(0, 2, 1),
-
- /* 0000 0000 ... */
- /* 0 */ V(5, 5, 1), /* 50 */
- /* 1 */ V(4, 5, 1),
-
- /* 0000 0011 ... */
- /* 0 */ V(5, 4, 1), /* 52 */
- /* 1 */ V(0, 5, 1)
-};
-
-static
-union huffpair const hufftab10[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 2),
- /* 0011 */ V(1, 1, 4),
- /* 0100 */ V(0, 1, 3),
- /* 0101 */ V(0, 1, 3),
- /* 0110 */ V(1, 0, 3),
- /* 0111 */ V(1, 0, 3),
- /* 1000 */ V(0, 0, 1),
- /* 1001 */ V(0, 0, 1),
- /* 1010 */ V(0, 0, 1),
- /* 1011 */ V(0, 0, 1),
- /* 1100 */ V(0, 0, 1),
- /* 1101 */ V(0, 0, 1),
- /* 1110 */ V(0, 0, 1),
- /* 1111 */ V(0, 0, 1),
-
- /* 0000 ... */
- /* 0000 */ PTR(52, 3), /* 16 */
- /* 0001 */ PTR(60, 2),
- /* 0010 */ PTR(64, 3),
- /* 0011 */ PTR(72, 1),
- /* 0100 */ PTR(74, 2),
- /* 0101 */ PTR(78, 2),
- /* 0110 */ PTR(82, 2),
- /* 0111 */ V(1, 7, 4),
- /* 1000 */ V(7, 1, 4),
- /* 1001 */ PTR(86, 1),
- /* 1010 */ PTR(88, 2),
- /* 1011 */ PTR(92, 2),
- /* 1100 */ V(1, 6, 4),
- /* 1101 */ V(6, 1, 4),
- /* 1110 */ V(6, 0, 4),
- /* 1111 */ PTR(96, 1),
-
- /* 0001 ... */
- /* 0000 */ PTR(98, 1), /* 32 */
- /* 0001 */ PTR(100, 1),
- /* 0010 */ V(1, 4, 4),
- /* 0011 */ V(4, 1, 4),
- /* 0100 */ V(4, 0, 4),
- /* 0101 */ V(2, 3, 4),
- /* 0110 */ V(3, 2, 4),
- /* 0111 */ V(0, 3, 4),
- /* 1000 */ V(1, 3, 3),
- /* 1001 */ V(1, 3, 3),
- /* 1010 */ V(3, 1, 3),
- /* 1011 */ V(3, 1, 3),
- /* 1100 */ V(3, 0, 3),
- /* 1101 */ V(3, 0, 3),
- /* 1110 */ V(2, 2, 3),
- /* 1111 */ V(2, 2, 3),
-
- /* 0010 ... */
- /* 00 */ V(1, 2, 2), /* 48 */
- /* 01 */ V(2, 1, 2),
- /* 10 */ V(0, 2, 2),
- /* 11 */ V(2, 0, 2),
-
- /* 0000 0000 ... */
- /* 000 */ V(7, 7, 3), /* 52 */
- /* 001 */ V(6, 7, 3),
- /* 010 */ V(7, 6, 3),
- /* 011 */ V(5, 7, 3),
- /* 100 */ V(7, 5, 3),
- /* 101 */ V(6, 6, 3),
- /* 110 */ V(4, 7, 2),
- /* 111 */ V(4, 7, 2),
-
- /* 0000 0001 ... */
- /* 00 */ V(7, 4, 2), /* 60 */
- /* 01 */ V(5, 6, 2),
- /* 10 */ V(6, 5, 2),
- /* 11 */ V(3, 7, 2),
-
- /* 0000 0010 ... */
- /* 000 */ V(7, 3, 2), /* 64 */
- /* 001 */ V(7, 3, 2),
- /* 010 */ V(4, 6, 2),
- /* 011 */ V(4, 6, 2),
- /* 100 */ V(5, 5, 3),
- /* 101 */ V(5, 4, 3),
- /* 110 */ V(6, 3, 2),
- /* 111 */ V(6, 3, 2),
-
- /* 0000 0011 ... */
- /* 0 */ V(2, 7, 1), /* 72 */
- /* 1 */ V(7, 2, 1),
-
- /* 0000 0100 ... */
- /* 00 */ V(6, 4, 2), /* 74 */
- /* 01 */ V(0, 7, 2),
- /* 10 */ V(7, 0, 1),
- /* 11 */ V(7, 0, 1),
-
- /* 0000 0101 ... */
- /* 00 */ V(6, 2, 1), /* 78 */
- /* 01 */ V(6, 2, 1),
- /* 10 */ V(4, 5, 2),
- /* 11 */ V(3, 5, 2),
-
- /* 0000 0110 ... */
- /* 00 */ V(0, 6, 1), /* 82 */
- /* 01 */ V(0, 6, 1),
- /* 10 */ V(5, 3, 2),
- /* 11 */ V(4, 4, 2),
-
- /* 0000 1001 ... */
- /* 0 */ V(3, 6, 1), /* 86 */
- /* 1 */ V(2, 6, 1),
-
- /* 0000 1010 ... */
- /* 00 */ V(2, 5, 2), /* 88 */
- /* 01 */ V(5, 2, 2),
- /* 10 */ V(1, 5, 1),
- /* 11 */ V(1, 5, 1),
-
- /* 0000 1011 ... */
- /* 00 */ V(5, 1, 1), /* 92 */
- /* 01 */ V(5, 1, 1),
- /* 10 */ V(3, 4, 2),
- /* 11 */ V(4, 3, 2),
-
- /* 0000 1111 ... */
- /* 0 */ V(0, 5, 1), /* 96 */
- /* 1 */ V(5, 0, 1),
-
- /* 0001 0000 ... */
- /* 0 */ V(2, 4, 1), /* 98 */
- /* 1 */ V(4, 2, 1),
-
- /* 0001 0001 ... */
- /* 0 */ V(3, 3, 1), /* 100 */
- /* 1 */ V(0, 4, 1)
-};
-
-static
-union huffpair const hufftab11[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 4),
- /* 0011 */ PTR(64, 3),
- /* 0100 */ V(1, 2, 4),
- /* 0101 */ PTR(72, 1),
- /* 0110 */ V(1, 1, 3),
- /* 0111 */ V(1, 1, 3),
- /* 1000 */ V(0, 1, 3),
- /* 1001 */ V(0, 1, 3),
- /* 1010 */ V(1, 0, 3),
- /* 1011 */ V(1, 0, 3),
- /* 1100 */ V(0, 0, 2),
- /* 1101 */ V(0, 0, 2),
- /* 1110 */ V(0, 0, 2),
- /* 1111 */ V(0, 0, 2),
-
- /* 0000 ... */
- /* 0000 */ PTR(74, 2), /* 16 */
- /* 0001 */ PTR(78, 3),
- /* 0010 */ PTR(86, 2),
- /* 0011 */ PTR(90, 1),
- /* 0100 */ PTR(92, 2),
- /* 0101 */ V(2, 7, 4),
- /* 0110 */ V(7, 2, 4),
- /* 0111 */ PTR(96, 1),
- /* 1000 */ V(7, 1, 3),
- /* 1001 */ V(7, 1, 3),
- /* 1010 */ V(1, 7, 4),
- /* 1011 */ V(7, 0, 4),
- /* 1100 */ V(3, 6, 4),
- /* 1101 */ V(6, 3, 4),
- /* 1110 */ V(6, 0, 4),
- /* 1111 */ PTR(98, 1),
-
- /* 0001 ... */
- /* 0000 */ PTR(100, 1), /* 32 */
- /* 0001 */ V(1, 5, 4),
- /* 0010 */ V(6, 2, 3),
- /* 0011 */ V(6, 2, 3),
- /* 0100 */ V(2, 6, 4),
- /* 0101 */ V(0, 6, 4),
- /* 0110 */ V(1, 6, 3),
- /* 0111 */ V(1, 6, 3),
- /* 1000 */ V(6, 1, 3),
- /* 1001 */ V(6, 1, 3),
- /* 1010 */ V(5, 1, 4),
- /* 1011 */ V(3, 4, 4),
- /* 1100 */ V(5, 0, 4),
- /* 1101 */ PTR(102, 1),
- /* 1110 */ V(2, 4, 4),
- /* 1111 */ V(4, 2, 4),
-
- /* 0010 ... */
- /* 0000 */ V(1, 4, 4), /* 48 */
- /* 0001 */ V(4, 1, 4),
- /* 0010 */ V(0, 4, 4),
- /* 0011 */ V(4, 0, 4),
- /* 0100 */ V(2, 3, 3),
- /* 0101 */ V(2, 3, 3),
- /* 0110 */ V(3, 2, 3),
- /* 0111 */ V(3, 2, 3),
- /* 1000 */ V(1, 3, 2),
- /* 1001 */ V(1, 3, 2),
- /* 1010 */ V(1, 3, 2),
- /* 1011 */ V(1, 3, 2),
- /* 1100 */ V(3, 1, 2),
- /* 1101 */ V(3, 1, 2),
- /* 1110 */ V(3, 1, 2),
- /* 1111 */ V(3, 1, 2),
-
- /* 0011 ... */
- /* 000 */ V(0, 3, 3), /* 64 */
- /* 001 */ V(3, 0, 3),
- /* 010 */ V(2, 2, 2),
- /* 011 */ V(2, 2, 2),
- /* 100 */ V(2, 1, 1),
- /* 101 */ V(2, 1, 1),
- /* 110 */ V(2, 1, 1),
- /* 111 */ V(2, 1, 1),
-
- /* 0101 ... */
- /* 0 */ V(0, 2, 1), /* 72 */
- /* 1 */ V(2, 0, 1),
-
- /* 0000 0000 ... */
- /* 00 */ V(7, 7, 2), /* 74 */
- /* 01 */ V(6, 7, 2),
- /* 10 */ V(7, 6, 2),
- /* 11 */ V(7, 5, 2),
-
- /* 0000 0001 ... */
- /* 000 */ V(6, 6, 2), /* 78 */
- /* 001 */ V(6, 6, 2),
- /* 010 */ V(4, 7, 2),
- /* 011 */ V(4, 7, 2),
- /* 100 */ V(7, 4, 2),
- /* 101 */ V(7, 4, 2),
- /* 110 */ V(5, 7, 3),
- /* 111 */ V(5, 5, 3),
-
- /* 0000 0010 ... */
- /* 00 */ V(5, 6, 2), /* 86 */
- /* 01 */ V(6, 5, 2),
- /* 10 */ V(3, 7, 1),
- /* 11 */ V(3, 7, 1),
-
- /* 0000 0011 ... */
- /* 0 */ V(7, 3, 1), /* 90 */
- /* 1 */ V(4, 6, 1),
-
- /* 0000 0100 ... */
- /* 00 */ V(4, 5, 2), /* 92 */
- /* 01 */ V(5, 4, 2),
- /* 10 */ V(3, 5, 2),
- /* 11 */ V(5, 3, 2),
-
- /* 0000 0111 ... */
- /* 0 */ V(6, 4, 1), /* 96 */
- /* 1 */ V(0, 7, 1),
-
- /* 0000 1111 ... */
- /* 0 */ V(4, 4, 1), /* 98 */
- /* 1 */ V(2, 5, 1),
-
- /* 0001 0000 ... */
- /* 0 */ V(5, 2, 1), /* 100 */
- /* 1 */ V(0, 5, 1),
-
- /* 0001 1101 ... */
- /* 0 */ V(4, 3, 1), /* 102 */
- /* 1 */ V(3, 3, 1)
-};
-
-static
-union huffpair const hufftab12[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 4),
- /* 0011 */ PTR(64, 2),
- /* 0100 */ PTR(68, 3),
- /* 0101 */ PTR(76, 1),
- /* 0110 */ V(1, 2, 4),
- /* 0111 */ V(2, 1, 4),
- /* 1000 */ PTR(78, 1),
- /* 1001 */ V(0, 0, 4),
- /* 1010 */ V(1, 1, 3),
- /* 1011 */ V(1, 1, 3),
- /* 1100 */ V(0, 1, 3),
- /* 1101 */ V(0, 1, 3),
- /* 1110 */ V(1, 0, 3),
- /* 1111 */ V(1, 0, 3),
-
- /* 0000 ... */
- /* 0000 */ PTR(80, 2), /* 16 */
- /* 0001 */ PTR(84, 1),
- /* 0010 */ PTR(86, 1),
- /* 0011 */ PTR(88, 1),
- /* 0100 */ V(5, 6, 4),
- /* 0101 */ V(3, 7, 4),
- /* 0110 */ PTR(90, 1),
- /* 0111 */ V(2, 7, 4),
- /* 1000 */ V(7, 2, 4),
- /* 1001 */ V(4, 6, 4),
- /* 1010 */ V(6, 4, 4),
- /* 1011 */ V(1, 7, 4),
- /* 1100 */ V(7, 1, 4),
- /* 1101 */ PTR(92, 1),
- /* 1110 */ V(3, 6, 4),
- /* 1111 */ V(6, 3, 4),
-
- /* 0001 ... */
- /* 0000 */ V(4, 5, 4), /* 32 */
- /* 0001 */ V(5, 4, 4),
- /* 0010 */ V(4, 4, 4),
- /* 0011 */ PTR(94, 1),
- /* 0100 */ V(2, 6, 3),
- /* 0101 */ V(2, 6, 3),
- /* 0110 */ V(6, 2, 3),
- /* 0111 */ V(6, 2, 3),
- /* 1000 */ V(6, 1, 3),
- /* 1001 */ V(6, 1, 3),
- /* 1010 */ V(1, 6, 4),
- /* 1011 */ V(6, 0, 4),
- /* 1100 */ V(3, 5, 4),
- /* 1101 */ V(5, 3, 4),
- /* 1110 */ V(2, 5, 4),
- /* 1111 */ V(5, 2, 4),
-
- /* 0010 ... */
- /* 0000 */ V(1, 5, 3), /* 48 */
- /* 0001 */ V(1, 5, 3),
- /* 0010 */ V(5, 1, 3),
- /* 0011 */ V(5, 1, 3),
- /* 0100 */ V(3, 4, 3),
- /* 0101 */ V(3, 4, 3),
- /* 0110 */ V(4, 3, 3),
- /* 0111 */ V(4, 3, 3),
- /* 1000 */ V(5, 0, 4),
- /* 1001 */ V(0, 4, 4),
- /* 1010 */ V(2, 4, 3),
- /* 1011 */ V(2, 4, 3),
- /* 1100 */ V(4, 2, 3),
- /* 1101 */ V(4, 2, 3),
- /* 1110 */ V(1, 4, 3),
- /* 1111 */ V(1, 4, 3),
-
- /* 0011 ... */
- /* 00 */ V(3, 3, 2), /* 64 */
- /* 01 */ V(4, 1, 2),
- /* 10 */ V(2, 3, 2),
- /* 11 */ V(3, 2, 2),
-
- /* 0100 ... */
- /* 000 */ V(4, 0, 3), /* 68 */
- /* 001 */ V(0, 3, 3),
- /* 010 */ V(3, 0, 2),
- /* 011 */ V(3, 0, 2),
- /* 100 */ V(1, 3, 1),
- /* 101 */ V(1, 3, 1),
- /* 110 */ V(1, 3, 1),
- /* 111 */ V(1, 3, 1),
-
- /* 0101 ... */
- /* 0 */ V(3, 1, 1), /* 76 */
- /* 1 */ V(2, 2, 1),
-
- /* 1000 ... */
- /* 0 */ V(0, 2, 1), /* 78 */
- /* 1 */ V(2, 0, 1),
-
- /* 0000 0000 ... */
- /* 00 */ V(7, 7, 2), /* 80 */
- /* 01 */ V(6, 7, 2),
- /* 10 */ V(7, 6, 1),
- /* 11 */ V(7, 6, 1),
-
- /* 0000 0001 ... */
- /* 0 */ V(5, 7, 1), /* 84 */
- /* 1 */ V(7, 5, 1),
-
- /* 0000 0010 ... */
- /* 0 */ V(6, 6, 1), /* 86 */
- /* 1 */ V(4, 7, 1),
-
- /* 0000 0011 ... */
- /* 0 */ V(7, 4, 1), /* 88 */
- /* 1 */ V(6, 5, 1),
-
- /* 0000 0110 ... */
- /* 0 */ V(7, 3, 1), /* 90 */
- /* 1 */ V(5, 5, 1),
-
- /* 0000 1101 ... */
- /* 0 */ V(0, 7, 1), /* 92 */
- /* 1 */ V(7, 0, 1),
-
- /* 0001 0011 ... */
- /* 0 */ V(0, 6, 1), /* 94 */
- /* 1 */ V(0, 5, 1)
-};
-
-static
-union huffpair const hufftab13[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 4),
- /* 0011 */ PTR(64, 2),
- /* 0100 */ V(1, 1, 4),
- /* 0101 */ V(0, 1, 4),
- /* 0110 */ V(1, 0, 3),
- /* 0111 */ V(1, 0, 3),
- /* 1000 */ V(0, 0, 1),
- /* 1001 */ V(0, 0, 1),
- /* 1010 */ V(0, 0, 1),
- /* 1011 */ V(0, 0, 1),
- /* 1100 */ V(0, 0, 1),
- /* 1101 */ V(0, 0, 1),
- /* 1110 */ V(0, 0, 1),
- /* 1111 */ V(0, 0, 1),
-
- /* 0000 ... */
- /* 0000 */ PTR(68, 4), /* 16 */
- /* 0001 */ PTR(84, 4),
- /* 0010 */ PTR(100, 4),
- /* 0011 */ PTR(116, 4),
- /* 0100 */ PTR(132, 4),
- /* 0101 */ PTR(148, 4),
- /* 0110 */ PTR(164, 3),
- /* 0111 */ PTR(172, 3),
- /* 1000 */ PTR(180, 3),
- /* 1001 */ PTR(188, 3),
- /* 1010 */ PTR(196, 3),
- /* 1011 */ PTR(204, 3),
- /* 1100 */ PTR(212, 1),
- /* 1101 */ PTR(214, 2),
- /* 1110 */ PTR(218, 3),
- /* 1111 */ PTR(226, 1),
-
- /* 0001 ... */
- /* 0000 */ PTR(228, 2), /* 32 */
- /* 0001 */ PTR(232, 2),
- /* 0010 */ PTR(236, 2),
- /* 0011 */ PTR(240, 2),
- /* 0100 */ V(8, 1, 4),
- /* 0101 */ PTR(244, 1),
- /* 0110 */ PTR(246, 1),
- /* 0111 */ PTR(248, 1),
- /* 1000 */ PTR(250, 2),
- /* 1001 */ PTR(254, 1),
- /* 1010 */ V(1, 5, 4),
- /* 1011 */ V(5, 1, 4),
- /* 1100 */ PTR(256, 1),
- /* 1101 */ PTR(258, 1),
- /* 1110 */ PTR(260, 1),
- /* 1111 */ V(1, 4, 4),
-
- /* 0010 ... */
- /* 0000 */ V(4, 1, 3), /* 48 */
- /* 0001 */ V(4, 1, 3),
- /* 0010 */ V(0, 4, 4),
- /* 0011 */ V(4, 0, 4),
- /* 0100 */ V(2, 3, 4),
- /* 0101 */ V(3, 2, 4),
- /* 0110 */ V(1, 3, 3),
- /* 0111 */ V(1, 3, 3),
- /* 1000 */ V(3, 1, 3),
- /* 1001 */ V(3, 1, 3),
- /* 1010 */ V(0, 3, 3),
- /* 1011 */ V(0, 3, 3),
- /* 1100 */ V(3, 0, 3),
- /* 1101 */ V(3, 0, 3),
- /* 1110 */ V(2, 2, 3),
- /* 1111 */ V(2, 2, 3),
-
- /* 0011 ... */
- /* 00 */ V(1, 2, 2), /* 64 */
- /* 01 */ V(2, 1, 2),
- /* 10 */ V(0, 2, 2),
- /* 11 */ V(2, 0, 2),
-
- /* 0000 0000 ... */
- /* 0000 */ PTR(262, 4), /* 68 */
- /* 0001 */ PTR(278, 4),
- /* 0010 */ PTR(294, 4),
- /* 0011 */ PTR(310, 3),
- /* 0100 */ PTR(318, 2),
- /* 0101 */ PTR(322, 2),
- /* 0110 */ PTR(326, 3),
- /* 0111 */ PTR(334, 2),
- /* 1000 */ PTR(338, 1),
- /* 1001 */ PTR(340, 2),
- /* 1010 */ PTR(344, 2),
- /* 1011 */ PTR(348, 2),
- /* 1100 */ PTR(352, 2),
- /* 1101 */ PTR(356, 2),
- /* 1110 */ V(1, 15, 4),
- /* 1111 */ V(15, 1, 4),
-
- /* 0000 0001 ... */
- /* 0000 */ V(15, 0, 4), /* 84 */
- /* 0001 */ PTR(360, 1),
- /* 0010 */ PTR(362, 1),
- /* 0011 */ PTR(364, 1),
- /* 0100 */ V(14, 2, 4),
- /* 0101 */ PTR(366, 1),
- /* 0110 */ V(1, 14, 4),
- /* 0111 */ V(14, 1, 4),
- /* 1000 */ PTR(368, 1),
- /* 1001 */ PTR(370, 1),
- /* 1010 */ PTR(372, 1),
- /* 1011 */ PTR(374, 1),
- /* 1100 */ PTR(376, 1),
- /* 1101 */ PTR(378, 1),
- /* 1110 */ V(12, 6, 4),
- /* 1111 */ V(3, 13, 4),
-
- /* 0000 0010 ... */
- /* 0000 */ PTR(380, 1), /* 100 */
- /* 0001 */ V(2, 13, 4),
- /* 0010 */ V(13, 2, 4),
- /* 0011 */ V(1, 13, 4),
- /* 0100 */ V(11, 7, 4),
- /* 0101 */ PTR(382, 1),
- /* 0110 */ PTR(384, 1),
- /* 0111 */ V(12, 3, 4),
- /* 1000 */ PTR(386, 1),
- /* 1001 */ V(4, 11, 4),
- /* 1010 */ V(13, 1, 3),
- /* 1011 */ V(13, 1, 3),
- /* 1100 */ V(0, 13, 4),
- /* 1101 */ V(13, 0, 4),
- /* 1110 */ V(8, 10, 4),
- /* 1111 */ V(10, 8, 4),
-
- /* 0000 0011 ... */
- /* 0000 */ V(4, 12, 4), /* 116 */
- /* 0001 */ V(12, 4, 4),
- /* 0010 */ V(6, 11, 4),
- /* 0011 */ V(11, 6, 4),
- /* 0100 */ V(3, 12, 3),
- /* 0101 */ V(3, 12, 3),
- /* 0110 */ V(2, 12, 3),
- /* 0111 */ V(2, 12, 3),
- /* 1000 */ V(12, 2, 3),
- /* 1001 */ V(12, 2, 3),
- /* 1010 */ V(5, 11, 3),
- /* 1011 */ V(5, 11, 3),
- /* 1100 */ V(11, 5, 4),
- /* 1101 */ V(8, 9, 4),
- /* 1110 */ V(1, 12, 3),
- /* 1111 */ V(1, 12, 3),
-
- /* 0000 0100 ... */
- /* 0000 */ V(12, 1, 3), /* 132 */
- /* 0001 */ V(12, 1, 3),
- /* 0010 */ V(9, 8, 4),
- /* 0011 */ V(0, 12, 4),
- /* 0100 */ V(12, 0, 3),
- /* 0101 */ V(12, 0, 3),
- /* 0110 */ V(11, 4, 4),
- /* 0111 */ V(6, 10, 4),
- /* 1000 */ V(10, 6, 4),
- /* 1001 */ V(7, 9, 4),
- /* 1010 */ V(3, 11, 3),
- /* 1011 */ V(3, 11, 3),
- /* 1100 */ V(11, 3, 3),
- /* 1101 */ V(11, 3, 3),
- /* 1110 */ V(8, 8, 4),
- /* 1111 */ V(5, 10, 4),
-
- /* 0000 0101 ... */
- /* 0000 */ V(2, 11, 3), /* 148 */
- /* 0001 */ V(2, 11, 3),
- /* 0010 */ V(10, 5, 4),
- /* 0011 */ V(6, 9, 4),
- /* 0100 */ V(10, 4, 3),
- /* 0101 */ V(10, 4, 3),
- /* 0110 */ V(7, 8, 4),
- /* 0111 */ V(8, 7, 4),
- /* 1000 */ V(9, 4, 3),
- /* 1001 */ V(9, 4, 3),
- /* 1010 */ V(7, 7, 4),
- /* 1011 */ V(7, 6, 4),
- /* 1100 */ V(11, 2, 2),
- /* 1101 */ V(11, 2, 2),
- /* 1110 */ V(11, 2, 2),
- /* 1111 */ V(11, 2, 2),
-
- /* 0000 0110 ... */
- /* 000 */ V(1, 11, 2), /* 164 */
- /* 001 */ V(1, 11, 2),
- /* 010 */ V(11, 1, 2),
- /* 011 */ V(11, 1, 2),
- /* 100 */ V(0, 11, 3),
- /* 101 */ V(11, 0, 3),
- /* 110 */ V(9, 6, 3),
- /* 111 */ V(4, 10, 3),
-
- /* 0000 0111 ... */
- /* 000 */ V(3, 10, 3), /* 172 */
- /* 001 */ V(10, 3, 3),
- /* 010 */ V(5, 9, 3),
- /* 011 */ V(9, 5, 3),
- /* 100 */ V(2, 10, 2),
- /* 101 */ V(2, 10, 2),
- /* 110 */ V(10, 2, 2),
- /* 111 */ V(10, 2, 2),
-
- /* 0000 1000 ... */
- /* 000 */ V(1, 10, 2), /* 180 */
- /* 001 */ V(1, 10, 2),
- /* 010 */ V(10, 1, 2),
- /* 011 */ V(10, 1, 2),
- /* 100 */ V(0, 10, 3),
- /* 101 */ V(6, 8, 3),
- /* 110 */ V(10, 0, 2),
- /* 111 */ V(10, 0, 2),
-
- /* 0000 1001 ... */
- /* 000 */ V(8, 6, 3), /* 188 */
- /* 001 */ V(4, 9, 3),
- /* 010 */ V(9, 3, 2),
- /* 011 */ V(9, 3, 2),
- /* 100 */ V(3, 9, 3),
- /* 101 */ V(5, 8, 3),
- /* 110 */ V(8, 5, 3),
- /* 111 */ V(6, 7, 3),
-
- /* 0000 1010 ... */
- /* 000 */ V(2, 9, 2), /* 196 */
- /* 001 */ V(2, 9, 2),
- /* 010 */ V(9, 2, 2),
- /* 011 */ V(9, 2, 2),
- /* 100 */ V(5, 7, 3),
- /* 101 */ V(7, 5, 3),
- /* 110 */ V(3, 8, 2),
- /* 111 */ V(3, 8, 2),
-
- /* 0000 1011 ... */
- /* 000 */ V(8, 3, 2), /* 204 */
- /* 001 */ V(8, 3, 2),
- /* 010 */ V(6, 6, 3),
- /* 011 */ V(4, 7, 3),
- /* 100 */ V(7, 4, 3),
- /* 101 */ V(5, 6, 3),
- /* 110 */ V(6, 5, 3),
- /* 111 */ V(7, 3, 3),
-
- /* 0000 1100 ... */
- /* 0 */ V(1, 9, 1), /* 212 */
- /* 1 */ V(9, 1, 1),
-
- /* 0000 1101 ... */
- /* 00 */ V(0, 9, 2), /* 214 */
- /* 01 */ V(9, 0, 2),
- /* 10 */ V(4, 8, 2),
- /* 11 */ V(8, 4, 2),
-
- /* 0000 1110 ... */
- /* 000 */ V(7, 2, 2), /* 218 */
- /* 001 */ V(7, 2, 2),
- /* 010 */ V(4, 6, 3),
- /* 011 */ V(6, 4, 3),
- /* 100 */ V(2, 8, 1),
- /* 101 */ V(2, 8, 1),
- /* 110 */ V(2, 8, 1),
- /* 111 */ V(2, 8, 1),
-
- /* 0000 1111 ... */
- /* 0 */ V(8, 2, 1), /* 226 */
- /* 1 */ V(1, 8, 1),
-
- /* 0001 0000 ... */
- /* 00 */ V(3, 7, 2), /* 228 */
- /* 01 */ V(2, 7, 2),
- /* 10 */ V(1, 7, 1),
- /* 11 */ V(1, 7, 1),
-
- /* 0001 0001 ... */
- /* 00 */ V(7, 1, 1), /* 232 */
- /* 01 */ V(7, 1, 1),
- /* 10 */ V(5, 5, 2),
- /* 11 */ V(0, 7, 2),
-
- /* 0001 0010 ... */
- /* 00 */ V(7, 0, 2), /* 236 */
- /* 01 */ V(3, 6, 2),
- /* 10 */ V(6, 3, 2),
- /* 11 */ V(4, 5, 2),
-
- /* 0001 0011 ... */
- /* 00 */ V(5, 4, 2), /* 240 */
- /* 01 */ V(2, 6, 2),
- /* 10 */ V(6, 2, 2),
- /* 11 */ V(3, 5, 2),
-
- /* 0001 0101 ... */
- /* 0 */ V(0, 8, 1), /* 244 */
- /* 1 */ V(8, 0, 1),
-
- /* 0001 0110 ... */
- /* 0 */ V(1, 6, 1), /* 246 */
- /* 1 */ V(6, 1, 1),
-
- /* 0001 0111 ... */
- /* 0 */ V(0, 6, 1), /* 248 */
- /* 1 */ V(6, 0, 1),
-
- /* 0001 1000 ... */
- /* 00 */ V(5, 3, 2), /* 250 */
- /* 01 */ V(4, 4, 2),
- /* 10 */ V(2, 5, 1),
- /* 11 */ V(2, 5, 1),
-
- /* 0001 1001 ... */
- /* 0 */ V(5, 2, 1), /* 254 */
- /* 1 */ V(0, 5, 1),
-
- /* 0001 1100 ... */
- /* 0 */ V(3, 4, 1), /* 256 */
- /* 1 */ V(4, 3, 1),
-
- /* 0001 1101 ... */
- /* 0 */ V(5, 0, 1), /* 258 */
- /* 1 */ V(2, 4, 1),
-
- /* 0001 1110 ... */
- /* 0 */ V(4, 2, 1), /* 260 */
- /* 1 */ V(3, 3, 1),
-
- /* 0000 0000 0000 ... */
- /* 0000 */ PTR(388, 3), /* 262 */
- /* 0001 */ V(15, 15, 4),
- /* 0010 */ V(14, 15, 4),
- /* 0011 */ V(13, 15, 4),
- /* 0100 */ V(14, 14, 4),
- /* 0101 */ V(12, 15, 4),
- /* 0110 */ V(13, 14, 4),
- /* 0111 */ V(11, 15, 4),
- /* 1000 */ V(15, 11, 4),
- /* 1001 */ V(12, 14, 4),
- /* 1010 */ V(13, 12, 4),
- /* 1011 */ PTR(396, 1),
- /* 1100 */ V(14, 12, 3),
- /* 1101 */ V(14, 12, 3),
- /* 1110 */ V(13, 13, 3),
- /* 1111 */ V(13, 13, 3),
-
- /* 0000 0000 0001 ... */
- /* 0000 */ V(15, 10, 4), /* 278 */
- /* 0001 */ V(12, 13, 4),
- /* 0010 */ V(11, 14, 3),
- /* 0011 */ V(11, 14, 3),
- /* 0100 */ V(14, 11, 3),
- /* 0101 */ V(14, 11, 3),
- /* 0110 */ V(9, 15, 3),
- /* 0111 */ V(9, 15, 3),
- /* 1000 */ V(15, 9, 3),
- /* 1001 */ V(15, 9, 3),
- /* 1010 */ V(14, 10, 3),
- /* 1011 */ V(14, 10, 3),
- /* 1100 */ V(11, 13, 3),
- /* 1101 */ V(11, 13, 3),
- /* 1110 */ V(13, 11, 3),
- /* 1111 */ V(13, 11, 3),
-
- /* 0000 0000 0010 ... */
- /* 0000 */ V(8, 15, 3), /* 294 */
- /* 0001 */ V(8, 15, 3),
- /* 0010 */ V(15, 8, 3),
- /* 0011 */ V(15, 8, 3),
- /* 0100 */ V(12, 12, 3),
- /* 0101 */ V(12, 12, 3),
- /* 0110 */ V(10, 14, 4),
- /* 0111 */ V(9, 14, 4),
- /* 1000 */ V(8, 14, 3),
- /* 1001 */ V(8, 14, 3),
- /* 1010 */ V(7, 15, 4),
- /* 1011 */ V(7, 14, 4),
- /* 1100 */ V(15, 7, 2),
- /* 1101 */ V(15, 7, 2),
- /* 1110 */ V(15, 7, 2),
- /* 1111 */ V(15, 7, 2),
-
- /* 0000 0000 0011 ... */
- /* 000 */ V(13, 10, 2), /* 310 */
- /* 001 */ V(13, 10, 2),
- /* 010 */ V(10, 13, 3),
- /* 011 */ V(11, 12, 3),
- /* 100 */ V(12, 11, 3),
- /* 101 */ V(15, 6, 3),
- /* 110 */ V(6, 15, 2),
- /* 111 */ V(6, 15, 2),
-
- /* 0000 0000 0100 ... */
- /* 00 */ V(14, 8, 2), /* 318 */
- /* 01 */ V(5, 15, 2),
- /* 10 */ V(9, 13, 2),
- /* 11 */ V(13, 9, 2),
-
- /* 0000 0000 0101 ... */
- /* 00 */ V(15, 5, 2), /* 322 */
- /* 01 */ V(14, 7, 2),
- /* 10 */ V(10, 12, 2),
- /* 11 */ V(11, 11, 2),
-
- /* 0000 0000 0110 ... */
- /* 000 */ V(4, 15, 2), /* 326 */
- /* 001 */ V(4, 15, 2),
- /* 010 */ V(15, 4, 2),
- /* 011 */ V(15, 4, 2),
- /* 100 */ V(12, 10, 3),
- /* 101 */ V(14, 6, 3),
- /* 110 */ V(15, 3, 2),
- /* 111 */ V(15, 3, 2),
-
- /* 0000 0000 0111 ... */
- /* 00 */ V(3, 15, 1), /* 334 */
- /* 01 */ V(3, 15, 1),
- /* 10 */ V(8, 13, 2),
- /* 11 */ V(13, 8, 2),
-
- /* 0000 0000 1000 ... */
- /* 0 */ V(2, 15, 1), /* 338 */
- /* 1 */ V(15, 2, 1),
-
- /* 0000 0000 1001 ... */
- /* 00 */ V(6, 14, 2), /* 340 */
- /* 01 */ V(9, 12, 2),
- /* 10 */ V(0, 15, 1),
- /* 11 */ V(0, 15, 1),
-
- /* 0000 0000 1010 ... */
- /* 00 */ V(12, 9, 2), /* 344 */
- /* 01 */ V(5, 14, 2),
- /* 10 */ V(10, 11, 1),
- /* 11 */ V(10, 11, 1),
-
- /* 0000 0000 1011 ... */
- /* 00 */ V(7, 13, 2), /* 348 */
- /* 01 */ V(13, 7, 2),
- /* 10 */ V(4, 14, 1),
- /* 11 */ V(4, 14, 1),
-
- /* 0000 0000 1100 ... */
- /* 00 */ V(12, 8, 2), /* 352 */
- /* 01 */ V(13, 6, 2),
- /* 10 */ V(3, 14, 1),
- /* 11 */ V(3, 14, 1),
-
- /* 0000 0000 1101 ... */
- /* 00 */ V(11, 9, 1), /* 356 */
- /* 01 */ V(11, 9, 1),
- /* 10 */ V(9, 11, 2),
- /* 11 */ V(10, 10, 2),
-
- /* 0000 0001 0001 ... */
- /* 0 */ V(11, 10, 1), /* 360 */
- /* 1 */ V(14, 5, 1),
-
- /* 0000 0001 0010 ... */
- /* 0 */ V(14, 4, 1), /* 362 */
- /* 1 */ V(8, 12, 1),
-
- /* 0000 0001 0011 ... */
- /* 0 */ V(6, 13, 1), /* 364 */
- /* 1 */ V(14, 3, 1),
-
- /* 0000 0001 0101 ... */
- /* 0 */ V(2, 14, 1), /* 366 */
- /* 1 */ V(0, 14, 1),
-
- /* 0000 0001 1000 ... */
- /* 0 */ V(14, 0, 1), /* 368 */
- /* 1 */ V(5, 13, 1),
-
- /* 0000 0001 1001 ... */
- /* 0 */ V(13, 5, 1), /* 370 */
- /* 1 */ V(7, 12, 1),
-
- /* 0000 0001 1010 ... */
- /* 0 */ V(12, 7, 1), /* 372 */
- /* 1 */ V(4, 13, 1),
-
- /* 0000 0001 1011 ... */
- /* 0 */ V(8, 11, 1), /* 374 */
- /* 1 */ V(11, 8, 1),
-
- /* 0000 0001 1100 ... */
- /* 0 */ V(13, 4, 1), /* 376 */
- /* 1 */ V(9, 10, 1),
-
- /* 0000 0001 1101 ... */
- /* 0 */ V(10, 9, 1), /* 378 */
- /* 1 */ V(6, 12, 1),
-
- /* 0000 0010 0000 ... */
- /* 0 */ V(13, 3, 1), /* 380 */
- /* 1 */ V(7, 11, 1),
-
- /* 0000 0010 0101 ... */
- /* 0 */ V(5, 12, 1), /* 382 */
- /* 1 */ V(12, 5, 1),
-
- /* 0000 0010 0110 ... */
- /* 0 */ V(9, 9, 1), /* 384 */
- /* 1 */ V(7, 10, 1),
-
- /* 0000 0010 1000 ... */
- /* 0 */ V(10, 7, 1), /* 386 */
- /* 1 */ V(9, 7, 1),
-
- /* 0000 0000 0000 0000 ... */
- /* 000 */ V(15, 14, 3), /* 388 */
- /* 001 */ V(15, 12, 3),
- /* 010 */ V(15, 13, 2),
- /* 011 */ V(15, 13, 2),
- /* 100 */ V(14, 13, 1),
- /* 101 */ V(14, 13, 1),
- /* 110 */ V(14, 13, 1),
- /* 111 */ V(14, 13, 1),
-
- /* 0000 0000 0000 1011 ... */
- /* 0 */ V(10, 15, 1), /* 396 */
- /* 1 */ V(14, 9, 1)
-};
-
-static
-union huffpair const hufftab15[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 4),
- /* 0011 */ PTR(64, 4),
- /* 0100 */ PTR(80, 4),
- /* 0101 */ PTR(96, 3),
- /* 0110 */ PTR(104, 3),
- /* 0111 */ PTR(112, 2),
- /* 1000 */ PTR(116, 1),
- /* 1001 */ PTR(118, 1),
- /* 1010 */ V(1, 1, 3),
- /* 1011 */ V(1, 1, 3),
- /* 1100 */ V(0, 1, 4),
- /* 1101 */ V(1, 0, 4),
- /* 1110 */ V(0, 0, 3),
- /* 1111 */ V(0, 0, 3),
-
- /* 0000 ... */
- /* 0000 */ PTR(120, 4), /* 16 */
- /* 0001 */ PTR(136, 4),
- /* 0010 */ PTR(152, 4),
- /* 0011 */ PTR(168, 4),
- /* 0100 */ PTR(184, 4),
- /* 0101 */ PTR(200, 3),
- /* 0110 */ PTR(208, 3),
- /* 0111 */ PTR(216, 4),
- /* 1000 */ PTR(232, 3),
- /* 1001 */ PTR(240, 3),
- /* 1010 */ PTR(248, 3),
- /* 1011 */ PTR(256, 3),
- /* 1100 */ PTR(264, 2),
- /* 1101 */ PTR(268, 3),
- /* 1110 */ PTR(276, 3),
- /* 1111 */ PTR(284, 2),
-
- /* 0001 ... */
- /* 0000 */ PTR(288, 2), /* 32 */
- /* 0001 */ PTR(292, 2),
- /* 0010 */ PTR(296, 2),
- /* 0011 */ PTR(300, 2),
- /* 0100 */ PTR(304, 2),
- /* 0101 */ PTR(308, 2),
- /* 0110 */ PTR(312, 2),
- /* 0111 */ PTR(316, 2),
- /* 1000 */ PTR(320, 1),
- /* 1001 */ PTR(322, 1),
- /* 1010 */ PTR(324, 1),
- /* 1011 */ PTR(326, 2),
- /* 1100 */ PTR(330, 1),
- /* 1101 */ PTR(332, 1),
- /* 1110 */ PTR(334, 2),
- /* 1111 */ PTR(338, 1),
-
- /* 0010 ... */
- /* 0000 */ PTR(340, 1), /* 48 */
- /* 0001 */ PTR(342, 1),
- /* 0010 */ V(9, 1, 4),
- /* 0011 */ PTR(344, 1),
- /* 0100 */ PTR(346, 1),
- /* 0101 */ PTR(348, 1),
- /* 0110 */ PTR(350, 1),
- /* 0111 */ PTR(352, 1),
- /* 1000 */ V(2, 8, 4),
- /* 1001 */ V(8, 2, 4),
- /* 1010 */ V(1, 8, 4),
- /* 1011 */ V(8, 1, 4),
- /* 1100 */ PTR(354, 1),
- /* 1101 */ PTR(356, 1),
- /* 1110 */ PTR(358, 1),
- /* 1111 */ PTR(360, 1),
-
- /* 0011 ... */
- /* 0000 */ V(2, 7, 4), /* 64 */
- /* 0001 */ V(7, 2, 4),
- /* 0010 */ V(6, 4, 4),
- /* 0011 */ V(1, 7, 4),
- /* 0100 */ V(5, 5, 4),
- /* 0101 */ V(7, 1, 4),
- /* 0110 */ PTR(362, 1),
- /* 0111 */ V(3, 6, 4),
- /* 1000 */ V(6, 3, 4),
- /* 1001 */ V(4, 5, 4),
- /* 1010 */ V(5, 4, 4),
- /* 1011 */ V(2, 6, 4),
- /* 1100 */ V(6, 2, 4),
- /* 1101 */ V(1, 6, 4),
- /* 1110 */ PTR(364, 1),
- /* 1111 */ V(3, 5, 4),
-
- /* 0100 ... */
- /* 0000 */ V(6, 1, 3), /* 80 */
- /* 0001 */ V(6, 1, 3),
- /* 0010 */ V(5, 3, 4),
- /* 0011 */ V(4, 4, 4),
- /* 0100 */ V(2, 5, 3),
- /* 0101 */ V(2, 5, 3),
- /* 0110 */ V(5, 2, 3),
- /* 0111 */ V(5, 2, 3),
- /* 1000 */ V(1, 5, 3),
- /* 1001 */ V(1, 5, 3),
- /* 1010 */ V(5, 1, 3),
- /* 1011 */ V(5, 1, 3),
- /* 1100 */ V(0, 5, 4),
- /* 1101 */ V(5, 0, 4),
- /* 1110 */ V(3, 4, 3),
- /* 1111 */ V(3, 4, 3),
-
- /* 0101 ... */
- /* 000 */ V(4, 3, 3), /* 96 */
- /* 001 */ V(2, 4, 3),
- /* 010 */ V(4, 2, 3),
- /* 011 */ V(3, 3, 3),
- /* 100 */ V(4, 1, 2),
- /* 101 */ V(4, 1, 2),
- /* 110 */ V(1, 4, 3),
- /* 111 */ V(0, 4, 3),
-
- /* 0110 ... */
- /* 000 */ V(2, 3, 2), /* 104 */
- /* 001 */ V(2, 3, 2),
- /* 010 */ V(3, 2, 2),
- /* 011 */ V(3, 2, 2),
- /* 100 */ V(4, 0, 3),
- /* 101 */ V(0, 3, 3),
- /* 110 */ V(1, 3, 2),
- /* 111 */ V(1, 3, 2),
-
- /* 0111 ... */
- /* 00 */ V(3, 1, 2), /* 112 */
- /* 01 */ V(3, 0, 2),
- /* 10 */ V(2, 2, 1),
- /* 11 */ V(2, 2, 1),
-
- /* 1000 ... */
- /* 0 */ V(1, 2, 1), /* 116 */
- /* 1 */ V(2, 1, 1),
-
- /* 1001 ... */
- /* 0 */ V(0, 2, 1), /* 118 */
- /* 1 */ V(2, 0, 1),
-
- /* 0000 0000 ... */
- /* 0000 */ PTR(366, 1), /* 120 */
- /* 0001 */ PTR(368, 1),
- /* 0010 */ V(14, 14, 4),
- /* 0011 */ PTR(370, 1),
- /* 0100 */ PTR(372, 1),
- /* 0101 */ PTR(374, 1),
- /* 0110 */ V(15, 11, 4),
- /* 0111 */ PTR(376, 1),
- /* 1000 */ V(13, 13, 4),
- /* 1001 */ V(10, 15, 4),
- /* 1010 */ V(15, 10, 4),
- /* 1011 */ V(11, 14, 4),
- /* 1100 */ V(14, 11, 4),
- /* 1101 */ V(12, 13, 4),
- /* 1110 */ V(13, 12, 4),
- /* 1111 */ V(9, 15, 4),
-
- /* 0000 0001 ... */
- /* 0000 */ V(15, 9, 4), /* 136 */
- /* 0001 */ V(14, 10, 4),
- /* 0010 */ V(11, 13, 4),
- /* 0011 */ V(13, 11, 4),
- /* 0100 */ V(8, 15, 4),
- /* 0101 */ V(15, 8, 4),
- /* 0110 */ V(12, 12, 4),
- /* 0111 */ V(9, 14, 4),
- /* 1000 */ V(14, 9, 4),
- /* 1001 */ V(7, 15, 4),
- /* 1010 */ V(15, 7, 4),
- /* 1011 */ V(10, 13, 4),
- /* 1100 */ V(13, 10, 4),
- /* 1101 */ V(11, 12, 4),
- /* 1110 */ V(6, 15, 4),
- /* 1111 */ PTR(378, 1),
-
- /* 0000 0010 ... */
- /* 0000 */ V(12, 11, 3), /* 152 */
- /* 0001 */ V(12, 11, 3),
- /* 0010 */ V(15, 6, 3),
- /* 0011 */ V(15, 6, 3),
- /* 0100 */ V(8, 14, 4),
- /* 0101 */ V(14, 8, 4),
- /* 0110 */ V(5, 15, 4),
- /* 0111 */ V(9, 13, 4),
- /* 1000 */ V(15, 5, 3),
- /* 1001 */ V(15, 5, 3),
- /* 1010 */ V(7, 14, 3),
- /* 1011 */ V(7, 14, 3),
- /* 1100 */ V(14, 7, 3),
- /* 1101 */ V(14, 7, 3),
- /* 1110 */ V(10, 12, 3),
- /* 1111 */ V(10, 12, 3),
-
- /* 0000 0011 ... */
- /* 0000 */ V(12, 10, 3), /* 168 */
- /* 0001 */ V(12, 10, 3),
- /* 0010 */ V(11, 11, 3),
- /* 0011 */ V(11, 11, 3),
- /* 0100 */ V(13, 9, 4),
- /* 0101 */ V(8, 13, 4),
- /* 0110 */ V(4, 15, 3),
- /* 0111 */ V(4, 15, 3),
- /* 1000 */ V(15, 4, 3),
- /* 1001 */ V(15, 4, 3),
- /* 1010 */ V(3, 15, 3),
- /* 1011 */ V(3, 15, 3),
- /* 1100 */ V(15, 3, 3),
- /* 1101 */ V(15, 3, 3),
- /* 1110 */ V(13, 8, 3),
- /* 1111 */ V(13, 8, 3),
-
- /* 0000 0100 ... */
- /* 0000 */ V(14, 6, 3), /* 184 */
- /* 0001 */ V(14, 6, 3),
- /* 0010 */ V(2, 15, 3),
- /* 0011 */ V(2, 15, 3),
- /* 0100 */ V(15, 2, 3),
- /* 0101 */ V(15, 2, 3),
- /* 0110 */ V(6, 14, 4),
- /* 0111 */ V(15, 0, 4),
- /* 1000 */ V(1, 15, 3),
- /* 1001 */ V(1, 15, 3),
- /* 1010 */ V(15, 1, 3),
- /* 1011 */ V(15, 1, 3),
- /* 1100 */ V(9, 12, 3),
- /* 1101 */ V(9, 12, 3),
- /* 1110 */ V(12, 9, 3),
- /* 1111 */ V(12, 9, 3),
-
- /* 0000 0101 ... */
- /* 000 */ V(5, 14, 3), /* 200 */
- /* 001 */ V(10, 11, 3),
- /* 010 */ V(11, 10, 3),
- /* 011 */ V(14, 5, 3),
- /* 100 */ V(7, 13, 3),
- /* 101 */ V(13, 7, 3),
- /* 110 */ V(4, 14, 3),
- /* 111 */ V(14, 4, 3),
-
- /* 0000 0110 ... */
- /* 000 */ V(8, 12, 3), /* 208 */
- /* 001 */ V(12, 8, 3),
- /* 010 */ V(3, 14, 3),
- /* 011 */ V(6, 13, 3),
- /* 100 */ V(13, 6, 3),
- /* 101 */ V(14, 3, 3),
- /* 110 */ V(9, 11, 3),
- /* 111 */ V(11, 9, 3),
-
- /* 0000 0111 ... */
- /* 0000 */ V(2, 14, 3), /* 216 */
- /* 0001 */ V(2, 14, 3),
- /* 0010 */ V(10, 10, 3),
- /* 0011 */ V(10, 10, 3),
- /* 0100 */ V(14, 2, 3),
- /* 0101 */ V(14, 2, 3),
- /* 0110 */ V(1, 14, 3),
- /* 0111 */ V(1, 14, 3),
- /* 1000 */ V(14, 1, 3),
- /* 1001 */ V(14, 1, 3),
- /* 1010 */ V(0, 14, 4),
- /* 1011 */ V(14, 0, 4),
- /* 1100 */ V(5, 13, 3),
- /* 1101 */ V(5, 13, 3),
- /* 1110 */ V(13, 5, 3),
- /* 1111 */ V(13, 5, 3),
-
- /* 0000 1000 ... */
- /* 000 */ V(7, 12, 3), /* 232 */
- /* 001 */ V(12, 7, 3),
- /* 010 */ V(4, 13, 3),
- /* 011 */ V(8, 11, 3),
- /* 100 */ V(13, 4, 2),
- /* 101 */ V(13, 4, 2),
- /* 110 */ V(11, 8, 3),
- /* 111 */ V(9, 10, 3),
-
- /* 0000 1001 ... */
- /* 000 */ V(10, 9, 3), /* 240 */
- /* 001 */ V(6, 12, 3),
- /* 010 */ V(12, 6, 3),
- /* 011 */ V(3, 13, 3),
- /* 100 */ V(13, 3, 2),
- /* 101 */ V(13, 3, 2),
- /* 110 */ V(13, 2, 2),
- /* 111 */ V(13, 2, 2),
-
- /* 0000 1010 ... */
- /* 000 */ V(2, 13, 3), /* 248 */
- /* 001 */ V(0, 13, 3),
- /* 010 */ V(1, 13, 2),
- /* 011 */ V(1, 13, 2),
- /* 100 */ V(7, 11, 2),
- /* 101 */ V(7, 11, 2),
- /* 110 */ V(11, 7, 2),
- /* 111 */ V(11, 7, 2),
-
- /* 0000 1011 ... */
- /* 000 */ V(13, 1, 2), /* 256 */
- /* 001 */ V(13, 1, 2),
- /* 010 */ V(5, 12, 3),
- /* 011 */ V(13, 0, 3),
- /* 100 */ V(12, 5, 2),
- /* 101 */ V(12, 5, 2),
- /* 110 */ V(8, 10, 2),
- /* 111 */ V(8, 10, 2),
-
- /* 0000 1100 ... */
- /* 00 */ V(10, 8, 2), /* 264 */
- /* 01 */ V(4, 12, 2),
- /* 10 */ V(12, 4, 2),
- /* 11 */ V(6, 11, 2),
-
- /* 0000 1101 ... */
- /* 000 */ V(11, 6, 2), /* 268 */
- /* 001 */ V(11, 6, 2),
- /* 010 */ V(9, 9, 3),
- /* 011 */ V(0, 12, 3),
- /* 100 */ V(3, 12, 2),
- /* 101 */ V(3, 12, 2),
- /* 110 */ V(12, 3, 2),
- /* 111 */ V(12, 3, 2),
-
- /* 0000 1110 ... */
- /* 000 */ V(7, 10, 2), /* 276 */
- /* 001 */ V(7, 10, 2),
- /* 010 */ V(10, 7, 2),
- /* 011 */ V(10, 7, 2),
- /* 100 */ V(10, 6, 2),
- /* 101 */ V(10, 6, 2),
- /* 110 */ V(12, 0, 3),
- /* 111 */ V(0, 11, 3),
-
- /* 0000 1111 ... */
- /* 00 */ V(12, 2, 1), /* 284 */
- /* 01 */ V(12, 2, 1),
- /* 10 */ V(2, 12, 2),
- /* 11 */ V(5, 11, 2),
-
- /* 0001 0000 ... */
- /* 00 */ V(11, 5, 2), /* 288 */
- /* 01 */ V(1, 12, 2),
- /* 10 */ V(8, 9, 2),
- /* 11 */ V(9, 8, 2),
-
- /* 0001 0001 ... */
- /* 00 */ V(12, 1, 2), /* 292 */
- /* 01 */ V(4, 11, 2),
- /* 10 */ V(11, 4, 2),
- /* 11 */ V(6, 10, 2),
-
- /* 0001 0010 ... */
- /* 00 */ V(3, 11, 2), /* 296 */
- /* 01 */ V(7, 9, 2),
- /* 10 */ V(11, 3, 1),
- /* 11 */ V(11, 3, 1),
-
- /* 0001 0011 ... */
- /* 00 */ V(9, 7, 2), /* 300 */
- /* 01 */ V(8, 8, 2),
- /* 10 */ V(2, 11, 2),
- /* 11 */ V(5, 10, 2),
-
- /* 0001 0100 ... */
- /* 00 */ V(11, 2, 1), /* 304 */
- /* 01 */ V(11, 2, 1),
- /* 10 */ V(10, 5, 2),
- /* 11 */ V(1, 11, 2),
-
- /* 0001 0101 ... */
- /* 00 */ V(11, 1, 1), /* 308 */
- /* 01 */ V(11, 1, 1),
- /* 10 */ V(11, 0, 2),
- /* 11 */ V(6, 9, 2),
-
- /* 0001 0110 ... */
- /* 00 */ V(9, 6, 2), /* 312 */
- /* 01 */ V(4, 10, 2),
- /* 10 */ V(10, 4, 2),
- /* 11 */ V(7, 8, 2),
-
- /* 0001 0111 ... */
- /* 00 */ V(8, 7, 2), /* 316 */
- /* 01 */ V(3, 10, 2),
- /* 10 */ V(10, 3, 1),
- /* 11 */ V(10, 3, 1),
-
- /* 0001 1000 ... */
- /* 0 */ V(5, 9, 1), /* 320 */
- /* 1 */ V(9, 5, 1),
-
- /* 0001 1001 ... */
- /* 0 */ V(2, 10, 1), /* 322 */
- /* 1 */ V(10, 2, 1),
-
- /* 0001 1010 ... */
- /* 0 */ V(1, 10, 1), /* 324 */
- /* 1 */ V(10, 1, 1),
-
- /* 0001 1011 ... */
- /* 00 */ V(0, 10, 2), /* 326 */
- /* 01 */ V(10, 0, 2),
- /* 10 */ V(6, 8, 1),
- /* 11 */ V(6, 8, 1),
-
- /* 0001 1100 ... */
- /* 0 */ V(8, 6, 1), /* 330 */
- /* 1 */ V(4, 9, 1),
-
- /* 0001 1101 ... */
- /* 0 */ V(9, 4, 1), /* 332 */
- /* 1 */ V(3, 9, 1),
-
- /* 0001 1110 ... */
- /* 00 */ V(9, 3, 1), /* 334 */
- /* 01 */ V(9, 3, 1),
- /* 10 */ V(7, 7, 2),
- /* 11 */ V(0, 9, 2),
-
- /* 0001 1111 ... */
- /* 0 */ V(5, 8, 1), /* 338 */
- /* 1 */ V(8, 5, 1),
-
- /* 0010 0000 ... */
- /* 0 */ V(2, 9, 1), /* 340 */
- /* 1 */ V(6, 7, 1),
-
- /* 0010 0001 ... */
- /* 0 */ V(7, 6, 1), /* 342 */
- /* 1 */ V(9, 2, 1),
-
- /* 0010 0011 ... */
- /* 0 */ V(1, 9, 1), /* 344 */
- /* 1 */ V(9, 0, 1),
-
- /* 0010 0100 ... */
- /* 0 */ V(4, 8, 1), /* 346 */
- /* 1 */ V(8, 4, 1),
-
- /* 0010 0101 ... */
- /* 0 */ V(5, 7, 1), /* 348 */
- /* 1 */ V(7, 5, 1),
-
- /* 0010 0110 ... */
- /* 0 */ V(3, 8, 1), /* 350 */
- /* 1 */ V(8, 3, 1),
-
- /* 0010 0111 ... */
- /* 0 */ V(6, 6, 1), /* 352 */
- /* 1 */ V(4, 7, 1),
-
- /* 0010 1100 ... */
- /* 0 */ V(7, 4, 1), /* 354 */
- /* 1 */ V(0, 8, 1),
-
- /* 0010 1101 ... */
- /* 0 */ V(8, 0, 1), /* 356 */
- /* 1 */ V(5, 6, 1),
-
- /* 0010 1110 ... */
- /* 0 */ V(6, 5, 1), /* 358 */
- /* 1 */ V(3, 7, 1),
-
- /* 0010 1111 ... */
- /* 0 */ V(7, 3, 1), /* 360 */
- /* 1 */ V(4, 6, 1),
-
- /* 0011 0110 ... */
- /* 0 */ V(0, 7, 1), /* 362 */
- /* 1 */ V(7, 0, 1),
-
- /* 0011 1110 ... */
- /* 0 */ V(0, 6, 1), /* 364 */
- /* 1 */ V(6, 0, 1),
-
- /* 0000 0000 0000 ... */
- /* 0 */ V(15, 15, 1), /* 366 */
- /* 1 */ V(14, 15, 1),
-
- /* 0000 0000 0001 ... */
- /* 0 */ V(15, 14, 1), /* 368 */
- /* 1 */ V(13, 15, 1),
-
- /* 0000 0000 0011 ... */
- /* 0 */ V(15, 13, 1), /* 370 */
- /* 1 */ V(12, 15, 1),
-
- /* 0000 0000 0100 ... */
- /* 0 */ V(15, 12, 1), /* 372 */
- /* 1 */ V(13, 14, 1),
-
- /* 0000 0000 0101 ... */
- /* 0 */ V(14, 13, 1), /* 374 */
- /* 1 */ V(11, 15, 1),
-
- /* 0000 0000 0111 ... */
- /* 0 */ V(12, 14, 1), /* 376 */
- /* 1 */ V(14, 12, 1),
-
- /* 0000 0001 1111 ... */
- /* 0 */ V(10, 14, 1), /* 378 */
- /* 1 */ V(0, 15, 1)
-};
-
-static
-union huffpair const hufftab16[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 4),
- /* 0011 */ PTR(64, 2),
- /* 0100 */ V(1, 1, 4),
- /* 0101 */ V(0, 1, 4),
- /* 0110 */ V(1, 0, 3),
- /* 0111 */ V(1, 0, 3),
- /* 1000 */ V(0, 0, 1),
- /* 1001 */ V(0, 0, 1),
- /* 1010 */ V(0, 0, 1),
- /* 1011 */ V(0, 0, 1),
- /* 1100 */ V(0, 0, 1),
- /* 1101 */ V(0, 0, 1),
- /* 1110 */ V(0, 0, 1),
- /* 1111 */ V(0, 0, 1),
-
- /* 0000 ... */
- /* 0000 */ PTR(68, 3), /* 16 */
- /* 0001 */ PTR(76, 3),
- /* 0010 */ PTR(84, 2),
- /* 0011 */ V(15, 15, 4),
- /* 0100 */ PTR(88, 2),
- /* 0101 */ PTR(92, 1),
- /* 0110 */ PTR(94, 4),
- /* 0111 */ V(15, 2, 4),
- /* 1000 */ PTR(110, 1),
- /* 1001 */ V(1, 15, 4),
- /* 1010 */ V(15, 1, 4),
- /* 1011 */ PTR(112, 4),
- /* 1100 */ PTR(128, 4),
- /* 1101 */ PTR(144, 4),
- /* 1110 */ PTR(160, 4),
- /* 1111 */ PTR(176, 4),
-
- /* 0001 ... */
- /* 0000 */ PTR(192, 4), /* 32 */
- /* 0001 */ PTR(208, 3),
- /* 0010 */ PTR(216, 3),
- /* 0011 */ PTR(224, 3),
- /* 0100 */ PTR(232, 3),
- /* 0101 */ PTR(240, 3),
- /* 0110 */ PTR(248, 3),
- /* 0111 */ PTR(256, 3),
- /* 1000 */ PTR(264, 2),
- /* 1001 */ PTR(268, 2),
- /* 1010 */ PTR(272, 1),
- /* 1011 */ PTR(274, 2),
- /* 1100 */ PTR(278, 2),
- /* 1101 */ PTR(282, 1),
- /* 1110 */ V(5, 1, 4),
- /* 1111 */ PTR(284, 1),
-
- /* 0010 ... */
- /* 0000 */ PTR(286, 1), /* 48 */
- /* 0001 */ PTR(288, 1),
- /* 0010 */ PTR(290, 1),
- /* 0011 */ V(1, 4, 4),
- /* 0100 */ V(4, 1, 4),
- /* 0101 */ PTR(292, 1),
- /* 0110 */ V(2, 3, 4),
- /* 0111 */ V(3, 2, 4),
- /* 1000 */ V(1, 3, 3),
- /* 1001 */ V(1, 3, 3),
- /* 1010 */ V(3, 1, 3),
- /* 1011 */ V(3, 1, 3),
- /* 1100 */ V(0, 3, 4),
- /* 1101 */ V(3, 0, 4),
- /* 1110 */ V(2, 2, 3),
- /* 1111 */ V(2, 2, 3),
-
- /* 0011 ... */
- /* 00 */ V(1, 2, 2), /* 64 */
- /* 01 */ V(2, 1, 2),
- /* 10 */ V(0, 2, 2),
- /* 11 */ V(2, 0, 2),
-
- /* 0000 0000 ... */
- /* 000 */ V(14, 15, 3), /* 68 */
- /* 001 */ V(15, 14, 3),
- /* 010 */ V(13, 15, 3),
- /* 011 */ V(15, 13, 3),
- /* 100 */ V(12, 15, 3),
- /* 101 */ V(15, 12, 3),
- /* 110 */ V(11, 15, 3),
- /* 111 */ V(15, 11, 3),
-
- /* 0000 0001 ... */
- /* 000 */ V(10, 15, 2), /* 76 */
- /* 001 */ V(10, 15, 2),
- /* 010 */ V(15, 10, 3),
- /* 011 */ V(9, 15, 3),
- /* 100 */ V(15, 9, 3),
- /* 101 */ V(15, 8, 3),
- /* 110 */ V(8, 15, 2),
- /* 111 */ V(8, 15, 2),
-
- /* 0000 0010 ... */
- /* 00 */ V(7, 15, 2), /* 84 */
- /* 01 */ V(15, 7, 2),
- /* 10 */ V(6, 15, 2),
- /* 11 */ V(15, 6, 2),
-
- /* 0000 0100 ... */
- /* 00 */ V(5, 15, 2), /* 88 */
- /* 01 */ V(15, 5, 2),
- /* 10 */ V(4, 15, 1),
- /* 11 */ V(4, 15, 1),
-
- /* 0000 0101 ... */
- /* 0 */ V(15, 4, 1), /* 92 */
- /* 1 */ V(15, 3, 1),
-
- /* 0000 0110 ... */
- /* 0000 */ V(15, 0, 1), /* 94 */
- /* 0001 */ V(15, 0, 1),
- /* 0010 */ V(15, 0, 1),
- /* 0011 */ V(15, 0, 1),
- /* 0100 */ V(15, 0, 1),
- /* 0101 */ V(15, 0, 1),
- /* 0110 */ V(15, 0, 1),
- /* 0111 */ V(15, 0, 1),
- /* 1000 */ V(3, 15, 2),
- /* 1001 */ V(3, 15, 2),
- /* 1010 */ V(3, 15, 2),
- /* 1011 */ V(3, 15, 2),
- /* 1100 */ PTR(294, 4),
- /* 1101 */ PTR(310, 3),
- /* 1110 */ PTR(318, 3),
- /* 1111 */ PTR(326, 3),
-
- /* 0000 1000 ... */
- /* 0 */ V(2, 15, 1), /* 110 */
- /* 1 */ V(0, 15, 1),
-
- /* 0000 1011 ... */
- /* 0000 */ PTR(334, 2), /* 112 */
- /* 0001 */ PTR(338, 2),
- /* 0010 */ PTR(342, 2),
- /* 0011 */ PTR(346, 1),
- /* 0100 */ PTR(348, 2),
- /* 0101 */ PTR(352, 2),
- /* 0110 */ PTR(356, 1),
- /* 0111 */ PTR(358, 2),
- /* 1000 */ PTR(362, 2),
- /* 1001 */ PTR(366, 2),
- /* 1010 */ PTR(370, 2),
- /* 1011 */ V(14, 3, 4),
- /* 1100 */ PTR(374, 1),
- /* 1101 */ PTR(376, 1),
- /* 1110 */ PTR(378, 1),
- /* 1111 */ PTR(380, 1),
-
- /* 0000 1100 ... */
- /* 0000 */ PTR(382, 1), /* 128 */
- /* 0001 */ PTR(384, 1),
- /* 0010 */ PTR(386, 1),
- /* 0011 */ V(0, 13, 4),
- /* 0100 */ PTR(388, 1),
- /* 0101 */ PTR(390, 1),
- /* 0110 */ PTR(392, 1),
- /* 0111 */ V(3, 12, 4),
- /* 1000 */ PTR(394, 1),
- /* 1001 */ V(1, 12, 4),
- /* 1010 */ V(12, 0, 4),
- /* 1011 */ PTR(396, 1),
- /* 1100 */ V(14, 2, 3),
- /* 1101 */ V(14, 2, 3),
- /* 1110 */ V(2, 14, 4),
- /* 1111 */ V(1, 14, 4),
-
- /* 0000 1101 ... */
- /* 0000 */ V(13, 3, 4), /* 144 */
- /* 0001 */ V(2, 13, 4),
- /* 0010 */ V(13, 2, 4),
- /* 0011 */ V(13, 1, 4),
- /* 0100 */ V(3, 11, 4),
- /* 0101 */ PTR(398, 1),
- /* 0110 */ V(1, 13, 3),
- /* 0111 */ V(1, 13, 3),
- /* 1000 */ V(12, 4, 4),
- /* 1001 */ V(6, 11, 4),
- /* 1010 */ V(12, 3, 4),
- /* 1011 */ V(10, 7, 4),
- /* 1100 */ V(2, 12, 3),
- /* 1101 */ V(2, 12, 3),
- /* 1110 */ V(12, 2, 4),
- /* 1111 */ V(11, 5, 4),
-
- /* 0000 1110 ... */
- /* 0000 */ V(12, 1, 4), /* 160 */
- /* 0001 */ V(0, 12, 4),
- /* 0010 */ V(4, 11, 4),
- /* 0011 */ V(11, 4, 4),
- /* 0100 */ V(6, 10, 4),
- /* 0101 */ V(10, 6, 4),
- /* 0110 */ V(11, 3, 3),
- /* 0111 */ V(11, 3, 3),
- /* 1000 */ V(5, 10, 4),
- /* 1001 */ V(10, 5, 4),
- /* 1010 */ V(2, 11, 3),
- /* 1011 */ V(2, 11, 3),
- /* 1100 */ V(11, 2, 3),
- /* 1101 */ V(11, 2, 3),
- /* 1110 */ V(1, 11, 3),
- /* 1111 */ V(1, 11, 3),
-
- /* 0000 1111 ... */
- /* 0000 */ V(11, 1, 3), /* 176 */
- /* 0001 */ V(11, 1, 3),
- /* 0010 */ V(0, 11, 4),
- /* 0011 */ V(11, 0, 4),
- /* 0100 */ V(6, 9, 4),
- /* 0101 */ V(9, 6, 4),
- /* 0110 */ V(4, 10, 4),
- /* 0111 */ V(10, 4, 4),
- /* 1000 */ V(7, 8, 4),
- /* 1001 */ V(8, 7, 4),
- /* 1010 */ V(10, 3, 3),
- /* 1011 */ V(10, 3, 3),
- /* 1100 */ V(3, 10, 4),
- /* 1101 */ V(5, 9, 4),
- /* 1110 */ V(2, 10, 3),
- /* 1111 */ V(2, 10, 3),
-
- /* 0001 0000 ... */
- /* 0000 */ V(9, 5, 4), /* 192 */
- /* 0001 */ V(6, 8, 4),
- /* 0010 */ V(10, 1, 3),
- /* 0011 */ V(10, 1, 3),
- /* 0100 */ V(8, 6, 4),
- /* 0101 */ V(7, 7, 4),
- /* 0110 */ V(9, 4, 3),
- /* 0111 */ V(9, 4, 3),
- /* 1000 */ V(4, 9, 4),
- /* 1001 */ V(5, 7, 4),
- /* 1010 */ V(6, 7, 3),
- /* 1011 */ V(6, 7, 3),
- /* 1100 */ V(10, 2, 2),
- /* 1101 */ V(10, 2, 2),
- /* 1110 */ V(10, 2, 2),
- /* 1111 */ V(10, 2, 2),
-
- /* 0001 0001 ... */
- /* 000 */ V(1, 10, 2), /* 208 */
- /* 001 */ V(1, 10, 2),
- /* 010 */ V(0, 10, 3),
- /* 011 */ V(10, 0, 3),
- /* 100 */ V(3, 9, 3),
- /* 101 */ V(9, 3, 3),
- /* 110 */ V(5, 8, 3),
- /* 111 */ V(8, 5, 3),
-
- /* 0001 0010 ... */
- /* 000 */ V(2, 9, 2), /* 216 */
- /* 001 */ V(2, 9, 2),
- /* 010 */ V(9, 2, 2),
- /* 011 */ V(9, 2, 2),
- /* 100 */ V(7, 6, 3),
- /* 101 */ V(0, 9, 3),
- /* 110 */ V(1, 9, 2),
- /* 111 */ V(1, 9, 2),
-
- /* 0001 0011 ... */
- /* 000 */ V(9, 1, 2), /* 224 */
- /* 001 */ V(9, 1, 2),
- /* 010 */ V(9, 0, 3),
- /* 011 */ V(4, 8, 3),
- /* 100 */ V(8, 4, 3),
- /* 101 */ V(7, 5, 3),
- /* 110 */ V(3, 8, 3),
- /* 111 */ V(8, 3, 3),
-
- /* 0001 0100 ... */
- /* 000 */ V(6, 6, 3), /* 232 */
- /* 001 */ V(2, 8, 3),
- /* 010 */ V(8, 2, 2),
- /* 011 */ V(8, 2, 2),
- /* 100 */ V(4, 7, 3),
- /* 101 */ V(7, 4, 3),
- /* 110 */ V(1, 8, 2),
- /* 111 */ V(1, 8, 2),
-
- /* 0001 0101 ... */
- /* 000 */ V(8, 1, 2), /* 240 */
- /* 001 */ V(8, 1, 2),
- /* 010 */ V(8, 0, 2),
- /* 011 */ V(8, 0, 2),
- /* 100 */ V(0, 8, 3),
- /* 101 */ V(5, 6, 3),
- /* 110 */ V(3, 7, 2),
- /* 111 */ V(3, 7, 2),
-
- /* 0001 0110 ... */
- /* 000 */ V(7, 3, 2), /* 248 */
- /* 001 */ V(7, 3, 2),
- /* 010 */ V(6, 5, 3),
- /* 011 */ V(4, 6, 3),
- /* 100 */ V(2, 7, 2),
- /* 101 */ V(2, 7, 2),
- /* 110 */ V(7, 2, 2),
- /* 111 */ V(7, 2, 2),
-
- /* 0001 0111 ... */
- /* 000 */ V(6, 4, 3), /* 256 */
- /* 001 */ V(5, 5, 3),
- /* 010 */ V(0, 7, 2),
- /* 011 */ V(0, 7, 2),
- /* 100 */ V(1, 7, 1),
- /* 101 */ V(1, 7, 1),
- /* 110 */ V(1, 7, 1),
- /* 111 */ V(1, 7, 1),
-
- /* 0001 1000 ... */
- /* 00 */ V(7, 1, 1), /* 264 */
- /* 01 */ V(7, 1, 1),
- /* 10 */ V(7, 0, 2),
- /* 11 */ V(3, 6, 2),
-
- /* 0001 1001 ... */
- /* 00 */ V(6, 3, 2), /* 268 */
- /* 01 */ V(4, 5, 2),
- /* 10 */ V(5, 4, 2),
- /* 11 */ V(2, 6, 2),
-
- /* 0001 1010 ... */
- /* 0 */ V(6, 2, 1), /* 272 */
- /* 1 */ V(1, 6, 1),
-
- /* 0001 1011 ... */
- /* 00 */ V(6, 1, 1), /* 274 */
- /* 01 */ V(6, 1, 1),
- /* 10 */ V(0, 6, 2),
- /* 11 */ V(6, 0, 2),
-
- /* 0001 1100 ... */
- /* 00 */ V(5, 3, 1), /* 278 */
- /* 01 */ V(5, 3, 1),
- /* 10 */ V(3, 5, 2),
- /* 11 */ V(4, 4, 2),
-
- /* 0001 1101 ... */
- /* 0 */ V(2, 5, 1), /* 282 */
- /* 1 */ V(5, 2, 1),
-
- /* 0001 1111 ... */
- /* 0 */ V(1, 5, 1), /* 284 */
- /* 1 */ V(0, 5, 1),
-
- /* 0010 0000 ... */
- /* 0 */ V(3, 4, 1), /* 286 */
- /* 1 */ V(4, 3, 1),
-
- /* 0010 0001 ... */
- /* 0 */ V(5, 0, 1), /* 288 */
- /* 1 */ V(2, 4, 1),
-
- /* 0010 0010 ... */
- /* 0 */ V(4, 2, 1), /* 290 */
- /* 1 */ V(3, 3, 1),
-
- /* 0010 0101 ... */
- /* 0 */ V(0, 4, 1), /* 292 */
- /* 1 */ V(4, 0, 1),
-
- /* 0000 0110 1100 ... */
- /* 0000 */ V(12, 14, 4), /* 294 */
- /* 0001 */ PTR(400, 1),
- /* 0010 */ V(13, 14, 3),
- /* 0011 */ V(13, 14, 3),
- /* 0100 */ V(14, 9, 3),
- /* 0101 */ V(14, 9, 3),
- /* 0110 */ V(14, 10, 4),
- /* 0111 */ V(13, 9, 4),
- /* 1000 */ V(14, 14, 2),
- /* 1001 */ V(14, 14, 2),
- /* 1010 */ V(14, 14, 2),
- /* 1011 */ V(14, 14, 2),
- /* 1100 */ V(14, 13, 3),
- /* 1101 */ V(14, 13, 3),
- /* 1110 */ V(14, 11, 3),
- /* 1111 */ V(14, 11, 3),
-
- /* 0000 0110 1101 ... */
- /* 000 */ V(11, 14, 2), /* 310 */
- /* 001 */ V(11, 14, 2),
- /* 010 */ V(12, 13, 2),
- /* 011 */ V(12, 13, 2),
- /* 100 */ V(13, 12, 3),
- /* 101 */ V(13, 11, 3),
- /* 110 */ V(10, 14, 2),
- /* 111 */ V(10, 14, 2),
-
- /* 0000 0110 1110 ... */
- /* 000 */ V(12, 12, 2), /* 318 */
- /* 001 */ V(12, 12, 2),
- /* 010 */ V(10, 13, 3),
- /* 011 */ V(13, 10, 3),
- /* 100 */ V(7, 14, 3),
- /* 101 */ V(10, 12, 3),
- /* 110 */ V(12, 10, 2),
- /* 111 */ V(12, 10, 2),
-
- /* 0000 0110 1111 ... */
- /* 000 */ V(12, 9, 3), /* 326 */
- /* 001 */ V(7, 13, 3),
- /* 010 */ V(5, 14, 2),
- /* 011 */ V(5, 14, 2),
- /* 100 */ V(11, 13, 1),
- /* 101 */ V(11, 13, 1),
- /* 110 */ V(11, 13, 1),
- /* 111 */ V(11, 13, 1),
-
- /* 0000 1011 0000 ... */
- /* 00 */ V(9, 14, 1), /* 334 */
- /* 01 */ V(9, 14, 1),
- /* 10 */ V(11, 12, 2),
- /* 11 */ V(12, 11, 2),
-
- /* 0000 1011 0001 ... */
- /* 00 */ V(8, 14, 2), /* 338 */
- /* 01 */ V(14, 8, 2),
- /* 10 */ V(9, 13, 2),
- /* 11 */ V(14, 7, 2),
-
- /* 0000 1011 0010 ... */
- /* 00 */ V(11, 11, 2), /* 342 */
- /* 01 */ V(8, 13, 2),
- /* 10 */ V(13, 8, 2),
- /* 11 */ V(6, 14, 2),
-
- /* 0000 1011 0011 ... */
- /* 0 */ V(14, 6, 1), /* 346 */
- /* 1 */ V(9, 12, 1),
-
- /* 0000 1011 0100 ... */
- /* 00 */ V(10, 11, 2), /* 348 */
- /* 01 */ V(11, 10, 2),
- /* 10 */ V(14, 5, 2),
- /* 11 */ V(13, 7, 2),
-
- /* 0000 1011 0101 ... */
- /* 00 */ V(4, 14, 1), /* 352 */
- /* 01 */ V(4, 14, 1),
- /* 10 */ V(14, 4, 2),
- /* 11 */ V(8, 12, 2),
-
- /* 0000 1011 0110 ... */
- /* 0 */ V(12, 8, 1), /* 356 */
- /* 1 */ V(3, 14, 1),
-
- /* 0000 1011 0111 ... */
- /* 00 */ V(6, 13, 1), /* 358 */
- /* 01 */ V(6, 13, 1),
- /* 10 */ V(13, 6, 2),
- /* 11 */ V(9, 11, 2),
-
- /* 0000 1011 1000 ... */
- /* 00 */ V(11, 9, 2), /* 362 */
- /* 01 */ V(10, 10, 2),
- /* 10 */ V(14, 1, 1),
- /* 11 */ V(14, 1, 1),
-
- /* 0000 1011 1001 ... */
- /* 00 */ V(13, 4, 1), /* 366 */
- /* 01 */ V(13, 4, 1),
- /* 10 */ V(11, 8, 2),
- /* 11 */ V(10, 9, 2),
-
- /* 0000 1011 1010 ... */
- /* 00 */ V(7, 11, 1), /* 370 */
- /* 01 */ V(7, 11, 1),
- /* 10 */ V(11, 7, 2),
- /* 11 */ V(13, 0, 2),
-
- /* 0000 1011 1100 ... */
- /* 0 */ V(0, 14, 1), /* 374 */
- /* 1 */ V(14, 0, 1),
-
- /* 0000 1011 1101 ... */
- /* 0 */ V(5, 13, 1), /* 376 */
- /* 1 */ V(13, 5, 1),
-
- /* 0000 1011 1110 ... */
- /* 0 */ V(7, 12, 1), /* 378 */
- /* 1 */ V(12, 7, 1),
-
- /* 0000 1011 1111 ... */
- /* 0 */ V(4, 13, 1), /* 380 */
- /* 1 */ V(8, 11, 1),
-
- /* 0000 1100 0000 ... */
- /* 0 */ V(9, 10, 1), /* 382 */
- /* 1 */ V(6, 12, 1),
-
- /* 0000 1100 0001 ... */
- /* 0 */ V(12, 6, 1), /* 384 */
- /* 1 */ V(3, 13, 1),
-
- /* 0000 1100 0010 ... */
- /* 0 */ V(5, 12, 1), /* 386 */
- /* 1 */ V(12, 5, 1),
-
- /* 0000 1100 0100 ... */
- /* 0 */ V(8, 10, 1), /* 388 */
- /* 1 */ V(10, 8, 1),
-
- /* 0000 1100 0101 ... */
- /* 0 */ V(9, 9, 1), /* 390 */
- /* 1 */ V(4, 12, 1),
-
- /* 0000 1100 0110 ... */
- /* 0 */ V(11, 6, 1), /* 392 */
- /* 1 */ V(7, 10, 1),
-
- /* 0000 1100 1000 ... */
- /* 0 */ V(5, 11, 1), /* 394 */
- /* 1 */ V(8, 9, 1),
-
- /* 0000 1100 1011 ... */
- /* 0 */ V(9, 8, 1), /* 396 */
- /* 1 */ V(7, 9, 1),
-
- /* 0000 1101 0101 ... */
- /* 0 */ V(9, 7, 1), /* 398 */
- /* 1 */ V(8, 8, 1),
-
- /* 0000 0110 1100 0001 ... */
- /* 0 */ V(14, 12, 1), /* 400 */
- /* 1 */ V(13, 13, 1)
-};
-
-static
-union huffpair const hufftab24[] = {
- /* 0000 */ PTR(16, 4),
- /* 0001 */ PTR(32, 4),
- /* 0010 */ PTR(48, 4),
- /* 0011 */ V(15, 15, 4),
- /* 0100 */ PTR(64, 4),
- /* 0101 */ PTR(80, 4),
- /* 0110 */ PTR(96, 4),
- /* 0111 */ PTR(112, 4),
- /* 1000 */ PTR(128, 4),
- /* 1001 */ PTR(144, 4),
- /* 1010 */ PTR(160, 3),
- /* 1011 */ PTR(168, 2),
- /* 1100 */ V(1, 1, 4),
- /* 1101 */ V(0, 1, 4),
- /* 1110 */ V(1, 0, 4),
- /* 1111 */ V(0, 0, 4),
-
- /* 0000 ... */
- /* 0000 */ V(14, 15, 4), /* 16 */
- /* 0001 */ V(15, 14, 4),
- /* 0010 */ V(13, 15, 4),
- /* 0011 */ V(15, 13, 4),
- /* 0100 */ V(12, 15, 4),
- /* 0101 */ V(15, 12, 4),
- /* 0110 */ V(11, 15, 4),
- /* 0111 */ V(15, 11, 4),
- /* 1000 */ V(15, 10, 3),
- /* 1001 */ V(15, 10, 3),
- /* 1010 */ V(10, 15, 4),
- /* 1011 */ V(9, 15, 4),
- /* 1100 */ V(15, 9, 3),
- /* 1101 */ V(15, 9, 3),
- /* 1110 */ V(15, 8, 3),
- /* 1111 */ V(15, 8, 3),
-
- /* 0001 ... */
- /* 0000 */ V(8, 15, 4), /* 32 */
- /* 0001 */ V(7, 15, 4),
- /* 0010 */ V(15, 7, 3),
- /* 0011 */ V(15, 7, 3),
- /* 0100 */ V(6, 15, 3),
- /* 0101 */ V(6, 15, 3),
- /* 0110 */ V(15, 6, 3),
- /* 0111 */ V(15, 6, 3),
- /* 1000 */ V(5, 15, 3),
- /* 1001 */ V(5, 15, 3),
- /* 1010 */ V(15, 5, 3),
- /* 1011 */ V(15, 5, 3),
- /* 1100 */ V(4, 15, 3),
- /* 1101 */ V(4, 15, 3),
- /* 1110 */ V(15, 4, 3),
- /* 1111 */ V(15, 4, 3),
-
- /* 0010 ... */
- /* 0000 */ V(3, 15, 3), /* 48 */
- /* 0001 */ V(3, 15, 3),
- /* 0010 */ V(15, 3, 3),
- /* 0011 */ V(15, 3, 3),
- /* 0100 */ V(2, 15, 3),
- /* 0101 */ V(2, 15, 3),
- /* 0110 */ V(15, 2, 3),
- /* 0111 */ V(15, 2, 3),
- /* 1000 */ V(15, 1, 3),
- /* 1001 */ V(15, 1, 3),
- /* 1010 */ V(1, 15, 4),
- /* 1011 */ V(15, 0, 4),
- /* 1100 */ PTR(172, 3),
- /* 1101 */ PTR(180, 3),
- /* 1110 */ PTR(188, 3),
- /* 1111 */ PTR(196, 3),
-
- /* 0100 ... */
- /* 0000 */ PTR(204, 4), /* 64 */
- /* 0001 */ PTR(220, 3),
- /* 0010 */ PTR(228, 3),
- /* 0011 */ PTR(236, 3),
- /* 0100 */ PTR(244, 2),
- /* 0101 */ PTR(248, 2),
- /* 0110 */ PTR(252, 2),
- /* 0111 */ PTR(256, 2),
- /* 1000 */ PTR(260, 2),
- /* 1001 */ PTR(264, 2),
- /* 1010 */ PTR(268, 2),
- /* 1011 */ PTR(272, 2),
- /* 1100 */ PTR(276, 2),
- /* 1101 */ PTR(280, 3),
- /* 1110 */ PTR(288, 2),
- /* 1111 */ PTR(292, 2),
-
- /* 0101 ... */
- /* 0000 */ PTR(296, 2), /* 80 */
- /* 0001 */ PTR(300, 3),
- /* 0010 */ PTR(308, 2),
- /* 0011 */ PTR(312, 3),
- /* 0100 */ PTR(320, 1),
- /* 0101 */ PTR(322, 2),
- /* 0110 */ PTR(326, 2),
- /* 0111 */ PTR(330, 1),
- /* 1000 */ PTR(332, 2),
- /* 1001 */ PTR(336, 1),
- /* 1010 */ PTR(338, 1),
- /* 1011 */ PTR(340, 1),
- /* 1100 */ PTR(342, 1),
- /* 1101 */ PTR(344, 1),
- /* 1110 */ PTR(346, 1),
- /* 1111 */ PTR(348, 1),
-
- /* 0110 ... */
- /* 0000 */ PTR(350, 1), /* 96 */
- /* 0001 */ PTR(352, 1),
- /* 0010 */ PTR(354, 1),
- /* 0011 */ PTR(356, 1),
- /* 0100 */ PTR(358, 1),
- /* 0101 */ PTR(360, 1),
- /* 0110 */ PTR(362, 1),
- /* 0111 */ PTR(364, 1),
- /* 1000 */ PTR(366, 1),
- /* 1001 */ PTR(368, 1),
- /* 1010 */ PTR(370, 2),
- /* 1011 */ PTR(374, 1),
- /* 1100 */ PTR(376, 2),
- /* 1101 */ V(7, 3, 4),
- /* 1110 */ PTR(380, 1),
- /* 1111 */ V(7, 2, 4),
-
- /* 0111 ... */
- /* 0000 */ V(4, 6, 4), /* 112 */
- /* 0001 */ V(6, 4, 4),
- /* 0010 */ V(5, 5, 4),
- /* 0011 */ V(7, 1, 4),
- /* 0100 */ V(3, 6, 4),
- /* 0101 */ V(6, 3, 4),
- /* 0110 */ V(4, 5, 4),
- /* 0111 */ V(5, 4, 4),
- /* 1000 */ V(2, 6, 4),
- /* 1001 */ V(6, 2, 4),
- /* 1010 */ V(1, 6, 4),
- /* 1011 */ V(6, 1, 4),
- /* 1100 */ PTR(382, 1),
- /* 1101 */ V(3, 5, 4),
- /* 1110 */ V(5, 3, 4),
- /* 1111 */ V(4, 4, 4),
-
- /* 1000 ... */
- /* 0000 */ V(2, 5, 4), /* 128 */
- /* 0001 */ V(5, 2, 4),
- /* 0010 */ V(1, 5, 4),
- /* 0011 */ PTR(384, 1),
- /* 0100 */ V(5, 1, 3),
- /* 0101 */ V(5, 1, 3),
- /* 0110 */ V(3, 4, 4),
- /* 0111 */ V(4, 3, 4),
- /* 1000 */ V(2, 4, 3),
- /* 1001 */ V(2, 4, 3),
- /* 1010 */ V(4, 2, 3),
- /* 1011 */ V(4, 2, 3),
- /* 1100 */ V(3, 3, 3),
- /* 1101 */ V(3, 3, 3),
- /* 1110 */ V(1, 4, 3),
- /* 1111 */ V(1, 4, 3),
-
- /* 1001 ... */
- /* 0000 */ V(4, 1, 3), /* 144 */
- /* 0001 */ V(4, 1, 3),
- /* 0010 */ V(0, 4, 4),
- /* 0011 */ V(4, 0, 4),
- /* 0100 */ V(2, 3, 3),
- /* 0101 */ V(2, 3, 3),
- /* 0110 */ V(3, 2, 3),
- /* 0111 */ V(3, 2, 3),
- /* 1000 */ V(1, 3, 2),
- /* 1001 */ V(1, 3, 2),
- /* 1010 */ V(1, 3, 2),
- /* 1011 */ V(1, 3, 2),
- /* 1100 */ V(3, 1, 2),
- /* 1101 */ V(3, 1, 2),
- /* 1110 */ V(3, 1, 2),
- /* 1111 */ V(3, 1, 2),
-
- /* 1010 ... */
- /* 000 */ V(0, 3, 3), /* 160 */
- /* 001 */ V(3, 0, 3),
- /* 010 */ V(2, 2, 2),
- /* 011 */ V(2, 2, 2),
- /* 100 */ V(1, 2, 1),
- /* 101 */ V(1, 2, 1),
- /* 110 */ V(1, 2, 1),
- /* 111 */ V(1, 2, 1),
-
- /* 1011 ... */
- /* 00 */ V(2, 1, 1), /* 168 */
- /* 01 */ V(2, 1, 1),
- /* 10 */ V(0, 2, 2),
- /* 11 */ V(2, 0, 2),
-
- /* 0010 1100 ... */
- /* 000 */ V(0, 15, 1), /* 172 */
- /* 001 */ V(0, 15, 1),
- /* 010 */ V(0, 15, 1),
- /* 011 */ V(0, 15, 1),
- /* 100 */ V(14, 14, 3),
- /* 101 */ V(13, 14, 3),
- /* 110 */ V(14, 13, 3),
- /* 111 */ V(12, 14, 3),
-
- /* 0010 1101 ... */
- /* 000 */ V(14, 12, 3), /* 180 */
- /* 001 */ V(13, 13, 3),
- /* 010 */ V(11, 14, 3),
- /* 011 */ V(14, 11, 3),
- /* 100 */ V(12, 13, 3),
- /* 101 */ V(13, 12, 3),
- /* 110 */ V(10, 14, 3),
- /* 111 */ V(14, 10, 3),
-
- /* 0010 1110 ... */
- /* 000 */ V(11, 13, 3), /* 188 */
- /* 001 */ V(13, 11, 3),
- /* 010 */ V(12, 12, 3),
- /* 011 */ V(9, 14, 3),
- /* 100 */ V(14, 9, 3),
- /* 101 */ V(10, 13, 3),
- /* 110 */ V(13, 10, 3),
- /* 111 */ V(11, 12, 3),
-
- /* 0010 1111 ... */
- /* 000 */ V(12, 11, 3), /* 196 */
- /* 001 */ V(8, 14, 3),
- /* 010 */ V(14, 8, 3),
- /* 011 */ V(9, 13, 3),
- /* 100 */ V(13, 9, 3),
- /* 101 */ V(7, 14, 3),
- /* 110 */ V(14, 7, 3),
- /* 111 */ V(10, 12, 3),
-
- /* 0100 0000 ... */
- /* 0000 */ V(12, 10, 3), /* 204 */
- /* 0001 */ V(12, 10, 3),
- /* 0010 */ V(11, 11, 3),
- /* 0011 */ V(11, 11, 3),
- /* 0100 */ V(8, 13, 3),
- /* 0101 */ V(8, 13, 3),
- /* 0110 */ V(13, 8, 3),
- /* 0111 */ V(13, 8, 3),
- /* 1000 */ V(0, 14, 4),
- /* 1001 */ V(14, 0, 4),
- /* 1010 */ V(0, 13, 3),
- /* 1011 */ V(0, 13, 3),
- /* 1100 */ V(14, 6, 2),
- /* 1101 */ V(14, 6, 2),
- /* 1110 */ V(14, 6, 2),
- /* 1111 */ V(14, 6, 2),
-
- /* 0100 0001 ... */
- /* 000 */ V(6, 14, 3), /* 220 */
- /* 001 */ V(9, 12, 3),
- /* 010 */ V(12, 9, 2),
- /* 011 */ V(12, 9, 2),
- /* 100 */ V(5, 14, 2),
- /* 101 */ V(5, 14, 2),
- /* 110 */ V(11, 10, 2),
- /* 111 */ V(11, 10, 2),
-
- /* 0100 0010 ... */
- /* 000 */ V(14, 5, 2), /* 228 */
- /* 001 */ V(14, 5, 2),
- /* 010 */ V(10, 11, 3),
- /* 011 */ V(7, 13, 3),
- /* 100 */ V(13, 7, 2),
- /* 101 */ V(13, 7, 2),
- /* 110 */ V(14, 4, 2),
- /* 111 */ V(14, 4, 2),
-
- /* 0100 0011 ... */
- /* 000 */ V(8, 12, 2), /* 236 */
- /* 001 */ V(8, 12, 2),
- /* 010 */ V(12, 8, 2),
- /* 011 */ V(12, 8, 2),
- /* 100 */ V(4, 14, 3),
- /* 101 */ V(2, 14, 3),
- /* 110 */ V(3, 14, 2),
- /* 111 */ V(3, 14, 2),
-
- /* 0100 0100 ... */
- /* 00 */ V(6, 13, 2), /* 244 */
- /* 01 */ V(13, 6, 2),
- /* 10 */ V(14, 3, 2),
- /* 11 */ V(9, 11, 2),
-
- /* 0100 0101 ... */
- /* 00 */ V(11, 9, 2), /* 248 */
- /* 01 */ V(10, 10, 2),
- /* 10 */ V(14, 2, 2),
- /* 11 */ V(1, 14, 2),
-
- /* 0100 0110 ... */
- /* 00 */ V(14, 1, 2), /* 252 */
- /* 01 */ V(5, 13, 2),
- /* 10 */ V(13, 5, 2),
- /* 11 */ V(7, 12, 2),
-
- /* 0100 0111 ... */
- /* 00 */ V(12, 7, 2), /* 256 */
- /* 01 */ V(4, 13, 2),
- /* 10 */ V(8, 11, 2),
- /* 11 */ V(11, 8, 2),
-
- /* 0100 1000 ... */
- /* 00 */ V(13, 4, 2), /* 260 */
- /* 01 */ V(9, 10, 2),
- /* 10 */ V(10, 9, 2),
- /* 11 */ V(6, 12, 2),
-
- /* 0100 1001 ... */
- /* 00 */ V(12, 6, 2), /* 264 */
- /* 01 */ V(3, 13, 2),
- /* 10 */ V(13, 3, 2),
- /* 11 */ V(2, 13, 2),
-
- /* 0100 1010 ... */
- /* 00 */ V(13, 2, 2), /* 268 */
- /* 01 */ V(1, 13, 2),
- /* 10 */ V(7, 11, 2),
- /* 11 */ V(11, 7, 2),
-
- /* 0100 1011 ... */
- /* 00 */ V(13, 1, 2), /* 272 */
- /* 01 */ V(5, 12, 2),
- /* 10 */ V(12, 5, 2),
- /* 11 */ V(8, 10, 2),
-
- /* 0100 1100 ... */
- /* 00 */ V(10, 8, 2), /* 276 */
- /* 01 */ V(9, 9, 2),
- /* 10 */ V(4, 12, 2),
- /* 11 */ V(12, 4, 2),
-
- /* 0100 1101 ... */
- /* 000 */ V(6, 11, 2), /* 280 */
- /* 001 */ V(6, 11, 2),
- /* 010 */ V(11, 6, 2),
- /* 011 */ V(11, 6, 2),
- /* 100 */ V(13, 0, 3),
- /* 101 */ V(0, 12, 3),
- /* 110 */ V(3, 12, 2),
- /* 111 */ V(3, 12, 2),
-
- /* 0100 1110 ... */
- /* 00 */ V(12, 3, 2), /* 288 */
- /* 01 */ V(7, 10, 2),
- /* 10 */ V(10, 7, 2),
- /* 11 */ V(2, 12, 2),
-
- /* 0100 1111 ... */
- /* 00 */ V(12, 2, 2), /* 292 */
- /* 01 */ V(5, 11, 2),
- /* 10 */ V(11, 5, 2),
- /* 11 */ V(1, 12, 2),
-
- /* 0101 0000 ... */
- /* 00 */ V(8, 9, 2), /* 296 */
- /* 01 */ V(9, 8, 2),
- /* 10 */ V(12, 1, 2),
- /* 11 */ V(4, 11, 2),
-
- /* 0101 0001 ... */
- /* 000 */ V(12, 0, 3), /* 300 */
- /* 001 */ V(0, 11, 3),
- /* 010 */ V(3, 11, 2),
- /* 011 */ V(3, 11, 2),
- /* 100 */ V(11, 0, 3),
- /* 101 */ V(0, 10, 3),
- /* 110 */ V(1, 10, 2),
- /* 111 */ V(1, 10, 2),
-
- /* 0101 0010 ... */
- /* 00 */ V(11, 4, 1), /* 308 */
- /* 01 */ V(11, 4, 1),
- /* 10 */ V(6, 10, 2),
- /* 11 */ V(10, 6, 2),
-
- /* 0101 0011 ... */
- /* 000 */ V(7, 9, 2), /* 312 */
- /* 001 */ V(7, 9, 2),
- /* 010 */ V(9, 7, 2),
- /* 011 */ V(9, 7, 2),
- /* 100 */ V(10, 0, 3),
- /* 101 */ V(0, 9, 3),
- /* 110 */ V(9, 0, 2),
- /* 111 */ V(9, 0, 2),
-
- /* 0101 0100 ... */
- /* 0 */ V(11, 3, 1), /* 320 */
- /* 1 */ V(8, 8, 1),
-
- /* 0101 0101 ... */
- /* 00 */ V(2, 11, 2), /* 322 */
- /* 01 */ V(5, 10, 2),
- /* 10 */ V(11, 2, 1),
- /* 11 */ V(11, 2, 1),
-
- /* 0101 0110 ... */
- /* 00 */ V(10, 5, 2), /* 326 */
- /* 01 */ V(1, 11, 2),
- /* 10 */ V(11, 1, 2),
- /* 11 */ V(6, 9, 2),
-
- /* 0101 0111 ... */
- /* 0 */ V(9, 6, 1), /* 330 */
- /* 1 */ V(10, 4, 1),
-
- /* 0101 1000 ... */
- /* 00 */ V(4, 10, 2), /* 332 */
- /* 01 */ V(7, 8, 2),
- /* 10 */ V(8, 7, 1),
- /* 11 */ V(8, 7, 1),
-
- /* 0101 1001 ... */
- /* 0 */ V(3, 10, 1), /* 336 */
- /* 1 */ V(10, 3, 1),
-
- /* 0101 1010 ... */
- /* 0 */ V(5, 9, 1), /* 338 */
- /* 1 */ V(9, 5, 1),
-
- /* 0101 1011 ... */
- /* 0 */ V(2, 10, 1), /* 340 */
- /* 1 */ V(10, 2, 1),
-
- /* 0101 1100 ... */
- /* 0 */ V(10, 1, 1), /* 342 */
- /* 1 */ V(6, 8, 1),
-
- /* 0101 1101 ... */
- /* 0 */ V(8, 6, 1), /* 344 */
- /* 1 */ V(7, 7, 1),
-
- /* 0101 1110 ... */
- /* 0 */ V(4, 9, 1), /* 346 */
- /* 1 */ V(9, 4, 1),
-
- /* 0101 1111 ... */
- /* 0 */ V(3, 9, 1), /* 348 */
- /* 1 */ V(9, 3, 1),
-
- /* 0110 0000 ... */
- /* 0 */ V(5, 8, 1), /* 350 */
- /* 1 */ V(8, 5, 1),
-
- /* 0110 0001 ... */
- /* 0 */ V(2, 9, 1), /* 352 */
- /* 1 */ V(6, 7, 1),
-
- /* 0110 0010 ... */
- /* 0 */ V(7, 6, 1), /* 354 */
- /* 1 */ V(9, 2, 1),
-
- /* 0110 0011 ... */
- /* 0 */ V(1, 9, 1), /* 356 */
- /* 1 */ V(9, 1, 1),
-
- /* 0110 0100 ... */
- /* 0 */ V(4, 8, 1), /* 358 */
- /* 1 */ V(8, 4, 1),
-
- /* 0110 0101 ... */
- /* 0 */ V(5, 7, 1), /* 360 */
- /* 1 */ V(7, 5, 1),
-
- /* 0110 0110 ... */
- /* 0 */ V(3, 8, 1), /* 362 */
- /* 1 */ V(8, 3, 1),
-
- /* 0110 0111 ... */
- /* 0 */ V(6, 6, 1), /* 364 */
- /* 1 */ V(2, 8, 1),
-
- /* 0110 1000 ... */
- /* 0 */ V(8, 2, 1), /* 366 */
- /* 1 */ V(1, 8, 1),
-
- /* 0110 1001 ... */
- /* 0 */ V(4, 7, 1), /* 368 */
- /* 1 */ V(7, 4, 1),
-
- /* 0110 1010 ... */
- /* 00 */ V(8, 1, 1), /* 370 */
- /* 01 */ V(8, 1, 1),
- /* 10 */ V(0, 8, 2),
- /* 11 */ V(8, 0, 2),
-
- /* 0110 1011 ... */
- /* 0 */ V(5, 6, 1), /* 374 */
- /* 1 */ V(6, 5, 1),
-
- /* 0110 1100 ... */
- /* 00 */ V(1, 7, 1), /* 376 */
- /* 01 */ V(1, 7, 1),
- /* 10 */ V(0, 7, 2),
- /* 11 */ V(7, 0, 2),
-
- /* 0110 1110 ... */
- /* 0 */ V(3, 7, 1), /* 380 */
- /* 1 */ V(2, 7, 1),
-
- /* 0111 1100 ... */
- /* 0 */ V(0, 6, 1), /* 382 */
- /* 1 */ V(6, 0, 1),
-
- /* 1000 0011 ... */
- /* 0 */ V(0, 5, 1), /* 384 */
- /* 1 */ V(5, 0, 1)
-};
-
-# undef V
-# undef PTR
-
-/* external tables */
-
-union huffquad const *const mad_huff_quad_table[2] = { hufftabA, hufftabB };
-
-struct hufftable const mad_huff_pair_table[32] = {
- /* 0 */ { hufftab0, 0, 0 },
- /* 1 */ { hufftab1, 0, 3 },
- /* 2 */ { hufftab2, 0, 3 },
- /* 3 */ { hufftab3, 0, 3 },
- /* 4 */ { 0 /* not used */ },
- /* 5 */ { hufftab5, 0, 3 },
- /* 6 */ { hufftab6, 0, 4 },
- /* 7 */ { hufftab7, 0, 4 },
- /* 8 */ { hufftab8, 0, 4 },
- /* 9 */ { hufftab9, 0, 4 },
- /* 10 */ { hufftab10, 0, 4 },
- /* 11 */ { hufftab11, 0, 4 },
- /* 12 */ { hufftab12, 0, 4 },
- /* 13 */ { hufftab13, 0, 4 },
- /* 14 */ { 0 /* not used */ },
- /* 15 */ { hufftab15, 0, 4 },
- /* 16 */ { hufftab16, 1, 4 },
- /* 17 */ { hufftab16, 2, 4 },
- /* 18 */ { hufftab16, 3, 4 },
- /* 19 */ { hufftab16, 4, 4 },
- /* 20 */ { hufftab16, 6, 4 },
- /* 21 */ { hufftab16, 8, 4 },
- /* 22 */ { hufftab16, 10, 4 },
- /* 23 */ { hufftab16, 13, 4 },
- /* 24 */ { hufftab24, 4, 4 },
- /* 25 */ { hufftab24, 5, 4 },
- /* 26 */ { hufftab24, 6, 4 },
- /* 27 */ { hufftab24, 7, 4 },
- /* 28 */ { hufftab24, 8, 4 },
- /* 29 */ { hufftab24, 9, 4 },
- /* 30 */ { hufftab24, 11, 4 },
- /* 31 */ { hufftab24, 13, 4 }
-};
diff --git a/libmad/src/huffman.h b/libmad/src/huffman.h
deleted file mode 100644
index 6325db4..0000000
--- a/libmad/src/huffman.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: huffman.h,v 1.11 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBMAD_HUFFMAN_H
-# define LIBMAD_HUFFMAN_H
-
-union huffquad {
- struct {
- unsigned short final : 1;
- unsigned short bits : 3;
- unsigned short offset : 12;
- } ptr;
- struct {
- unsigned short final : 1;
- unsigned short hlen : 3;
- unsigned short v : 1;
- unsigned short w : 1;
- unsigned short x : 1;
- unsigned short y : 1;
- } value;
- unsigned short final : 1;
-};
-
-union huffpair {
- struct {
- unsigned short final : 1;
- unsigned short bits : 3;
- unsigned short offset : 12;
- } ptr;
- struct {
- unsigned short final : 1;
- unsigned short hlen : 3;
- unsigned short x : 4;
- unsigned short y : 4;
- } value;
- unsigned short final : 1;
-};
-
-struct hufftable {
- union huffpair const *table;
- unsigned short linbits;
- unsigned short startbits;
-};
-
-extern union huffquad const *const mad_huff_quad_table[2];
-extern struct hufftable const mad_huff_pair_table[32];
-
-# endif
diff --git a/libmad/src/imdct_s.dat b/libmad/src/imdct_s.dat
deleted file mode 100644
index 476710e..0000000
--- a/libmad/src/imdct_s.dat
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: imdct_s.dat,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
- /* 0 */ { MAD_F(0x09bd7ca0) /* 0.608761429 */,
- -MAD_F(0x0ec835e8) /* -0.923879533 */,
- -MAD_F(0x0216a2a2) /* -0.130526192 */,
- MAD_F(0x0fdcf549) /* 0.991444861 */,
- -MAD_F(0x061f78aa) /* -0.382683432 */,
- -MAD_F(0x0cb19346) /* -0.793353340 */ },
-
- /* 6 */ { -MAD_F(0x0cb19346) /* -0.793353340 */,
- MAD_F(0x061f78aa) /* 0.382683432 */,
- MAD_F(0x0fdcf549) /* 0.991444861 */,
- MAD_F(0x0216a2a2) /* 0.130526192 */,
- -MAD_F(0x0ec835e8) /* -0.923879533 */,
- -MAD_F(0x09bd7ca0) /* -0.608761429 */ },
-
- /* 1 */ { MAD_F(0x061f78aa) /* 0.382683432 */,
- -MAD_F(0x0ec835e8) /* -0.923879533 */,
- MAD_F(0x0ec835e8) /* 0.923879533 */,
- -MAD_F(0x061f78aa) /* -0.382683432 */,
- -MAD_F(0x061f78aa) /* -0.382683432 */,
- MAD_F(0x0ec835e8) /* 0.923879533 */ },
-
- /* 7 */ { -MAD_F(0x0ec835e8) /* -0.923879533 */,
- -MAD_F(0x061f78aa) /* -0.382683432 */,
- MAD_F(0x061f78aa) /* 0.382683432 */,
- MAD_F(0x0ec835e8) /* 0.923879533 */,
- MAD_F(0x0ec835e8) /* 0.923879533 */,
- MAD_F(0x061f78aa) /* 0.382683432 */ },
-
- /* 2 */ { MAD_F(0x0216a2a2) /* 0.130526192 */,
- -MAD_F(0x061f78aa) /* -0.382683432 */,
- MAD_F(0x09bd7ca0) /* 0.608761429 */,
- -MAD_F(0x0cb19346) /* -0.793353340 */,
- MAD_F(0x0ec835e8) /* 0.923879533 */,
- -MAD_F(0x0fdcf549) /* -0.991444861 */ },
-
- /* 8 */ { -MAD_F(0x0fdcf549) /* -0.991444861 */,
- -MAD_F(0x0ec835e8) /* -0.923879533 */,
- -MAD_F(0x0cb19346) /* -0.793353340 */,
- -MAD_F(0x09bd7ca0) /* -0.608761429 */,
- -MAD_F(0x061f78aa) /* -0.382683432 */,
- -MAD_F(0x0216a2a2) /* -0.130526192 */ }
diff --git a/libmad/src/layer12.c b/libmad/src/layer12.c
deleted file mode 100644
index 62be832..0000000
--- a/libmad/src/layer12.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: layer12.c,v 1.17 2004/02/05 09:02:39 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# ifdef HAVE_LIMITS_H
-# include <limits.h>
-# else
-# define CHAR_BIT 8
-# endif
-
-# include "fixed.h"
-# include "bit.h"
-# include "stream.h"
-# include "frame.h"
-# include "layer12.h"
-
-# ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4244 4018)
-# endif
-
-/*
- * scalefactor table
- * used in both Layer I and Layer II decoding
- */
-static
-mad_fixed_t const sf_table[64] = {
-# include "sf_table.dat"
-};
-
-/* --- Layer I ------------------------------------------------------------- */
-
-/* linear scaling table */
-static
-mad_fixed_t const linear_table[14] = {
- MAD_F(0x15555555), /* 2^2 / (2^2 - 1) == 1.33333333333333 */
- MAD_F(0x12492492), /* 2^3 / (2^3 - 1) == 1.14285714285714 */
- MAD_F(0x11111111), /* 2^4 / (2^4 - 1) == 1.06666666666667 */
- MAD_F(0x10842108), /* 2^5 / (2^5 - 1) == 1.03225806451613 */
- MAD_F(0x10410410), /* 2^6 / (2^6 - 1) == 1.01587301587302 */
- MAD_F(0x10204081), /* 2^7 / (2^7 - 1) == 1.00787401574803 */
- MAD_F(0x10101010), /* 2^8 / (2^8 - 1) == 1.00392156862745 */
- MAD_F(0x10080402), /* 2^9 / (2^9 - 1) == 1.00195694716243 */
- MAD_F(0x10040100), /* 2^10 / (2^10 - 1) == 1.00097751710655 */
- MAD_F(0x10020040), /* 2^11 / (2^11 - 1) == 1.00048851978505 */
- MAD_F(0x10010010), /* 2^12 / (2^12 - 1) == 1.00024420024420 */
- MAD_F(0x10008004), /* 2^13 / (2^13 - 1) == 1.00012208521548 */
- MAD_F(0x10004001), /* 2^14 / (2^14 - 1) == 1.00006103888177 */
- MAD_F(0x10002000) /* 2^15 / (2^15 - 1) == 1.00003051850948 */
-};
-
-/*
- * NAME: I_sample()
- * DESCRIPTION: decode one requantized Layer I sample from a bitstream
- */
-static
-mad_fixed_t I_sample(struct mad_bitptr *ptr, unsigned int nb)
-{
- mad_fixed_t sample;
-
- sample = mad_bit_read(ptr, nb);
-
- /* invert most significant bit, extend sign, then scale to fixed format */
-
- sample ^= 1 << (nb - 1);
- sample |= -(sample & (1 << (nb - 1)));
-
- sample <<= MAD_F_FRACBITS - (nb - 1);
-
- /* requantize the sample */
-
- /* s'' = (2^nb / (2^nb - 1)) * (s''' + 2^(-nb + 1)) */
-
- sample += MAD_F_ONE >> (nb - 1);
-
- return mad_f_mul(sample, linear_table[nb - 2]);
-
- /* s' = factor * s'' */
- /* (to be performed by caller) */
-}
-
-/*
- * NAME: layer->I()
- * DESCRIPTION: decode a single Layer I frame
- */
-int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame)
-{
- struct mad_header *header = &frame->header;
- unsigned int nch, bound, ch, s, sb, nb;
- unsigned char allocation[2][32], scalefactor[2][32];
-
- nch = MAD_NCHANNELS(header);
-
- bound = 32;
- if (header->mode == MAD_MODE_JOINT_STEREO) {
- header->flags |= MAD_FLAG_I_STEREO;
- bound = 4 + header->mode_extension * 4;
- }
-
- /* check CRC word */
-
- if (header->flags & MAD_FLAG_PROTECTION) {
- header->crc_check =
- mad_bit_crc(stream->ptr, 4 * (bound * nch + (32 - bound)),
- header->crc_check);
-
- if (header->crc_check != header->crc_target &&
- !(frame->options & MAD_OPTION_IGNORECRC)) {
- stream->error = MAD_ERROR_BADCRC;
- return -1;
- }
- }
-
- /* decode bit allocations */
-
- for (sb = 0; sb < bound; ++sb) {
- for (ch = 0; ch < nch; ++ch) {
- nb = mad_bit_read(&stream->ptr, 4);
-
- if (nb == 15) {
- stream->error = MAD_ERROR_BADBITALLOC;
- return -1;
- }
-
- allocation[ch][sb] = nb ? nb + 1 : 0;
- }
- }
-
- for (sb = bound; sb < 32; ++sb) {
- nb = mad_bit_read(&stream->ptr, 4);
-
- if (nb == 15) {
- stream->error = MAD_ERROR_BADBITALLOC;
- return -1;
- }
-
- allocation[0][sb] =
- allocation[1][sb] = nb ? nb + 1 : 0;
- }
-
- /* decode scalefactors */
-
- for (sb = 0; sb < 32; ++sb) {
- for (ch = 0; ch < nch; ++ch) {
- if (allocation[ch][sb]) {
- scalefactor[ch][sb] = mad_bit_read(&stream->ptr, 6);
-
-# if defined(OPT_STRICT)
- /*
- * Scalefactor index 63 does not appear in Table B.1 of
- * ISO/IEC 11172-3. Nonetheless, other implementations accept it,
- * so we only reject it if OPT_STRICT is defined.
- */
- if (scalefactor[ch][sb] == 63) {
- stream->error = MAD_ERROR_BADSCALEFACTOR;
- return -1;
- }
-# endif
- }
- }
- }
-
- /* decode samples */
-
- for (s = 0; s < 12; ++s) {
- for (sb = 0; sb < bound; ++sb) {
- for (ch = 0; ch < nch; ++ch) {
- nb = allocation[ch][sb];
- frame->sbsample[ch][s][sb] = nb ?
- mad_f_mul(I_sample(&stream->ptr, nb),
- sf_table[scalefactor[ch][sb]]) : 0;
- }
- }
-
- for (sb = bound; sb < 32; ++sb) {
- if ((nb = allocation[0][sb])) {
- mad_fixed_t sample;
-
- sample = I_sample(&stream->ptr, nb);
-
- for (ch = 0; ch < nch; ++ch) {
- frame->sbsample[ch][s][sb] =
- mad_f_mul(sample, sf_table[scalefactor[ch][sb]]);
- }
- }
- else {
- for (ch = 0; ch < nch; ++ch)
- frame->sbsample[ch][s][sb] = 0;
- }
- }
- }
-
- return 0;
-}
-
-/* --- Layer II ------------------------------------------------------------ */
-
-/* possible quantization per subband table */
-static
-struct {
- unsigned int sblimit;
- unsigned char const offsets[30];
-} const sbquant_table[5] = {
- /* ISO/IEC 11172-3 Table B.2a */
- { 27, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 0 */
- 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 } },
- /* ISO/IEC 11172-3 Table B.2b */
- { 30, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 1 */
- 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0 } },
- /* ISO/IEC 11172-3 Table B.2c */
- { 8, { 5, 5, 2, 2, 2, 2, 2, 2 } }, /* 2 */
- /* ISO/IEC 11172-3 Table B.2d */
- { 12, { 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 } }, /* 3 */
- /* ISO/IEC 13818-3 Table B.1 */
- { 30, { 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, /* 4 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }
-};
-
-/* bit allocation table */
-static
-struct {
- unsigned short nbal;
- unsigned short offset;
-} const bitalloc_table[8] = {
- { 2, 0 }, /* 0 */
- { 2, 3 }, /* 1 */
- { 3, 3 }, /* 2 */
- { 3, 1 }, /* 3 */
- { 4, 2 }, /* 4 */
- { 4, 3 }, /* 5 */
- { 4, 4 }, /* 6 */
- { 4, 5 } /* 7 */
-};
-
-/* offsets into quantization class table */
-static
-unsigned char const offset_table[6][15] = {
- { 0, 1, 16 }, /* 0 */
- { 0, 1, 2, 3, 4, 5, 16 }, /* 1 */
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, /* 2 */
- { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* 3 */
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }, /* 4 */
- { 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } /* 5 */
-};
-
-/* quantization class table */
-static
-struct quantclass {
- unsigned short nlevels;
- unsigned char group;
- unsigned char bits;
- mad_fixed_t C;
- mad_fixed_t D;
-} const qc_table[17] = {
-# include "qc_table.dat"
-};
-
-/*
- * NAME: II_samples()
- * DESCRIPTION: decode three requantized Layer II samples from a bitstream
- */
-static
-void II_samples(struct mad_bitptr *ptr,
- struct quantclass const *quantclass,
- mad_fixed_t output[3])
-{
- unsigned int nb, s, sample[3];
-
- if ((nb = quantclass->group)) {
- unsigned int c, nlevels;
-
- /* degrouping */
- c = mad_bit_read(ptr, quantclass->bits);
- nlevels = quantclass->nlevels;
-
- for (s = 0; s < 3; ++s) {
- sample[s] = c % nlevels;
- c /= nlevels;
- }
- }
- else {
- nb = quantclass->bits;
-
- for (s = 0; s < 3; ++s)
- sample[s] = mad_bit_read(ptr, nb);
- }
-
- for (s = 0; s < 3; ++s) {
- mad_fixed_t requantized;
-
- /* invert most significant bit, extend sign, then scale to fixed format */
-
- requantized = sample[s] ^ (1 << (nb - 1));
- requantized |= -(requantized & (1 << (nb - 1)));
-
- requantized <<= MAD_F_FRACBITS - (nb - 1);
-
- /* requantize the sample */
-
- /* s'' = C * (s''' + D) */
-
- output[s] = mad_f_mul(requantized + quantclass->D, quantclass->C);
-
- /* s' = factor * s'' */
- /* (to be performed by caller) */
- }
-}
-
-/*
- * NAME: layer->II()
- * DESCRIPTION: decode a single Layer II frame
- */
-int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame)
-{
- struct mad_header *header = &frame->header;
- struct mad_bitptr start;
- unsigned int index, sblimit, nbal, nch, bound, gr, ch, s, sb;
- unsigned char const *offsets;
- unsigned char allocation[2][32], scfsi[2][32], scalefactor[2][32][3];
- mad_fixed_t samples[3];
-
- nch = MAD_NCHANNELS(header);
-
- if (header->flags & MAD_FLAG_LSF_EXT)
- index = 4;
- else if (header->flags & MAD_FLAG_FREEFORMAT)
- goto freeformat;
- else {
- unsigned long bitrate_per_channel;
-
- bitrate_per_channel = header->bitrate;
- if (nch == 2) {
- bitrate_per_channel /= 2;
-
-# if defined(OPT_STRICT)
- /*
- * ISO/IEC 11172-3 allows only single channel mode for 32, 48, 56, and
- * 80 kbps bitrates in Layer II, but some encoders ignore this
- * restriction. We enforce it if OPT_STRICT is defined.
- */
- if (bitrate_per_channel <= 28000 || bitrate_per_channel == 40000) {
- stream->error = MAD_ERROR_BADMODE;
- return -1;
- }
-# endif
- }
- else { /* nch == 1 */
- if (bitrate_per_channel > 192000) {
- /*
- * ISO/IEC 11172-3 does not allow single channel mode for 224, 256,
- * 320, or 384 kbps bitrates in Layer II.
- */
- stream->error = MAD_ERROR_BADMODE;
- return -1;
- }
- }
-
- if (bitrate_per_channel <= 48000)
- index = (header->samplerate == 32000) ? 3 : 2;
- else if (bitrate_per_channel <= 80000)
- index = 0;
- else {
- freeformat:
- index = (header->samplerate == 48000) ? 0 : 1;
- }
- }
-
- sblimit = sbquant_table[index].sblimit;
- offsets = sbquant_table[index].offsets;
-
- bound = 32;
- if (header->mode == MAD_MODE_JOINT_STEREO) {
- header->flags |= MAD_FLAG_I_STEREO;
- bound = 4 + header->mode_extension * 4;
- }
-
- if (bound > sblimit)
- bound = sblimit;
-
- start = stream->ptr;
-
- /* decode bit allocations */
-
- for (sb = 0; sb < bound; ++sb) {
- nbal = bitalloc_table[offsets[sb]].nbal;
-
- for (ch = 0; ch < nch; ++ch)
- allocation[ch][sb] = mad_bit_read(&stream->ptr, nbal);
- }
-
- for (sb = bound; sb < sblimit; ++sb) {
- nbal = bitalloc_table[offsets[sb]].nbal;
-
- allocation[0][sb] =
- allocation[1][sb] = mad_bit_read(&stream->ptr, nbal);
- }
-
- /* decode scalefactor selection info */
-
- for (sb = 0; sb < sblimit; ++sb) {
- for (ch = 0; ch < nch; ++ch) {
- if (allocation[ch][sb])
- scfsi[ch][sb] = mad_bit_read(&stream->ptr, 2);
- }
- }
-
- /* check CRC word */
-
- if (header->flags & MAD_FLAG_PROTECTION) {
- header->crc_check =
- mad_bit_crc(start, mad_bit_length(&start, &stream->ptr),
- header->crc_check);
-
- if (header->crc_check != header->crc_target &&
- !(frame->options & MAD_OPTION_IGNORECRC)) {
- stream->error = MAD_ERROR_BADCRC;
- return -1;
- }
- }
-
- /* decode scalefactors */
-
- for (sb = 0; sb < sblimit; ++sb) {
- for (ch = 0; ch < nch; ++ch) {
- if (allocation[ch][sb]) {
- scalefactor[ch][sb][0] = mad_bit_read(&stream->ptr, 6);
-
- switch (scfsi[ch][sb]) {
- case 2:
- scalefactor[ch][sb][2] =
- scalefactor[ch][sb][1] =
- scalefactor[ch][sb][0];
- break;
-
- case 0:
- scalefactor[ch][sb][1] = mad_bit_read(&stream->ptr, 6);
- /* fall through */
-
- case 1:
- case 3:
- scalefactor[ch][sb][2] = mad_bit_read(&stream->ptr, 6);
- }
-
- if (scfsi[ch][sb] & 1)
- scalefactor[ch][sb][1] = scalefactor[ch][sb][scfsi[ch][sb] - 1];
-
-# if defined(OPT_STRICT)
- /*
- * Scalefactor index 63 does not appear in Table B.1 of
- * ISO/IEC 11172-3. Nonetheless, other implementations accept it,
- * so we only reject it if OPT_STRICT is defined.
- */
- if (scalefactor[ch][sb][0] == 63 ||
- scalefactor[ch][sb][1] == 63 ||
- scalefactor[ch][sb][2] == 63) {
- stream->error = MAD_ERROR_BADSCALEFACTOR;
- return -1;
- }
-# endif
- }
- }
- }
-
- /* decode samples */
-
- for (gr = 0; gr < 12; ++gr) {
- for (sb = 0; sb < bound; ++sb) {
- for (ch = 0; ch < nch; ++ch) {
- if ((index = allocation[ch][sb])) {
- index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1];
-
- II_samples(&stream->ptr, &qc_table[index], samples);
-
- for (s = 0; s < 3; ++s) {
- frame->sbsample[ch][3 * gr + s][sb] =
- mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]);
- }
- }
- else {
- for (s = 0; s < 3; ++s)
- frame->sbsample[ch][3 * gr + s][sb] = 0;
- }
- }
- }
-
- for (sb = bound; sb < sblimit; ++sb) {
- if ((index = allocation[0][sb])) {
- index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1];
-
- II_samples(&stream->ptr, &qc_table[index], samples);
-
- for (ch = 0; ch < nch; ++ch) {
- for (s = 0; s < 3; ++s) {
- frame->sbsample[ch][3 * gr + s][sb] =
- mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]);
- }
- }
- }
- else {
- for (ch = 0; ch < nch; ++ch) {
- for (s = 0; s < 3; ++s)
- frame->sbsample[ch][3 * gr + s][sb] = 0;
- }
- }
- }
-
- for (ch = 0; ch < nch; ++ch) {
- for (s = 0; s < 3; ++s) {
- for (sb = sblimit; sb < 32; ++sb)
- frame->sbsample[ch][3 * gr + s][sb] = 0;
- }
- }
- }
-
- return 0;
-}
-
-# ifdef _MSC_VER
-# pragma warning(pop)
-# endif
diff --git a/libmad/src/layer12.h b/libmad/src/layer12.h
deleted file mode 100644
index e1c4996..0000000
--- a/libmad/src/layer12.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: layer12.h,v 1.10 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBMAD_LAYER12_H
-# define LIBMAD_LAYER12_H
-
-# include "stream.h"
-# include "frame.h"
-
-int mad_layer_I(struct mad_stream *, struct mad_frame *);
-int mad_layer_II(struct mad_stream *, struct mad_frame *);
-
-# endif
diff --git a/libmad/src/layer3.c b/libmad/src/layer3.c
deleted file mode 100644
index f92706f..0000000
--- a/libmad/src/layer3.c
+++ /dev/null
@@ -1,2707 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: layer3.c,v 1.43 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-# include <string.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# ifdef HAVE_LIMITS_H
-# include <limits.h>
-# else
-# define CHAR_BIT 8
-# endif
-
-# include "fixed.h"
-# include "bit.h"
-# include "stream.h"
-# include "frame.h"
-# include "huffman.h"
-# include "layer3.h"
-
-# ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4244 4018)
-# endif
-
-/* --- Layer III ----------------------------------------------------------- */
-
-enum {
- count1table_select = 0x01,
- scalefac_scale = 0x02,
- preflag = 0x04,
- mixed_block_flag = 0x08
-};
-
-enum {
- I_STEREO = 0x1,
- MS_STEREO = 0x2
-};
-
-struct sideinfo {
- unsigned int main_data_begin;
- unsigned int private_bits;
-
- unsigned char scfsi[2];
-
- struct granule {
- struct channel {
- /* from side info */
- unsigned short part2_3_length;
- unsigned short big_values;
- unsigned short global_gain;
- unsigned short scalefac_compress;
-
- unsigned char flags;
- unsigned char block_type;
- unsigned char table_select[3];
- unsigned char subblock_gain[3];
- unsigned char region0_count;
- unsigned char region1_count;
-
- /* from main_data */
- unsigned char scalefac[39]; /* scalefac_l and/or scalefac_s */
- } ch[2];
- } gr[2];
-};
-
-/*
- * scalefactor bit lengths
- * derived from section 2.4.2.7 of ISO/IEC 11172-3
- */
-static
-struct {
- unsigned char slen1;
- unsigned char slen2;
-} const sflen_table[16] = {
- { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 },
- { 3, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 },
- { 2, 1 }, { 2, 2 }, { 2, 3 }, { 3, 1 },
- { 3, 2 }, { 3, 3 }, { 4, 2 }, { 4, 3 }
-};
-
-/*
- * number of LSF scalefactor band values
- * derived from section 2.4.3.2 of ISO/IEC 13818-3
- */
-static
-unsigned char const nsfb_table[6][3][4] = {
- { { 6, 5, 5, 5 },
- { 9, 9, 9, 9 },
- { 6, 9, 9, 9 } },
-
- { { 6, 5, 7, 3 },
- { 9, 9, 12, 6 },
- { 6, 9, 12, 6 } },
-
- { { 11, 10, 0, 0 },
- { 18, 18, 0, 0 },
- { 15, 18, 0, 0 } },
-
- { { 7, 7, 7, 0 },
- { 12, 12, 12, 0 },
- { 6, 15, 12, 0 } },
-
- { { 6, 6, 6, 3 },
- { 12, 9, 9, 6 },
- { 6, 12, 9, 6 } },
-
- { { 8, 8, 5, 0 },
- { 15, 12, 9, 0 },
- { 6, 18, 9, 0 } }
-};
-
-/*
- * MPEG-1 scalefactor band widths
- * derived from Table B.8 of ISO/IEC 11172-3
- */
-static
-unsigned char const sfb_48000_long[] = {
- 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10,
- 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192
-};
-
-static
-unsigned char const sfb_44100_long[] = {
- 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10,
- 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158
-};
-
-static
-unsigned char const sfb_32000_long[] = {
- 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12,
- 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26
-};
-
-static
-unsigned char const sfb_48000_short[] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6,
- 6, 6, 6, 6, 6, 10, 10, 10, 12, 12, 12, 14, 14,
- 14, 16, 16, 16, 20, 20, 20, 26, 26, 26, 66, 66, 66
-};
-
-static
-unsigned char const sfb_44100_short[] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6,
- 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 12, 14, 14,
- 14, 18, 18, 18, 22, 22, 22, 30, 30, 30, 56, 56, 56
-};
-
-static
-unsigned char const sfb_32000_short[] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6,
- 6, 6, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 20,
- 20, 26, 26, 26, 34, 34, 34, 42, 42, 42, 12, 12, 12
-};
-
-static
-unsigned char const sfb_48000_mixed[] = {
- /* long */ 4, 4, 4, 4, 4, 4, 6, 6,
- /* short */ 4, 4, 4, 6, 6, 6, 6, 6, 6, 10,
- 10, 10, 12, 12, 12, 14, 14, 14, 16, 16,
- 16, 20, 20, 20, 26, 26, 26, 66, 66, 66
-};
-
-static
-unsigned char const sfb_44100_mixed[] = {
- /* long */ 4, 4, 4, 4, 4, 4, 6, 6,
- /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 10,
- 10, 10, 12, 12, 12, 14, 14, 14, 18, 18,
- 18, 22, 22, 22, 30, 30, 30, 56, 56, 56
-};
-
-static
-unsigned char const sfb_32000_mixed[] = {
- /* long */ 4, 4, 4, 4, 4, 4, 6, 6,
- /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 12,
- 12, 12, 16, 16, 16, 20, 20, 20, 26, 26,
- 26, 34, 34, 34, 42, 42, 42, 12, 12, 12
-};
-
-/*
- * MPEG-2 scalefactor band widths
- * derived from Table B.2 of ISO/IEC 13818-3
- */
-static
-unsigned char const sfb_24000_long[] = {
- 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16,
- 18, 22, 26, 32, 38, 46, 54, 62, 70, 76, 36
-};
-
-static
-unsigned char const sfb_22050_long[] = {
- 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16,
- 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54
-};
-
-# define sfb_16000_long sfb_22050_long
-
-static
-unsigned char const sfb_24000_short[] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8,
- 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18,
- 18, 24, 24, 24, 32, 32, 32, 44, 44, 44, 12, 12, 12
-};
-
-static
-unsigned char const sfb_22050_short[] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6,
- 6, 6, 8, 8, 8, 10, 10, 10, 14, 14, 14, 18, 18,
- 18, 26, 26, 26, 32, 32, 32, 42, 42, 42, 18, 18, 18
-};
-
-static
-unsigned char const sfb_16000_short[] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8,
- 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18,
- 18, 24, 24, 24, 30, 30, 30, 40, 40, 40, 18, 18, 18
-};
-
-static
-unsigned char const sfb_24000_mixed[] = {
- /* long */ 6, 6, 6, 6, 6, 6,
- /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12,
- 12, 12, 14, 14, 14, 18, 18, 18, 24, 24,
- 24, 32, 32, 32, 44, 44, 44, 12, 12, 12
-};
-
-static
-unsigned char const sfb_22050_mixed[] = {
- /* long */ 6, 6, 6, 6, 6, 6,
- /* short */ 6, 6, 6, 6, 6, 6, 8, 8, 8, 10,
- 10, 10, 14, 14, 14, 18, 18, 18, 26, 26,
- 26, 32, 32, 32, 42, 42, 42, 18, 18, 18
-};
-
-static
-unsigned char const sfb_16000_mixed[] = {
- /* long */ 6, 6, 6, 6, 6, 6,
- /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12,
- 12, 12, 14, 14, 14, 18, 18, 18, 24, 24,
- 24, 30, 30, 30, 40, 40, 40, 18, 18, 18
-};
-
-/*
- * MPEG 2.5 scalefactor band widths
- * derived from public sources
- */
-# define sfb_12000_long sfb_16000_long
-# define sfb_11025_long sfb_12000_long
-
-static
-unsigned char const sfb_8000_long[] = {
- 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32,
- 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2
-};
-
-# define sfb_12000_short sfb_16000_short
-# define sfb_11025_short sfb_12000_short
-
-static
-unsigned char const sfb_8000_short[] = {
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 16,
- 16, 16, 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36,
- 36, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26
-};
-
-# define sfb_12000_mixed sfb_16000_mixed
-# define sfb_11025_mixed sfb_12000_mixed
-
-/* the 8000 Hz short block scalefactor bands do not break after
- the first 36 frequency lines, so this is probably wrong */
-static
-unsigned char const sfb_8000_mixed[] = {
- /* long */ 12, 12, 12,
- /* short */ 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16,
- 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36, 36,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26
-};
-
-static
-struct {
- unsigned char const *l;
- unsigned char const *s;
- unsigned char const *m;
-} const sfbwidth_table[9] = {
- { sfb_48000_long, sfb_48000_short, sfb_48000_mixed },
- { sfb_44100_long, sfb_44100_short, sfb_44100_mixed },
- { sfb_32000_long, sfb_32000_short, sfb_32000_mixed },
- { sfb_24000_long, sfb_24000_short, sfb_24000_mixed },
- { sfb_22050_long, sfb_22050_short, sfb_22050_mixed },
- { sfb_16000_long, sfb_16000_short, sfb_16000_mixed },
- { sfb_12000_long, sfb_12000_short, sfb_12000_mixed },
- { sfb_11025_long, sfb_11025_short, sfb_11025_mixed },
- { sfb_8000_long, sfb_8000_short, sfb_8000_mixed }
-};
-
-/*
- * scalefactor band preemphasis (used only when preflag is set)
- * derived from Table B.6 of ISO/IEC 11172-3
- */
-static
-unsigned char const pretab[22] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0
-};
-
-/*
- * table for requantization
- *
- * rq_table[x].mantissa * 2^(rq_table[x].exponent) = x^(4/3)
- */
-static
-struct fixedfloat {
- unsigned long mantissa : 27;
- unsigned short exponent : 5;
-} const rq_table[8207] = {
-# include "rq_table.dat"
-};
-
-/*
- * fractional powers of two
- * used for requantization and joint stereo decoding
- *
- * root_table[3 + x] = 2^(x/4)
- */
-static
-mad_fixed_t const root_table[7] = {
- MAD_F(0x09837f05) /* 2^(-3/4) == 0.59460355750136 */,
- MAD_F(0x0b504f33) /* 2^(-2/4) == 0.70710678118655 */,
- MAD_F(0x0d744fcd) /* 2^(-1/4) == 0.84089641525371 */,
- MAD_F(0x10000000) /* 2^( 0/4) == 1.00000000000000 */,
- MAD_F(0x1306fe0a) /* 2^(+1/4) == 1.18920711500272 */,
- MAD_F(0x16a09e66) /* 2^(+2/4) == 1.41421356237310 */,
- MAD_F(0x1ae89f99) /* 2^(+3/4) == 1.68179283050743 */
-};
-
-/*
- * coefficients for aliasing reduction
- * derived from Table B.9 of ISO/IEC 11172-3
- *
- * c[] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 }
- * cs[i] = 1 / sqrt(1 + c[i]^2)
- * ca[i] = c[i] / sqrt(1 + c[i]^2)
- */
-static
-mad_fixed_t const cs[8] = {
- +MAD_F(0x0db84a81) /* +0.857492926 */, +MAD_F(0x0e1b9d7f) /* +0.881741997 */,
- +MAD_F(0x0f31adcf) /* +0.949628649 */, +MAD_F(0x0fbba815) /* +0.983314592 */,
- +MAD_F(0x0feda417) /* +0.995517816 */, +MAD_F(0x0ffc8fc8) /* +0.999160558 */,
- +MAD_F(0x0fff964c) /* +0.999899195 */, +MAD_F(0x0ffff8d3) /* +0.999993155 */
-};
-
-static
-mad_fixed_t const ca[8] = {
- -MAD_F(0x083b5fe7) /* -0.514495755 */, -MAD_F(0x078c36d2) /* -0.471731969 */,
- -MAD_F(0x05039814) /* -0.313377454 */, -MAD_F(0x02e91dd1) /* -0.181913200 */,
- -MAD_F(0x0183603a) /* -0.094574193 */, -MAD_F(0x00a7cb87) /* -0.040965583 */,
- -MAD_F(0x003a2847) /* -0.014198569 */, -MAD_F(0x000f27b4) /* -0.003699975 */
-};
-
-/*
- * IMDCT coefficients for short blocks
- * derived from section 2.4.3.4.10.2 of ISO/IEC 11172-3
- *
- * imdct_s[i/even][k] = cos((PI / 24) * (2 * (i / 2) + 7) * (2 * k + 1))
- * imdct_s[i /odd][k] = cos((PI / 24) * (2 * (6 + (i-1)/2) + 7) * (2 * k + 1))
- */
-static
-mad_fixed_t const imdct_s[6][6] = {
-# include "imdct_s.dat"
-};
-
-# if !defined(ASO_IMDCT)
-/*
- * windowing coefficients for long blocks
- * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3
- *
- * window_l[i] = sin((PI / 36) * (i + 1/2))
- */
-static
-mad_fixed_t const window_l[36] = {
- MAD_F(0x00b2aa3e) /* 0.043619387 */, MAD_F(0x0216a2a2) /* 0.130526192 */,
- MAD_F(0x03768962) /* 0.216439614 */, MAD_F(0x04cfb0e2) /* 0.300705800 */,
- MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x07635284) /* 0.461748613 */,
- MAD_F(0x0898c779) /* 0.537299608 */, MAD_F(0x09bd7ca0) /* 0.608761429 */,
- MAD_F(0x0acf37ad) /* 0.675590208 */, MAD_F(0x0bcbe352) /* 0.737277337 */,
- MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x0d7e8807) /* 0.843391446 */,
-
- MAD_F(0x0e313245) /* 0.887010833 */, MAD_F(0x0ec835e8) /* 0.923879533 */,
- MAD_F(0x0f426cb5) /* 0.953716951 */, MAD_F(0x0f9ee890) /* 0.976296007 */,
- MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ffc19fd) /* 0.999048222 */,
- MAD_F(0x0ffc19fd) /* 0.999048222 */, MAD_F(0x0fdcf549) /* 0.991444861 */,
- MAD_F(0x0f9ee890) /* 0.976296007 */, MAD_F(0x0f426cb5) /* 0.953716951 */,
- MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0e313245) /* 0.887010833 */,
-
- MAD_F(0x0d7e8807) /* 0.843391446 */, MAD_F(0x0cb19346) /* 0.793353340 */,
- MAD_F(0x0bcbe352) /* 0.737277337 */, MAD_F(0x0acf37ad) /* 0.675590208 */,
- MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0898c779) /* 0.537299608 */,
- MAD_F(0x07635284) /* 0.461748613 */, MAD_F(0x061f78aa) /* 0.382683432 */,
- MAD_F(0x04cfb0e2) /* 0.300705800 */, MAD_F(0x03768962) /* 0.216439614 */,
- MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x00b2aa3e) /* 0.043619387 */,
-};
-# endif /* ASO_IMDCT */
-
-/*
- * windowing coefficients for short blocks
- * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3
- *
- * window_s[i] = sin((PI / 12) * (i + 1/2))
- */
-static
-mad_fixed_t const window_s[12] = {
- MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x061f78aa) /* 0.382683432 */,
- MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0cb19346) /* 0.793353340 */,
- MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0fdcf549) /* 0.991444861 */,
- MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ec835e8) /* 0.923879533 */,
- MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x09bd7ca0) /* 0.608761429 */,
- MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x0216a2a2) /* 0.130526192 */,
-};
-
-/*
- * coefficients for intensity stereo processing
- * derived from section 2.4.3.4.9.3 of ISO/IEC 11172-3
- *
- * is_ratio[i] = tan(i * (PI / 12))
- * is_table[i] = is_ratio[i] / (1 + is_ratio[i])
- */
-static
-mad_fixed_t const is_table[7] = {
- MAD_F(0x00000000) /* 0.000000000 */,
- MAD_F(0x0361962f) /* 0.211324865 */,
- MAD_F(0x05db3d74) /* 0.366025404 */,
- MAD_F(0x08000000) /* 0.500000000 */,
- MAD_F(0x0a24c28c) /* 0.633974596 */,
- MAD_F(0x0c9e69d1) /* 0.788675135 */,
- MAD_F(0x10000000) /* 1.000000000 */
-};
-
-/*
- * coefficients for LSF intensity stereo processing
- * derived from section 2.4.3.2 of ISO/IEC 13818-3
- *
- * is_lsf_table[0][i] = (1 / sqrt(sqrt(2)))^(i + 1)
- * is_lsf_table[1][i] = (1 / sqrt(2)) ^(i + 1)
- */
-static
-mad_fixed_t const is_lsf_table[2][15] = {
- {
- MAD_F(0x0d744fcd) /* 0.840896415 */,
- MAD_F(0x0b504f33) /* 0.707106781 */,
- MAD_F(0x09837f05) /* 0.594603558 */,
- MAD_F(0x08000000) /* 0.500000000 */,
- MAD_F(0x06ba27e6) /* 0.420448208 */,
- MAD_F(0x05a8279a) /* 0.353553391 */,
- MAD_F(0x04c1bf83) /* 0.297301779 */,
- MAD_F(0x04000000) /* 0.250000000 */,
- MAD_F(0x035d13f3) /* 0.210224104 */,
- MAD_F(0x02d413cd) /* 0.176776695 */,
- MAD_F(0x0260dfc1) /* 0.148650889 */,
- MAD_F(0x02000000) /* 0.125000000 */,
- MAD_F(0x01ae89fa) /* 0.105112052 */,
- MAD_F(0x016a09e6) /* 0.088388348 */,
- MAD_F(0x01306fe1) /* 0.074325445 */
- }, {
- MAD_F(0x0b504f33) /* 0.707106781 */,
- MAD_F(0x08000000) /* 0.500000000 */,
- MAD_F(0x05a8279a) /* 0.353553391 */,
- MAD_F(0x04000000) /* 0.250000000 */,
- MAD_F(0x02d413cd) /* 0.176776695 */,
- MAD_F(0x02000000) /* 0.125000000 */,
- MAD_F(0x016a09e6) /* 0.088388348 */,
- MAD_F(0x01000000) /* 0.062500000 */,
- MAD_F(0x00b504f3) /* 0.044194174 */,
- MAD_F(0x00800000) /* 0.031250000 */,
- MAD_F(0x005a827a) /* 0.022097087 */,
- MAD_F(0x00400000) /* 0.015625000 */,
- MAD_F(0x002d413d) /* 0.011048543 */,
- MAD_F(0x00200000) /* 0.007812500 */,
- MAD_F(0x0016a09e) /* 0.005524272 */
- }
-};
-
-/*
- * NAME: III_sideinfo()
- * DESCRIPTION: decode frame side information from a bitstream
- */
-static
-enum mad_error III_sideinfo(struct mad_bitptr *ptr, unsigned int nch,
- int lsf, struct sideinfo *si,
- unsigned int *data_bitlen,
- unsigned int *priv_bitlen)
-{
- unsigned int ngr, gr, ch, i;
- enum mad_error result = MAD_ERROR_NONE;
-
- *data_bitlen = 0;
- *priv_bitlen = lsf ? ((nch == 1) ? 1 : 2) : ((nch == 1) ? 5 : 3);
-
- si->main_data_begin = mad_bit_read(ptr, lsf ? 8 : 9);
- si->private_bits = mad_bit_read(ptr, *priv_bitlen);
-
- ngr = 1;
- if (!lsf) {
- ngr = 2;
-
- for (ch = 0; ch < nch; ++ch)
- si->scfsi[ch] = mad_bit_read(ptr, 4);
- }
-
- for (gr = 0; gr < ngr; ++gr) {
- struct granule *granule = &si->gr[gr];
-
- for (ch = 0; ch < nch; ++ch) {
- struct channel *channel = &granule->ch[ch];
-
- channel->part2_3_length = mad_bit_read(ptr, 12);
- channel->big_values = mad_bit_read(ptr, 9);
- channel->global_gain = mad_bit_read(ptr, 8);
- channel->scalefac_compress = mad_bit_read(ptr, lsf ? 9 : 4);
-
- *data_bitlen += channel->part2_3_length;
-
- if (channel->big_values > 288 && result == 0)
- result = MAD_ERROR_BADBIGVALUES;
-
- channel->flags = 0;
-
- /* window_switching_flag */
- if (mad_bit_read(ptr, 1)) {
- channel->block_type = mad_bit_read(ptr, 2);
-
- if (channel->block_type == 0 && result == 0)
- result = MAD_ERROR_BADBLOCKTYPE;
-
- if (!lsf && channel->block_type == 2 && si->scfsi[ch] && result == 0)
- result = MAD_ERROR_BADSCFSI;
-
- channel->region0_count = 7;
- channel->region1_count = 36;
-
- if (mad_bit_read(ptr, 1))
- channel->flags |= mixed_block_flag;
- else if (channel->block_type == 2)
- channel->region0_count = 8;
-
- for (i = 0; i < 2; ++i)
- channel->table_select[i] = mad_bit_read(ptr, 5);
-
-# if defined(DEBUG)
- channel->table_select[2] = 4; /* not used */
-# endif
-
- for (i = 0; i < 3; ++i)
- channel->subblock_gain[i] = mad_bit_read(ptr, 3);
- }
- else {
- channel->block_type = 0;
-
- for (i = 0; i < 3; ++i)
- channel->table_select[i] = mad_bit_read(ptr, 5);
-
- channel->region0_count = mad_bit_read(ptr, 4);
- channel->region1_count = mad_bit_read(ptr, 3);
- }
-
- /* [preflag,] scalefac_scale, count1table_select */
- channel->flags |= mad_bit_read(ptr, lsf ? 2 : 3);
- }
- }
-
- return result;
-}
-
-/*
- * NAME: III_scalefactors_lsf()
- * DESCRIPTION: decode channel scalefactors for LSF from a bitstream
- */
-static
-unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr,
- struct channel *channel,
- struct channel *gr1ch, int mode_extension)
-{
- struct mad_bitptr start;
- unsigned int scalefac_compress, index, slen[4], part, n, i;
- unsigned char const *nsfb;
-
- start = *ptr;
-
- scalefac_compress = channel->scalefac_compress;
- index = (channel->block_type == 2) ?
- ((channel->flags & mixed_block_flag) ? 2 : 1) : 0;
-
- if (!((mode_extension & I_STEREO) && gr1ch)) {
- if (scalefac_compress < 400) {
- slen[0] = (scalefac_compress >> 4) / 5;
- slen[1] = (scalefac_compress >> 4) % 5;
- slen[2] = (scalefac_compress % 16) >> 2;
- slen[3] = scalefac_compress % 4;
-
- nsfb = nsfb_table[0][index];
- }
- else if (scalefac_compress < 500) {
- scalefac_compress -= 400;
-
- slen[0] = (scalefac_compress >> 2) / 5;
- slen[1] = (scalefac_compress >> 2) % 5;
- slen[2] = scalefac_compress % 4;
- slen[3] = 0;
-
- nsfb = nsfb_table[1][index];
- }
- else {
- scalefac_compress -= 500;
-
- slen[0] = scalefac_compress / 3;
- slen[1] = scalefac_compress % 3;
- slen[2] = 0;
- slen[3] = 0;
-
- channel->flags |= preflag;
-
- nsfb = nsfb_table[2][index];
- }
-
- n = 0;
- for (part = 0; part < 4; ++part) {
- for (i = 0; i < nsfb[part]; ++i)
- channel->scalefac[n++] = mad_bit_read(ptr, slen[part]);
- }
-
- while (n < 39)
- channel->scalefac[n++] = 0;
- }
- else { /* (mode_extension & I_STEREO) && gr1ch (i.e. ch == 1) */
- scalefac_compress >>= 1;
-
- if (scalefac_compress < 180) {
- slen[0] = scalefac_compress / 36;
- slen[1] = (scalefac_compress % 36) / 6;
- slen[2] = (scalefac_compress % 36) % 6;
- slen[3] = 0;
-
- nsfb = nsfb_table[3][index];
- }
- else if (scalefac_compress < 244) {
- scalefac_compress -= 180;
-
- slen[0] = (scalefac_compress % 64) >> 4;
- slen[1] = (scalefac_compress % 16) >> 2;
- slen[2] = scalefac_compress % 4;
- slen[3] = 0;
-
- nsfb = nsfb_table[4][index];
- }
- else {
- scalefac_compress -= 244;
-
- slen[0] = scalefac_compress / 3;
- slen[1] = scalefac_compress % 3;
- slen[2] = 0;
- slen[3] = 0;
-
- nsfb = nsfb_table[5][index];
- }
-
- n = 0;
- for (part = 0; part < 4; ++part) {
- unsigned int max, is_pos;
-
- max = (1 << slen[part]) - 1;
-
- for (i = 0; i < nsfb[part]; ++i) {
- is_pos = mad_bit_read(ptr, slen[part]);
-
- channel->scalefac[n] = is_pos;
- gr1ch->scalefac[n++] = (is_pos == max);
- }
- }
-
- while (n < 39) {
- channel->scalefac[n] = 0;
- gr1ch->scalefac[n++] = 0; /* apparently not illegal */
- }
- }
-
- return mad_bit_length(&start, ptr);
-}
-
-/*
- * NAME: III_scalefactors()
- * DESCRIPTION: decode channel scalefactors of one granule from a bitstream
- */
-static
-unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel,
- struct channel const *gr0ch, unsigned int scfsi)
-{
- struct mad_bitptr start;
- unsigned int slen1, slen2, sfbi;
-
- start = *ptr;
-
- slen1 = sflen_table[channel->scalefac_compress].slen1;
- slen2 = sflen_table[channel->scalefac_compress].slen2;
-
- if (channel->block_type == 2) {
- unsigned int nsfb;
-
- sfbi = 0;
-
- nsfb = (channel->flags & mixed_block_flag) ? 8 + 3 * 3 : 6 * 3;
- while (nsfb--)
- channel->scalefac[sfbi++] = mad_bit_read(ptr, slen1);
-
- nsfb = 6 * 3;
- while (nsfb--)
- channel->scalefac[sfbi++] = mad_bit_read(ptr, slen2);
-
- nsfb = 1 * 3;
- while (nsfb--)
- channel->scalefac[sfbi++] = 0;
- }
- else { /* channel->block_type != 2 */
- if (scfsi & 0x8) {
- for (sfbi = 0; sfbi < 6; ++sfbi)
- channel->scalefac[sfbi] = gr0ch->scalefac[sfbi];
- }
- else {
- for (sfbi = 0; sfbi < 6; ++sfbi)
- channel->scalefac[sfbi] = mad_bit_read(ptr, slen1);
- }
-
- if (scfsi & 0x4) {
- for (sfbi = 6; sfbi < 11; ++sfbi)
- channel->scalefac[sfbi] = gr0ch->scalefac[sfbi];
- }
- else {
- for (sfbi = 6; sfbi < 11; ++sfbi)
- channel->scalefac[sfbi] = mad_bit_read(ptr, slen1);
- }
-
- if (scfsi & 0x2) {
- for (sfbi = 11; sfbi < 16; ++sfbi)
- channel->scalefac[sfbi] = gr0ch->scalefac[sfbi];
- }
- else {
- for (sfbi = 11; sfbi < 16; ++sfbi)
- channel->scalefac[sfbi] = mad_bit_read(ptr, slen2);
- }
-
- if (scfsi & 0x1) {
- for (sfbi = 16; sfbi < 21; ++sfbi)
- channel->scalefac[sfbi] = gr0ch->scalefac[sfbi];
- }
- else {
- for (sfbi = 16; sfbi < 21; ++sfbi)
- channel->scalefac[sfbi] = mad_bit_read(ptr, slen2);
- }
-
- channel->scalefac[21] = 0;
- }
-
- return mad_bit_length(&start, ptr);
-}
-
-/*
- * The Layer III formula for requantization and scaling is defined by
- * section 2.4.3.4.7.1 of ISO/IEC 11172-3, as follows:
- *
- * long blocks:
- * xr[i] = sign(is[i]) * abs(is[i])^(4/3) *
- * 2^((1/4) * (global_gain - 210)) *
- * 2^-(scalefac_multiplier *
- * (scalefac_l[sfb] + preflag * pretab[sfb]))
- *
- * short blocks:
- * xr[i] = sign(is[i]) * abs(is[i])^(4/3) *
- * 2^((1/4) * (global_gain - 210 - 8 * subblock_gain[w])) *
- * 2^-(scalefac_multiplier * scalefac_s[sfb][w])
- *
- * where:
- * scalefac_multiplier = (scalefac_scale + 1) / 2
- *
- * The routines III_exponents() and III_requantize() facilitate this
- * calculation.
- */
-
-/*
- * NAME: III_exponents()
- * DESCRIPTION: calculate scalefactor exponents
- */
-static
-void III_exponents(struct channel const *channel,
- unsigned char const *sfbwidth, signed int exponents[39])
-{
- signed int gain;
- unsigned int scalefac_multiplier, sfbi;
-
- gain = (signed int) channel->global_gain - 210;
- scalefac_multiplier = (channel->flags & scalefac_scale) ? 2 : 1;
-
- if (channel->block_type == 2) {
- unsigned int l;
- signed int gain0, gain1, gain2;
-
- sfbi = l = 0;
-
- if (channel->flags & mixed_block_flag) {
- unsigned int premask;
-
- premask = (channel->flags & preflag) ? ~0 : 0;
-
- /* long block subbands 0-1 */
-
- while (l < 36) {
- exponents[sfbi] = gain -
- (signed int) ((channel->scalefac[sfbi] + (pretab[sfbi] & premask)) <<
- scalefac_multiplier);
-
- l += sfbwidth[sfbi++];
- }
- }
-
- /* this is probably wrong for 8000 Hz short/mixed blocks */
-
- gain0 = gain - 8 * (signed int) channel->subblock_gain[0];
- gain1 = gain - 8 * (signed int) channel->subblock_gain[1];
- gain2 = gain - 8 * (signed int) channel->subblock_gain[2];
-
- while (l < 576) {
- exponents[sfbi + 0] = gain0 -
- (signed int) (channel->scalefac[sfbi + 0] << scalefac_multiplier);
- exponents[sfbi + 1] = gain1 -
- (signed int) (channel->scalefac[sfbi + 1] << scalefac_multiplier);
- exponents[sfbi + 2] = gain2 -
- (signed int) (channel->scalefac[sfbi + 2] << scalefac_multiplier);
-
- l += 3 * sfbwidth[sfbi];
- sfbi += 3;
- }
- }
- else { /* channel->block_type != 2 */
- if (channel->flags & preflag) {
- for (sfbi = 0; sfbi < 22; ++sfbi) {
- exponents[sfbi] = gain -
- (signed int) ((channel->scalefac[sfbi] + pretab[sfbi]) <<
- scalefac_multiplier);
- }
- }
- else {
- for (sfbi = 0; sfbi < 22; ++sfbi) {
- exponents[sfbi] = gain -
- (signed int) (channel->scalefac[sfbi] << scalefac_multiplier);
- }
- }
- }
-}
-
-/*
- * NAME: III_requantize()
- * DESCRIPTION: requantize one (positive) value
- */
-static
-mad_fixed_t III_requantize(unsigned int value, signed int exp)
-{
- mad_fixed_t requantized;
- signed int frac;
- struct fixedfloat const *power;
-
- frac = exp % 4; /* assumes sign(frac) == sign(exp) */
- exp /= 4;
-
- power = &rq_table[value];
- requantized = power->mantissa;
- exp += power->exponent;
-
- if (exp < 0) {
- if (-exp >= sizeof(mad_fixed_t) * CHAR_BIT) {
- /* underflow */
- requantized = 0;
- }
- else {
- requantized += 1L << (-exp - 1);
- requantized >>= -exp;
- }
- }
- else {
- if (exp >= 5) {
- /* overflow */
-# if defined(DEBUG)
- fprintf(stderr, "requantize overflow (%f * 2^%d)\n",
- mad_f_todouble(requantized), exp);
-# endif
- requantized = MAD_F_MAX;
- }
- else
- requantized <<= exp;
- }
-
- return frac ? mad_f_mul(requantized, root_table[3 + frac]) : requantized;
-}
-
-/* we must take care that sz >= bits and sz < sizeof(long) lest bits == 0 */
-# define MASK(cache, sz, bits) \
- (((cache) >> ((sz) - (bits))) & ((1 << (bits)) - 1))
-# define MASK1BIT(cache, sz) \
- ((cache) & (1 << ((sz) - 1)))
-
-/*
- * NAME: III_huffdecode()
- * DESCRIPTION: decode Huffman code words of one channel of one granule
- */
-static
-enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576],
- struct channel *channel,
- unsigned char const *sfbwidth,
- unsigned int part2_length)
-{
- signed int exponents[39], exp;
- signed int const *expptr;
- struct mad_bitptr peek;
- signed int bits_left, cachesz;
- register mad_fixed_t *xrptr;
- mad_fixed_t const *sfbound;
- register unsigned long bitcache;
-
- bits_left = (signed) channel->part2_3_length - (signed) part2_length;
- if (bits_left < 0)
- return MAD_ERROR_BADPART3LEN;
-
- III_exponents(channel, sfbwidth, exponents);
-
- peek = *ptr;
- mad_bit_skip(ptr, bits_left);
-
- /* align bit reads to byte boundaries */
- cachesz = mad_bit_bitsleft(&peek);
- cachesz += ((32 - 1 - 24) + (24 - cachesz)) & ~7;
-
- bitcache = mad_bit_read(&peek, cachesz);
- bits_left -= cachesz;
-
- xrptr = &xr[0];
-
- /* big_values */
- {
- unsigned int region, rcount;
- struct hufftable const *entry;
- union huffpair const *table;
- unsigned int linbits, startbits, big_values, reqhits;
- mad_fixed_t reqcache[16];
-
- sfbound = xrptr + *sfbwidth++;
- rcount = channel->region0_count + 1;
-
- entry = &mad_huff_pair_table[channel->table_select[region = 0]];
- table = entry->table;
- linbits = entry->linbits;
- startbits = entry->startbits;
-
- if (table == 0)
- return MAD_ERROR_BADHUFFTABLE;
-
- expptr = &exponents[0];
- exp = *expptr++;
- reqhits = 0;
-
- big_values = channel->big_values;
-
- while (big_values-- && cachesz + bits_left > 0) {
- union huffpair const *pair;
- unsigned int clumpsz, value;
- register mad_fixed_t requantized;
-
- if (xrptr == sfbound) {
- sfbound += *sfbwidth++;
-
- /* change table if region boundary */
-
- if (--rcount == 0) {
- if (region == 0)
- rcount = channel->region1_count + 1;
- else
- rcount = 0; /* all remaining */
-
- entry = &mad_huff_pair_table[channel->table_select[++region]];
- table = entry->table;
- linbits = entry->linbits;
- startbits = entry->startbits;
-
- if (table == 0)
- return MAD_ERROR_BADHUFFTABLE;
- }
-
- if (exp != *expptr) {
- exp = *expptr;
- reqhits = 0;
- }
-
- ++expptr;
- }
-
- if (cachesz < 21) {
- unsigned int bits;
-
- bits = ((32 - 1 - 21) + (21 - cachesz)) & ~7;
- bitcache = (bitcache << bits) | mad_bit_read(&peek, bits);
- cachesz += bits;
- bits_left -= bits;
- }
-
- /* hcod (0..19) */
-
- clumpsz = startbits;
- pair = &table[MASK(bitcache, cachesz, clumpsz)];
-
- while (!pair->final) {
- cachesz -= clumpsz;
-
- clumpsz = pair->ptr.bits;
- pair = &table[pair->ptr.offset + MASK(bitcache, cachesz, clumpsz)];
- }
-
- cachesz -= pair->value.hlen;
-
- if (linbits) {
- /* x (0..14) */
-
- value = pair->value.x;
-
- switch (value) {
- case 0:
- xrptr[0] = 0;
- break;
-
- case 15:
- if (cachesz < linbits + 2) {
- bitcache = (bitcache << 16) | mad_bit_read(&peek, 16);
- cachesz += 16;
- bits_left -= 16;
- }
-
- value += MASK(bitcache, cachesz, linbits);
- cachesz -= linbits;
-
- requantized = III_requantize(value, exp);
- goto x_final;
-
- default:
- if (reqhits & (1 << value))
- requantized = reqcache[value];
- else {
- reqhits |= (1 << value);
- requantized = reqcache[value] = III_requantize(value, exp);
- }
-
- x_final:
- xrptr[0] = MASK1BIT(bitcache, cachesz--) ?
- -requantized : requantized;
- }
-
- /* y (0..14) */
-
- value = pair->value.y;
-
- switch (value) {
- case 0:
- xrptr[1] = 0;
- break;
-
- case 15:
- if (cachesz < linbits + 1) {
- bitcache = (bitcache << 16) | mad_bit_read(&peek, 16);
- cachesz += 16;
- bits_left -= 16;
- }
-
- value += MASK(bitcache, cachesz, linbits);
- cachesz -= linbits;
-
- requantized = III_requantize(value, exp);
- goto y_final;
-
- default:
- if (reqhits & (1 << value))
- requantized = reqcache[value];
- else {
- reqhits |= (1 << value);
- requantized = reqcache[value] = III_requantize(value, exp);
- }
-
- y_final:
- xrptr[1] = MASK1BIT(bitcache, cachesz--) ?
- -requantized : requantized;
- }
- }
- else {
- /* x (0..1) */
-
- value = pair->value.x;
-
- if (value == 0)
- xrptr[0] = 0;
- else {
- if (reqhits & (1 << value))
- requantized = reqcache[value];
- else {
- reqhits |= (1 << value);
- requantized = reqcache[value] = III_requantize(value, exp);
- }
-
- xrptr[0] = MASK1BIT(bitcache, cachesz--) ?
- -requantized : requantized;
- }
-
- /* y (0..1) */
-
- value = pair->value.y;
-
- if (value == 0)
- xrptr[1] = 0;
- else {
- if (reqhits & (1 << value))
- requantized = reqcache[value];
- else {
- reqhits |= (1 << value);
- requantized = reqcache[value] = III_requantize(value, exp);
- }
-
- xrptr[1] = MASK1BIT(bitcache, cachesz--) ?
- -requantized : requantized;
- }
- }
-
- xrptr += 2;
- }
- }
-
- if (cachesz + bits_left < 0)
- return MAD_ERROR_BADHUFFDATA; /* big_values overrun */
-
- /* count1 */
- {
- union huffquad const *table;
- register mad_fixed_t requantized;
-
- table = mad_huff_quad_table[channel->flags & count1table_select];
-
- requantized = III_requantize(1, exp);
-
- while (cachesz + bits_left > 0 && xrptr <= &xr[572]) {
- union huffquad const *quad;
-
- /* hcod (1..6) */
-
- if (cachesz < 10) {
- bitcache = (bitcache << 16) | mad_bit_read(&peek, 16);
- cachesz += 16;
- bits_left -= 16;
- }
-
- quad = &table[MASK(bitcache, cachesz, 4)];
-
- /* quad tables guaranteed to have at most one extra lookup */
- if (!quad->final) {
- cachesz -= 4;
-
- quad = &table[quad->ptr.offset +
- MASK(bitcache, cachesz, quad->ptr.bits)];
- }
-
- cachesz -= quad->value.hlen;
-
- if (xrptr == sfbound) {
- sfbound += *sfbwidth++;
-
- if (exp != *expptr) {
- exp = *expptr;
- requantized = III_requantize(1, exp);
- }
-
- ++expptr;
- }
-
- /* v (0..1) */
-
- xrptr[0] = quad->value.v ?
- (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0;
-
- /* w (0..1) */
-
- xrptr[1] = quad->value.w ?
- (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0;
-
- xrptr += 2;
-
- if (xrptr == sfbound) {
- sfbound += *sfbwidth++;
-
- if (exp != *expptr) {
- exp = *expptr;
- requantized = III_requantize(1, exp);
- }
-
- ++expptr;
- }
-
- /* x (0..1) */
-
- xrptr[0] = quad->value.x ?
- (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0;
-
- /* y (0..1) */
-
- xrptr[1] = quad->value.y ?
- (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0;
-
- xrptr += 2;
- }
-
- if (cachesz + bits_left < 0) {
-# if 0 && defined(DEBUG)
- fprintf(stderr, "huffman count1 overrun (%d bits)\n",
- -(cachesz + bits_left));
-# endif
-
- /* technically the bitstream is misformatted, but apparently
- some encoders are just a bit sloppy with stuffing bits */
-
- xrptr -= 4;
- }
- }
-
- assert(-bits_left <= MAD_BUFFER_GUARD * CHAR_BIT);
-
-# if 0 && defined(DEBUG)
- if (bits_left < 0)
- fprintf(stderr, "read %d bits too many\n", -bits_left);
- else if (cachesz + bits_left > 0)
- fprintf(stderr, "%d stuffing bits\n", cachesz + bits_left);
-# endif
-
- /* rzero */
- while (xrptr < &xr[576]) {
- xrptr[0] = 0;
- xrptr[1] = 0;
-
- xrptr += 2;
- }
-
- return MAD_ERROR_NONE;
-}
-
-# undef MASK
-# undef MASK1BIT
-
-/*
- * NAME: III_reorder()
- * DESCRIPTION: reorder frequency lines of a short block into subband order
- */
-static
-void III_reorder(mad_fixed_t xr[576], struct channel const *channel,
- unsigned char const sfbwidth[39])
-{
- mad_fixed_t tmp[32][3][6];
- unsigned int sb, l, f, w, sbw[3], sw[3];
-
- /* this is probably wrong for 8000 Hz mixed blocks */
-
- sb = 0;
- if (channel->flags & mixed_block_flag) {
- sb = 2;
-
- l = 0;
- while (l < 36)
- l += *sfbwidth++;
- }
-
- for (w = 0; w < 3; ++w) {
- sbw[w] = sb;
- sw[w] = 0;
- }
-
- f = *sfbwidth++;
- w = 0;
-
- for (l = 18 * sb; l < 576; ++l) {
- if (f-- == 0) {
- f = *sfbwidth++ - 1;
- w = (w + 1) % 3;
- }
-
- tmp[sbw[w]][w][sw[w]++] = xr[l];
-
- if (sw[w] == 6) {
- sw[w] = 0;
- ++sbw[w];
- }
- }
-
- memcpy(&xr[18 * sb], &tmp[sb], (576 - 18 * sb) * sizeof(mad_fixed_t));
-}
-
-/*
- * NAME: III_stereo()
- * DESCRIPTION: perform joint stereo processing on a granule
- */
-static
-enum mad_error III_stereo(mad_fixed_t xr[2][576],
- struct granule const *granule,
- struct mad_header *header,
- unsigned char const *sfbwidth)
-{
- short modes[39];
- unsigned int sfbi, l, n, i;
-
- if (granule->ch[0].block_type !=
- granule->ch[1].block_type ||
- (granule->ch[0].flags & mixed_block_flag) !=
- (granule->ch[1].flags & mixed_block_flag))
- return MAD_ERROR_BADSTEREO;
-
- for (i = 0; i < 39; ++i)
- modes[i] = header->mode_extension;
-
- /* intensity stereo */
-
- if (header->mode_extension & I_STEREO) {
- struct channel const *right_ch = &granule->ch[1];
- mad_fixed_t const *right_xr = xr[1];
- unsigned int is_pos;
-
- header->flags |= MAD_FLAG_I_STEREO;
-
- /* first determine which scalefactor bands are to be processed */
-
- if (right_ch->block_type == 2) {
- unsigned int lower, start, max, bound[3], w;
-
- lower = start = max = bound[0] = bound[1] = bound[2] = 0;
-
- sfbi = l = 0;
-
- if (right_ch->flags & mixed_block_flag) {
- while (l < 36) {
- n = sfbwidth[sfbi++];
-
- for (i = 0; i < n; ++i) {
- if (right_xr[i]) {
- lower = sfbi;
- break;
- }
- }
-
- right_xr += n;
- l += n;
- }
-
- start = sfbi;
- }
-
- w = 0;
- while (l < 576) {
- n = sfbwidth[sfbi++];
-
- for (i = 0; i < n; ++i) {
- if (right_xr[i]) {
- max = bound[w] = sfbi;
- break;
- }
- }
-
- right_xr += n;
- l += n;
- w = (w + 1) % 3;
- }
-
- if (max)
- lower = start;
-
- /* long blocks */
-
- for (i = 0; i < lower; ++i)
- modes[i] = header->mode_extension & ~I_STEREO;
-
- /* short blocks */
-
- w = 0;
- for (i = start; i < max; ++i) {
- if (i < bound[w])
- modes[i] = header->mode_extension & ~I_STEREO;
-
- w = (w + 1) % 3;
- }
- }
- else { /* right_ch->block_type != 2 */
- unsigned int bound;
-
- bound = 0;
- for (sfbi = l = 0; l < 576; l += n) {
- n = sfbwidth[sfbi++];
-
- for (i = 0; i < n; ++i) {
- if (right_xr[i]) {
- bound = sfbi;
- break;
- }
- }
-
- right_xr += n;
- }
-
- for (i = 0; i < bound; ++i)
- modes[i] = header->mode_extension & ~I_STEREO;
- }
-
- /* now do the actual processing */
-
- if (header->flags & MAD_FLAG_LSF_EXT) {
- unsigned char const *illegal_pos = granule[1].ch[1].scalefac;
- mad_fixed_t const *lsf_scale;
-
- /* intensity_scale */
- lsf_scale = is_lsf_table[right_ch->scalefac_compress & 0x1];
-
- for (sfbi = l = 0; l < 576; ++sfbi, l += n) {
- n = sfbwidth[sfbi];
-
- if (!(modes[sfbi] & I_STEREO))
- continue;
-
- if (illegal_pos[sfbi]) {
- modes[sfbi] &= ~I_STEREO;
- continue;
- }
-
- is_pos = right_ch->scalefac[sfbi];
-
- for (i = 0; i < n; ++i) {
- register mad_fixed_t left;
-
- left = xr[0][l + i];
-
- if (is_pos == 0)
- xr[1][l + i] = left;
- else {
- register mad_fixed_t opposite;
-
- opposite = mad_f_mul(left, lsf_scale[(is_pos - 1) / 2]);
-
- if (is_pos & 1) {
- xr[0][l + i] = opposite;
- xr[1][l + i] = left;
- }
- else
- xr[1][l + i] = opposite;
- }
- }
- }
- }
- else { /* !(header->flags & MAD_FLAG_LSF_EXT) */
- for (sfbi = l = 0; l < 576; ++sfbi, l += n) {
- n = sfbwidth[sfbi];
-
- if (!(modes[sfbi] & I_STEREO))
- continue;
-
- is_pos = right_ch->scalefac[sfbi];
-
- if (is_pos >= 7) { /* illegal intensity position */
- modes[sfbi] &= ~I_STEREO;
- continue;
- }
-
- for (i = 0; i < n; ++i) {
- register mad_fixed_t left;
-
- left = xr[0][l + i];
-
- xr[0][l + i] = mad_f_mul(left, is_table[ is_pos]);
- xr[1][l + i] = mad_f_mul(left, is_table[6 - is_pos]);
- }
- }
- }
- }
-
- /* middle/side stereo */
-
- if (header->mode_extension & MS_STEREO) {
- register mad_fixed_t invsqrt2;
-
- header->flags |= MAD_FLAG_MS_STEREO;
-
- invsqrt2 = root_table[3 + -2];
-
- for (sfbi = l = 0; l < 576; ++sfbi, l += n) {
- n = sfbwidth[sfbi];
-
- if (modes[sfbi] != MS_STEREO)
- continue;
-
- for (i = 0; i < n; ++i) {
- register mad_fixed_t m, s;
-
- m = xr[0][l + i];
- s = xr[1][l + i];
-
- xr[0][l + i] = mad_f_mul(m + s, invsqrt2); /* l = (m + s) / sqrt(2) */
- xr[1][l + i] = mad_f_mul(m - s, invsqrt2); /* r = (m - s) / sqrt(2) */
- }
- }
- }
-
- return MAD_ERROR_NONE;
-}
-
-/*
- * NAME: III_aliasreduce()
- * DESCRIPTION: perform frequency line alias reduction
- */
-static
-void III_aliasreduce(mad_fixed_t xr[576], int lines)
-{
- mad_fixed_t const *bound;
- int i;
-
- bound = &xr[lines];
- for (xr += 18; xr < bound; xr += 18) {
- for (i = 0; i < 8; ++i) {
- register mad_fixed_t a, b;
- register mad_fixed64hi_t hi;
- register mad_fixed64lo_t lo;
-
- a = xr[-1 - i];
- b = xr[ i];
-
-# if defined(ASO_ZEROCHECK)
- if (a | b) {
-# endif
- MAD_F_ML0(hi, lo, a, cs[i]);
- MAD_F_MLA(hi, lo, -b, ca[i]);
-
- xr[-1 - i] = MAD_F_MLZ(hi, lo);
-
- MAD_F_ML0(hi, lo, b, cs[i]);
- MAD_F_MLA(hi, lo, a, ca[i]);
-
- xr[ i] = MAD_F_MLZ(hi, lo);
-# if defined(ASO_ZEROCHECK)
- }
-# endif
- }
- }
-}
-
-# if defined(ASO_IMDCT)
-void III_imdct_l(mad_fixed_t const [18], mad_fixed_t [36], unsigned int);
-# else
-# if 1
-static
-void fastsdct(mad_fixed_t const x[9], mad_fixed_t y[18])
-{
- mad_fixed_t a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12;
- mad_fixed_t a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25;
- mad_fixed_t m0, m1, m2, m3, m4, m5, m6, m7;
-
- enum {
- c0 = MAD_F(0x1f838b8d), /* 2 * cos( 1 * PI / 18) */
- c1 = MAD_F(0x1bb67ae8), /* 2 * cos( 3 * PI / 18) */
- c2 = MAD_F(0x18836fa3), /* 2 * cos( 4 * PI / 18) */
- c3 = MAD_F(0x1491b752), /* 2 * cos( 5 * PI / 18) */
- c4 = MAD_F(0x0af1d43a), /* 2 * cos( 7 * PI / 18) */
- c5 = MAD_F(0x058e86a0), /* 2 * cos( 8 * PI / 18) */
- c6 = -MAD_F(0x1e11f642) /* 2 * cos(16 * PI / 18) */
- };
-
- a0 = x[3] + x[5];
- a1 = x[3] - x[5];
- a2 = x[6] + x[2];
- a3 = x[6] - x[2];
- a4 = x[1] + x[7];
- a5 = x[1] - x[7];
- a6 = x[8] + x[0];
- a7 = x[8] - x[0];
-
- a8 = a0 + a2;
- a9 = a0 - a2;
- a10 = a0 - a6;
- a11 = a2 - a6;
- a12 = a8 + a6;
- a13 = a1 - a3;
- a14 = a13 + a7;
- a15 = a3 + a7;
- a16 = a1 - a7;
- a17 = a1 + a3;
-
- m0 = mad_f_mul(a17, -c3);
- m1 = mad_f_mul(a16, -c0);
- m2 = mad_f_mul(a15, -c4);
- m3 = mad_f_mul(a14, -c1);
- m4 = mad_f_mul(a5, -c1);
- m5 = mad_f_mul(a11, -c6);
- m6 = mad_f_mul(a10, -c5);
- m7 = mad_f_mul(a9, -c2);
-
- a18 = x[4] + a4;
- a19 = 2 * x[4] - a4;
- a20 = a19 + m5;
- a21 = a19 - m5;
- a22 = a19 + m6;
- a23 = m4 + m2;
- a24 = m4 - m2;
- a25 = m4 + m1;
-
- /* output to every other slot for convenience */
-
- y[ 0] = a18 + a12;
- y[ 2] = m0 - a25;
- y[ 4] = m7 - a20;
- y[ 6] = m3;
- y[ 8] = a21 - m6;
- y[10] = a24 - m1;
- y[12] = a12 - 2 * a18;
- y[14] = a23 + m0;
- y[16] = a22 + m7;
-}
-
-static inline
-void sdctII(mad_fixed_t const x[18], mad_fixed_t X[18])
-{
- mad_fixed_t tmp[9];
- int i;
-
- /* scale[i] = 2 * cos(PI * (2 * i + 1) / (2 * 18)) */
- static mad_fixed_t const scale[9] = {
- MAD_F(0x1fe0d3b4), MAD_F(0x1ee8dd47), MAD_F(0x1d007930),
- MAD_F(0x1a367e59), MAD_F(0x16a09e66), MAD_F(0x125abcf8),
- MAD_F(0x0d8616bc), MAD_F(0x08483ee1), MAD_F(0x02c9fad7)
- };
-
- /* divide the 18-point SDCT-II into two 9-point SDCT-IIs */
-
- /* even input butterfly */
-
- for (i = 0; i < 9; i += 3) {
- tmp[i + 0] = x[i + 0] + x[18 - (i + 0) - 1];
- tmp[i + 1] = x[i + 1] + x[18 - (i + 1) - 1];
- tmp[i + 2] = x[i + 2] + x[18 - (i + 2) - 1];
- }
-
- fastsdct(tmp, &X[0]);
-
- /* odd input butterfly and scaling */
-
- for (i = 0; i < 9; i += 3) {
- tmp[i + 0] = mad_f_mul(x[i + 0] - x[18 - (i + 0) - 1], scale[i + 0]);
- tmp[i + 1] = mad_f_mul(x[i + 1] - x[18 - (i + 1) - 1], scale[i + 1]);
- tmp[i + 2] = mad_f_mul(x[i + 2] - x[18 - (i + 2) - 1], scale[i + 2]);
- }
-
- fastsdct(tmp, &X[1]);
-
- /* output accumulation */
-
- for (i = 3; i < 18; i += 8) {
- X[i + 0] -= X[(i + 0) - 2];
- X[i + 2] -= X[(i + 2) - 2];
- X[i + 4] -= X[(i + 4) - 2];
- X[i + 6] -= X[(i + 6) - 2];
- }
-}
-
-static inline
-void dctIV(mad_fixed_t const y[18], mad_fixed_t X[18])
-{
- mad_fixed_t tmp[18];
- int i;
-
- /* scale[i] = 2 * cos(PI * (2 * i + 1) / (4 * 18)) */
- static mad_fixed_t const scale[18] = {
- MAD_F(0x1ff833fa), MAD_F(0x1fb9ea93), MAD_F(0x1f3dd120),
- MAD_F(0x1e84d969), MAD_F(0x1d906bcf), MAD_F(0x1c62648b),
- MAD_F(0x1afd100f), MAD_F(0x1963268b), MAD_F(0x1797c6a4),
- MAD_F(0x159e6f5b), MAD_F(0x137af940), MAD_F(0x11318ef3),
- MAD_F(0x0ec6a507), MAD_F(0x0c3ef153), MAD_F(0x099f61c5),
- MAD_F(0x06ed12c5), MAD_F(0x042d4544), MAD_F(0x0165547c)
- };
-
- /* scaling */
-
- for (i = 0; i < 18; i += 3) {
- tmp[i + 0] = mad_f_mul(y[i + 0], scale[i + 0]);
- tmp[i + 1] = mad_f_mul(y[i + 1], scale[i + 1]);
- tmp[i + 2] = mad_f_mul(y[i + 2], scale[i + 2]);
- }
-
- /* SDCT-II */
-
- sdctII(tmp, X);
-
- /* scale reduction and output accumulation */
-
- X[0] /= 2;
- for (i = 1; i < 17; i += 4) {
- X[i + 0] = X[i + 0] / 2 - X[(i + 0) - 1];
- X[i + 1] = X[i + 1] / 2 - X[(i + 1) - 1];
- X[i + 2] = X[i + 2] / 2 - X[(i + 2) - 1];
- X[i + 3] = X[i + 3] / 2 - X[(i + 3) - 1];
- }
- X[17] = X[17] / 2 - X[16];
-}
-
-/*
- * NAME: imdct36
- * DESCRIPTION: perform X[18]->x[36] IMDCT using Szu-Wei Lee's fast algorithm
- */
-static inline
-void imdct36(mad_fixed_t const x[18], mad_fixed_t y[36])
-{
- mad_fixed_t tmp[18];
- int i;
-
- /* DCT-IV */
-
- dctIV(x, tmp);
-
- /* convert 18-point DCT-IV to 36-point IMDCT */
-
- for (i = 0; i < 9; i += 3) {
- y[i + 0] = tmp[9 + (i + 0)];
- y[i + 1] = tmp[9 + (i + 1)];
- y[i + 2] = tmp[9 + (i + 2)];
- }
- for (i = 9; i < 27; i += 3) {
- y[i + 0] = -tmp[36 - (9 + (i + 0)) - 1];
- y[i + 1] = -tmp[36 - (9 + (i + 1)) - 1];
- y[i + 2] = -tmp[36 - (9 + (i + 2)) - 1];
- }
- for (i = 27; i < 36; i += 3) {
- y[i + 0] = -tmp[(i + 0) - 27];
- y[i + 1] = -tmp[(i + 1) - 27];
- y[i + 2] = -tmp[(i + 2) - 27];
- }
-}
-# else
-/*
- * NAME: imdct36
- * DESCRIPTION: perform X[18]->x[36] IMDCT
- */
-static inline
-void imdct36(mad_fixed_t const X[18], mad_fixed_t x[36])
-{
- mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7;
- mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15;
- register mad_fixed64hi_t hi;
- register mad_fixed64lo_t lo;
-
- MAD_F_ML0(hi, lo, X[4], MAD_F(0x0ec835e8));
- MAD_F_MLA(hi, lo, X[13], MAD_F(0x061f78aa));
-
- t6 = MAD_F_MLZ(hi, lo);
-
- MAD_F_MLA(hi, lo, (t14 = X[1] - X[10]), -MAD_F(0x061f78aa));
- MAD_F_MLA(hi, lo, (t15 = X[7] + X[16]), -MAD_F(0x0ec835e8));
-
- t0 = MAD_F_MLZ(hi, lo);
-
- MAD_F_MLA(hi, lo, (t8 = X[0] - X[11] - X[12]), MAD_F(0x0216a2a2));
- MAD_F_MLA(hi, lo, (t9 = X[2] - X[9] - X[14]), MAD_F(0x09bd7ca0));
- MAD_F_MLA(hi, lo, (t10 = X[3] - X[8] - X[15]), -MAD_F(0x0cb19346));
- MAD_F_MLA(hi, lo, (t11 = X[5] - X[6] - X[17]), -MAD_F(0x0fdcf549));
-
- x[7] = MAD_F_MLZ(hi, lo);
- x[10] = -x[7];
-
- MAD_F_ML0(hi, lo, t8, -MAD_F(0x0cb19346));
- MAD_F_MLA(hi, lo, t9, MAD_F(0x0fdcf549));
- MAD_F_MLA(hi, lo, t10, MAD_F(0x0216a2a2));
- MAD_F_MLA(hi, lo, t11, -MAD_F(0x09bd7ca0));
-
- x[19] = x[34] = MAD_F_MLZ(hi, lo) - t0;
-
- t12 = X[0] - X[3] + X[8] - X[11] - X[12] + X[15];
- t13 = X[2] + X[5] - X[6] - X[9] - X[14] - X[17];
-
- MAD_F_ML0(hi, lo, t12, -MAD_F(0x0ec835e8));
- MAD_F_MLA(hi, lo, t13, MAD_F(0x061f78aa));
-
- x[22] = x[31] = MAD_F_MLZ(hi, lo) + t0;
-
- MAD_F_ML0(hi, lo, X[1], -MAD_F(0x09bd7ca0));
- MAD_F_MLA(hi, lo, X[7], MAD_F(0x0216a2a2));
- MAD_F_MLA(hi, lo, X[10], -MAD_F(0x0fdcf549));
- MAD_F_MLA(hi, lo, X[16], MAD_F(0x0cb19346));
-
- t1 = MAD_F_MLZ(hi, lo) + t6;
-
- MAD_F_ML0(hi, lo, X[0], MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[6], MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[9], MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[15], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0f9ee890));
-
- x[6] = MAD_F_MLZ(hi, lo) + t1;
- x[11] = -x[6];
-
- MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[2], -MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[3], MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[5], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[6], MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[8], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[15], MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[17], MAD_F(0x04cfb0e2));
-
- x[23] = x[30] = MAD_F_MLZ(hi, lo) + t1;
-
- MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[3], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[5], MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[9], -MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[11], MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[15], MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0acf37ad));
-
- x[18] = x[35] = MAD_F_MLZ(hi, lo) - t1;
-
- MAD_F_ML0(hi, lo, X[4], MAD_F(0x061f78aa));
- MAD_F_MLA(hi, lo, X[13], -MAD_F(0x0ec835e8));
-
- t7 = MAD_F_MLZ(hi, lo);
-
- MAD_F_MLA(hi, lo, X[1], -MAD_F(0x0cb19346));
- MAD_F_MLA(hi, lo, X[7], MAD_F(0x0fdcf549));
- MAD_F_MLA(hi, lo, X[10], MAD_F(0x0216a2a2));
- MAD_F_MLA(hi, lo, X[16], -MAD_F(0x09bd7ca0));
-
- t2 = MAD_F_MLZ(hi, lo);
-
- MAD_F_MLA(hi, lo, X[0], MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[5], MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[9], MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[12], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[15], MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[17], MAD_F(0x0f426cb5));
-
- x[5] = MAD_F_MLZ(hi, lo);
- x[12] = -x[5];
-
- MAD_F_ML0(hi, lo, X[0], MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[3], MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[6], -MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[8], MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[15], MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0bcbe352));
-
- x[0] = MAD_F_MLZ(hi, lo) + t2;
- x[17] = -x[0];
-
- MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[2], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[3], -MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[5], MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[8], MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[9], MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x03768962));
-
- x[24] = x[29] = MAD_F_MLZ(hi, lo) + t2;
-
- MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0216a2a2));
- MAD_F_MLA(hi, lo, X[7], -MAD_F(0x09bd7ca0));
- MAD_F_MLA(hi, lo, X[10], MAD_F(0x0cb19346));
- MAD_F_MLA(hi, lo, X[16], MAD_F(0x0fdcf549));
-
- t3 = MAD_F_MLZ(hi, lo) + t7;
-
- MAD_F_ML0(hi, lo, X[0], MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[3], -MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[5], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[6], MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[8], MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[12], MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0ffc19fd));
-
- x[8] = MAD_F_MLZ(hi, lo) + t3;
- x[9] = -x[8];
-
- MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[3], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[8], MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[14], -MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[15], MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[17], MAD_F(0x07635284));
-
- x[21] = x[32] = MAD_F_MLZ(hi, lo) + t3;
-
- MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[3], MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[6], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[9], MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[12], MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[15], -MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0898c779));
-
- x[20] = x[33] = MAD_F_MLZ(hi, lo) - t3;
-
- MAD_F_ML0(hi, lo, t14, -MAD_F(0x0ec835e8));
- MAD_F_MLA(hi, lo, t15, MAD_F(0x061f78aa));
-
- t4 = MAD_F_MLZ(hi, lo) - t7;
-
- MAD_F_ML0(hi, lo, t12, MAD_F(0x061f78aa));
- MAD_F_MLA(hi, lo, t13, MAD_F(0x0ec835e8));
-
- x[4] = MAD_F_MLZ(hi, lo) + t4;
- x[13] = -x[4];
-
- MAD_F_ML0(hi, lo, t8, MAD_F(0x09bd7ca0));
- MAD_F_MLA(hi, lo, t9, -MAD_F(0x0216a2a2));
- MAD_F_MLA(hi, lo, t10, MAD_F(0x0fdcf549));
- MAD_F_MLA(hi, lo, t11, -MAD_F(0x0cb19346));
-
- x[1] = MAD_F_MLZ(hi, lo) + t4;
- x[16] = -x[1];
-
- MAD_F_ML0(hi, lo, t8, -MAD_F(0x0fdcf549));
- MAD_F_MLA(hi, lo, t9, -MAD_F(0x0cb19346));
- MAD_F_MLA(hi, lo, t10, -MAD_F(0x09bd7ca0));
- MAD_F_MLA(hi, lo, t11, -MAD_F(0x0216a2a2));
-
- x[25] = x[28] = MAD_F_MLZ(hi, lo) + t4;
-
- MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0fdcf549));
- MAD_F_MLA(hi, lo, X[7], -MAD_F(0x0cb19346));
- MAD_F_MLA(hi, lo, X[10], -MAD_F(0x09bd7ca0));
- MAD_F_MLA(hi, lo, X[16], -MAD_F(0x0216a2a2));
-
- t5 = MAD_F_MLZ(hi, lo) - t6;
-
- MAD_F_ML0(hi, lo, X[0], MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[3], MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[5], MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[6], MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[8], -MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[12], MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[15], MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0d7e8807));
-
- x[2] = MAD_F_MLZ(hi, lo) + t5;
- x[15] = -x[2];
-
- MAD_F_ML0(hi, lo, X[0], MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[2], MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[3], MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[5], MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[6], -MAD_F(0x00b2aa3e));
- MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[9], -MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[11], MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[17], MAD_F(0x0e313245));
-
- x[3] = MAD_F_MLZ(hi, lo) + t5;
- x[14] = -x[3];
-
- MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0ffc19fd));
- MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0f9ee890));
- MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0f426cb5));
- MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0e313245));
- MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0d7e8807));
- MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0bcbe352));
- MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0acf37ad));
- MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0898c779));
- MAD_F_MLA(hi, lo, X[12], -MAD_F(0x07635284));
- MAD_F_MLA(hi, lo, X[14], -MAD_F(0x04cfb0e2));
- MAD_F_MLA(hi, lo, X[15], -MAD_F(0x03768962));
- MAD_F_MLA(hi, lo, X[17], -MAD_F(0x00b2aa3e));
-
- x[26] = x[27] = MAD_F_MLZ(hi, lo) + t5;
-}
-# endif
-
-/*
- * NAME: III_imdct_l()
- * DESCRIPTION: perform IMDCT and windowing for long blocks
- */
-static
-void III_imdct_l(mad_fixed_t const X[18], mad_fixed_t z[36],
- unsigned int block_type)
-{
- unsigned int i;
-
- /* IMDCT */
-
- imdct36(X, z);
-
- /* windowing */
-
- switch (block_type) {
- case 0: /* normal window */
-# if defined(ASO_INTERLEAVE1)
- {
- register mad_fixed_t tmp1, tmp2;
-
- tmp1 = window_l[0];
- tmp2 = window_l[1];
-
- for (i = 0; i < 34; i += 2) {
- z[i + 0] = mad_f_mul(z[i + 0], tmp1);
- tmp1 = window_l[i + 2];
- z[i + 1] = mad_f_mul(z[i + 1], tmp2);
- tmp2 = window_l[i + 3];
- }
-
- z[34] = mad_f_mul(z[34], tmp1);
- z[35] = mad_f_mul(z[35], tmp2);
- }
-# elif defined(ASO_INTERLEAVE2)
- {
- register mad_fixed_t tmp1, tmp2;
-
- tmp1 = z[0];
- tmp2 = window_l[0];
-
- for (i = 0; i < 35; ++i) {
- z[i] = mad_f_mul(tmp1, tmp2);
- tmp1 = z[i + 1];
- tmp2 = window_l[i + 1];
- }
-
- z[35] = mad_f_mul(tmp1, tmp2);
- }
-# elif 1
- for (i = 0; i < 36; i += 4) {
- z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]);
- z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]);
- z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]);
- z[i + 3] = mad_f_mul(z[i + 3], window_l[i + 3]);
- }
-# else
- for (i = 0; i < 36; ++i) z[i] = mad_f_mul(z[i], window_l[i]);
-# endif
- break;
-
- case 1: /* start block */
- for (i = 0; i < 18; i += 3) {
- z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]);
- z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]);
- z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]);
- }
- /* (i = 18; i < 24; ++i) z[i] unchanged */
- for (i = 24; i < 30; ++i) z[i] = mad_f_mul(z[i], window_s[i - 18]);
- for (i = 30; i < 36; ++i) z[i] = 0;
- break;
-
- case 3: /* stop block */
- for (i = 0; i < 6; ++i) z[i] = 0;
- for (i = 6; i < 12; ++i) z[i] = mad_f_mul(z[i], window_s[i - 6]);
- /* (i = 12; i < 18; ++i) z[i] unchanged */
- for (i = 18; i < 36; i += 3) {
- z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]);
- z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]);
- z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]);
- }
- break;
- }
-}
-# endif /* ASO_IMDCT */
-
-/*
- * NAME: III_imdct_s()
- * DESCRIPTION: perform IMDCT and windowing for short blocks
- */
-static
-void III_imdct_s(mad_fixed_t const X[18], mad_fixed_t z[36])
-{
- mad_fixed_t y[36], *yptr;
- mad_fixed_t const *wptr;
- int w, i;
- register mad_fixed64hi_t hi;
- register mad_fixed64lo_t lo;
-
- /* IMDCT */
-
- yptr = &y[0];
-
- for (w = 0; w < 3; ++w) {
- register mad_fixed_t const (*s)[6];
-
- s = imdct_s;
-
- for (i = 0; i < 3; ++i) {
- MAD_F_ML0(hi, lo, X[0], (*s)[0]);
- MAD_F_MLA(hi, lo, X[1], (*s)[1]);
- MAD_F_MLA(hi, lo, X[2], (*s)[2]);
- MAD_F_MLA(hi, lo, X[3], (*s)[3]);
- MAD_F_MLA(hi, lo, X[4], (*s)[4]);
- MAD_F_MLA(hi, lo, X[5], (*s)[5]);
-
- yptr[i + 0] = MAD_F_MLZ(hi, lo);
- yptr[5 - i] = -yptr[i + 0];
-
- ++s;
-
- MAD_F_ML0(hi, lo, X[0], (*s)[0]);
- MAD_F_MLA(hi, lo, X[1], (*s)[1]);
- MAD_F_MLA(hi, lo, X[2], (*s)[2]);
- MAD_F_MLA(hi, lo, X[3], (*s)[3]);
- MAD_F_MLA(hi, lo, X[4], (*s)[4]);
- MAD_F_MLA(hi, lo, X[5], (*s)[5]);
-
- yptr[ i + 6] = MAD_F_MLZ(hi, lo);
- yptr[11 - i] = yptr[i + 6];
-
- ++s;
- }
-
- yptr += 12;
- X += 6;
- }
-
- /* windowing, overlapping and concatenation */
-
- yptr = &y[0];
- wptr = &window_s[0];
-
- for (i = 0; i < 6; ++i) {
- z[i + 0] = 0;
- z[i + 6] = mad_f_mul(yptr[ 0 + 0], wptr[0]);
-
- MAD_F_ML0(hi, lo, yptr[ 0 + 6], wptr[6]);
- MAD_F_MLA(hi, lo, yptr[12 + 0], wptr[0]);
-
- z[i + 12] = MAD_F_MLZ(hi, lo);
-
- MAD_F_ML0(hi, lo, yptr[12 + 6], wptr[6]);
- MAD_F_MLA(hi, lo, yptr[24 + 0], wptr[0]);
-
- z[i + 18] = MAD_F_MLZ(hi, lo);
-
- z[i + 24] = mad_f_mul(yptr[24 + 6], wptr[6]);
- z[i + 30] = 0;
-
- ++yptr;
- ++wptr;
- }
-}
-
-/*
- * NAME: III_overlap()
- * DESCRIPTION: perform overlap-add of windowed IMDCT outputs
- */
-static
-void III_overlap(mad_fixed_t const output[36], mad_fixed_t overlap[18],
- mad_fixed_t sample[18][32], unsigned int sb)
-{
- unsigned int i;
-
-# if defined(ASO_INTERLEAVE2)
- {
- register mad_fixed_t tmp1, tmp2;
-
- tmp1 = overlap[0];
- tmp2 = overlap[1];
-
- for (i = 0; i < 16; i += 2) {
- sample[i + 0][sb] = output[i + 0 + 0] + tmp1;
- overlap[i + 0] = output[i + 0 + 18];
- tmp1 = overlap[i + 2];
-
- sample[i + 1][sb] = output[i + 1 + 0] + tmp2;
- overlap[i + 1] = output[i + 1 + 18];
- tmp2 = overlap[i + 3];
- }
-
- sample[16][sb] = output[16 + 0] + tmp1;
- overlap[16] = output[16 + 18];
- sample[17][sb] = output[17 + 0] + tmp2;
- overlap[17] = output[17 + 18];
- }
-# elif 0
- for (i = 0; i < 18; i += 2) {
- sample[i + 0][sb] = output[i + 0 + 0] + overlap[i + 0];
- overlap[i + 0] = output[i + 0 + 18];
-
- sample[i + 1][sb] = output[i + 1 + 0] + overlap[i + 1];
- overlap[i + 1] = output[i + 1 + 18];
- }
-# else
- for (i = 0; i < 18; ++i) {
- sample[i][sb] = output[i + 0] + overlap[i];
- overlap[i] = output[i + 18];
- }
-# endif
-}
-
-/*
- * NAME: III_overlap_z()
- * DESCRIPTION: perform "overlap-add" of zero IMDCT outputs
- */
-static inline
-void III_overlap_z(mad_fixed_t overlap[18],
- mad_fixed_t sample[18][32], unsigned int sb)
-{
- unsigned int i;
-
-# if defined(ASO_INTERLEAVE2)
- {
- register mad_fixed_t tmp1, tmp2;
-
- tmp1 = overlap[0];
- tmp2 = overlap[1];
-
- for (i = 0; i < 16; i += 2) {
- sample[i + 0][sb] = tmp1;
- overlap[i + 0] = 0;
- tmp1 = overlap[i + 2];
-
- sample[i + 1][sb] = tmp2;
- overlap[i + 1] = 0;
- tmp2 = overlap[i + 3];
- }
-
- sample[16][sb] = tmp1;
- overlap[16] = 0;
- sample[17][sb] = tmp2;
- overlap[17] = 0;
- }
-# else
- for (i = 0; i < 18; ++i) {
- sample[i][sb] = overlap[i];
- overlap[i] = 0;
- }
-# endif
-}
-
-/*
- * NAME: III_freqinver()
- * DESCRIPTION: perform subband frequency inversion for odd sample lines
- */
-static
-void III_freqinver(mad_fixed_t sample[18][32], unsigned int sb)
-{
- unsigned int i;
-
-# if 1 || defined(ASO_INTERLEAVE1) || defined(ASO_INTERLEAVE2)
- {
- register mad_fixed_t tmp1, tmp2;
-
- tmp1 = sample[1][sb];
- tmp2 = sample[3][sb];
-
- for (i = 1; i < 13; i += 4) {
- sample[i + 0][sb] = -tmp1;
- tmp1 = sample[i + 4][sb];
- sample[i + 2][sb] = -tmp2;
- tmp2 = sample[i + 6][sb];
- }
-
- sample[13][sb] = -tmp1;
- tmp1 = sample[17][sb];
- sample[15][sb] = -tmp2;
- sample[17][sb] = -tmp1;
- }
-# else
- for (i = 1; i < 18; i += 2)
- sample[i][sb] = -sample[i][sb];
-# endif
-}
-
-/*
- * NAME: III_decode()
- * DESCRIPTION: decode frame main_data
- */
-static
-enum mad_error III_decode(struct mad_bitptr *ptr, struct mad_frame *frame,
- struct sideinfo *si, unsigned int nch)
-{
- struct mad_header *header = &frame->header;
- unsigned int sfreqi, ngr, gr;
-
- {
- unsigned int sfreq;
-
- sfreq = header->samplerate;
- if (header->flags & MAD_FLAG_MPEG_2_5_EXT)
- sfreq *= 2;
-
- /* 48000 => 0, 44100 => 1, 32000 => 2,
- 24000 => 3, 22050 => 4, 16000 => 5 */
- sfreqi = ((sfreq >> 7) & 0x000f) +
- ((sfreq >> 15) & 0x0001) - 8;
-
- if (header->flags & MAD_FLAG_MPEG_2_5_EXT)
- sfreqi += 3;
- }
-
- /* scalefactors, Huffman decoding, requantization */
-
- ngr = (header->flags & MAD_FLAG_LSF_EXT) ? 1 : 2;
-
- for (gr = 0; gr < ngr; ++gr) {
- struct granule *granule = &si->gr[gr];
- unsigned char const *sfbwidth[2];
- mad_fixed_t xr[2][576];
- unsigned int ch;
- enum mad_error error;
-
- for (ch = 0; ch < nch; ++ch) {
- struct channel *channel = &granule->ch[ch];
- unsigned int part2_length;
-
- sfbwidth[ch] = sfbwidth_table[sfreqi].l;
- if (channel->block_type == 2) {
- sfbwidth[ch] = (channel->flags & mixed_block_flag) ?
- sfbwidth_table[sfreqi].m : sfbwidth_table[sfreqi].s;
- }
-
- if (header->flags & MAD_FLAG_LSF_EXT) {
- part2_length = III_scalefactors_lsf(ptr, channel,
- ch == 0 ? 0 : &si->gr[1].ch[1],
- header->mode_extension);
- }
- else {
- part2_length = III_scalefactors(ptr, channel, &si->gr[0].ch[ch],
- gr == 0 ? 0 : si->scfsi[ch]);
- }
-
- error = III_huffdecode(ptr, xr[ch], channel, sfbwidth[ch], part2_length);
- if (error)
- return error;
- }
-
- /* joint stereo processing */
-
- if (header->mode == MAD_MODE_JOINT_STEREO && header->mode_extension) {
- error = III_stereo(xr, granule, header, sfbwidth[0]);
- if (error)
- return error;
- }
-
- /* reordering, alias reduction, IMDCT, overlap-add, frequency inversion */
-
- for (ch = 0; ch < nch; ++ch) {
- struct channel const *channel = &granule->ch[ch];
- mad_fixed_t (*sample)[32] = &frame->sbsample[ch][18 * gr];
- unsigned int sb, l, i, sblimit;
- mad_fixed_t output[36];
-
- if (channel->block_type == 2) {
- III_reorder(xr[ch], channel, sfbwidth[ch]);
-
-# if !defined(OPT_STRICT)
- /*
- * According to ISO/IEC 11172-3, "Alias reduction is not applied for
- * granules with block_type == 2 (short block)." However, other
- * sources suggest alias reduction should indeed be performed on the
- * lower two subbands of mixed blocks. Most other implementations do
- * this, so by default we will too.
- */
- if (channel->flags & mixed_block_flag)
- III_aliasreduce(xr[ch], 36);
-# endif
- }
- else
- III_aliasreduce(xr[ch], 576);
-
- l = 0;
-
- /* subbands 0-1 */
-
- if (channel->block_type != 2 || (channel->flags & mixed_block_flag)) {
- unsigned int block_type;
-
- block_type = channel->block_type;
- if (channel->flags & mixed_block_flag)
- block_type = 0;
-
- /* long blocks */
- for (sb = 0; sb < 2; ++sb, l += 18) {
- III_imdct_l(&xr[ch][l], output, block_type);
- III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
- }
- }
- else {
- /* short blocks */
- for (sb = 0; sb < 2; ++sb, l += 18) {
- III_imdct_s(&xr[ch][l], output);
- III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
- }
- }
-
- III_freqinver(sample, 1);
-
- /* (nonzero) subbands 2-31 */
-
- i = 576;
- while (i > 36 && xr[ch][i - 1] == 0)
- --i;
-
- sblimit = 32 - (576 - i) / 18;
-
- if (channel->block_type != 2) {
- /* long blocks */
- for (sb = 2; sb < sblimit; ++sb, l += 18) {
- III_imdct_l(&xr[ch][l], output, channel->block_type);
- III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
-
- if (sb & 1)
- III_freqinver(sample, sb);
- }
- }
- else {
- /* short blocks */
- for (sb = 2; sb < sblimit; ++sb, l += 18) {
- III_imdct_s(&xr[ch][l], output);
- III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
-
- if (sb & 1)
- III_freqinver(sample, sb);
- }
- }
-
- /* remaining (zero) subbands */
-
- for (sb = sblimit; sb < 32; ++sb) {
- III_overlap_z((*frame->overlap)[ch][sb], sample, sb);
-
- if (sb & 1)
- III_freqinver(sample, sb);
- }
- }
- }
-
- return MAD_ERROR_NONE;
-}
-
-/*
- * NAME: layer->III()
- * DESCRIPTION: decode a single Layer III frame
- */
-int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame)
-{
- struct mad_header *header = &frame->header;
- unsigned int nch, priv_bitlen, next_md_begin = 0;
- unsigned int si_len, data_bitlen, md_len;
- unsigned int frame_space, frame_used, frame_free;
- struct mad_bitptr ptr;
- struct sideinfo si;
- enum mad_error error;
- int result = 0;
-
- /* allocate Layer III dynamic structures */
-
- if (stream->main_data == 0) {
- stream->main_data = malloc(MAD_BUFFER_MDLEN);
- if (stream->main_data == 0) {
- stream->error = MAD_ERROR_NOMEM;
- return -1;
- }
- }
-
- if (frame->overlap == 0) {
- frame->overlap = calloc(2 * 32 * 18, sizeof(mad_fixed_t));
- if (frame->overlap == 0) {
- stream->error = MAD_ERROR_NOMEM;
- return -1;
- }
- }
-
- nch = MAD_NCHANNELS(header);
- si_len = (header->flags & MAD_FLAG_LSF_EXT) ?
- (nch == 1 ? 9 : 17) : (nch == 1 ? 17 : 32);
-
- /* check frame sanity */
-
- if (stream->next_frame - mad_bit_nextbyte(&stream->ptr) <
- (signed int) si_len) {
- stream->error = MAD_ERROR_BADFRAMELEN;
- stream->md_len = 0;
- return -1;
- }
-
- /* check CRC word */
-
- if (header->flags & MAD_FLAG_PROTECTION) {
- header->crc_check =
- mad_bit_crc(stream->ptr, si_len * CHAR_BIT, header->crc_check);
-
- if (header->crc_check != header->crc_target &&
- !(frame->options & MAD_OPTION_IGNORECRC)) {
- stream->error = MAD_ERROR_BADCRC;
- result = -1;
- }
- }
-
- /* decode frame side information */
-
- error = III_sideinfo(&stream->ptr, nch, header->flags & MAD_FLAG_LSF_EXT,
- &si, &data_bitlen, &priv_bitlen);
- if (error && result == 0) {
- stream->error = error;
- result = -1;
- }
-
- header->flags |= priv_bitlen;
- header->private_bits |= si.private_bits;
-
- /* find main_data of next frame */
-
- {
- struct mad_bitptr peek;
- unsigned long header;
-
- mad_bit_init(&peek, stream->next_frame);
-
- header = mad_bit_read(&peek, 32);
- if ((header & 0xffe60000L) /* syncword | layer */ == 0xffe20000L) {
- if (!(header & 0x00010000L)) /* protection_bit */
- mad_bit_skip(&peek, 16); /* crc_check */
-
- next_md_begin =
- mad_bit_read(&peek, (header & 0x00080000L) /* ID */ ? 9 : 8);
- }
-
- mad_bit_finish(&peek);
- }
-
- /* find main_data of this frame */
-
- frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr);
-
- if (next_md_begin > si.main_data_begin + frame_space)
- next_md_begin = 0;
-
- md_len = si.main_data_begin + frame_space - next_md_begin;
-
- frame_used = 0;
-
- if (si.main_data_begin == 0) {
- ptr = stream->ptr;
- stream->md_len = 0;
-
- frame_used = md_len;
- }
- else {
- if (si.main_data_begin > stream->md_len) {
- if (result == 0) {
- stream->error = MAD_ERROR_BADDATAPTR;
- result = -1;
- }
- }
- else {
- mad_bit_init(&ptr,
- *stream->main_data + stream->md_len - si.main_data_begin);
-
- if (md_len > si.main_data_begin) {
- assert(stream->md_len + md_len -
- si.main_data_begin <= MAD_BUFFER_MDLEN);
-
- memcpy(*stream->main_data + stream->md_len,
- mad_bit_nextbyte(&stream->ptr),
- frame_used = md_len - si.main_data_begin);
- stream->md_len += frame_used;
- }
- }
- }
-
- frame_free = frame_space - frame_used;
-
- /* decode main_data */
-
- if (result == 0) {
- error = III_decode(&ptr, frame, &si, nch);
- if (error) {
- stream->error = error;
- result = -1;
- }
-
- /* designate ancillary bits */
-
- stream->anc_ptr = ptr;
- stream->anc_bitlen = md_len * CHAR_BIT - data_bitlen;
- }
-
-# if 0 && defined(DEBUG)
- fprintf(stderr,
- "main_data_begin:%u, md_len:%u, frame_free:%u, "
- "data_bitlen:%u, anc_bitlen: %u\n",
- si.main_data_begin, md_len, frame_free,
- data_bitlen, stream->anc_bitlen);
-# endif
-
- /* preload main_data buffer with up to 511 bytes for next frame(s) */
-
- if (frame_free >= next_md_begin) {
- memcpy(*stream->main_data,
- stream->next_frame - next_md_begin, next_md_begin);
- stream->md_len = next_md_begin;
- }
- else {
- if (md_len < si.main_data_begin) {
- unsigned int extra;
-
- extra = si.main_data_begin - md_len;
- if (extra + frame_free > next_md_begin)
- extra = next_md_begin - frame_free;
-
- if (extra < stream->md_len) {
- memmove(*stream->main_data,
- *stream->main_data + stream->md_len - extra, extra);
- stream->md_len = extra;
- }
- }
- else
- stream->md_len = 0;
-
- memcpy(*stream->main_data + stream->md_len,
- stream->next_frame - frame_free, frame_free);
- stream->md_len += frame_free;
- }
-
- return result;
-}
-
-# ifdef _MSC_VER
-# pragma warning(pop)
-# endif
diff --git a/libmad/src/layer3.h b/libmad/src/layer3.h
deleted file mode 100644
index 2504d46..0000000
--- a/libmad/src/layer3.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: layer3.h,v 1.10 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBMAD_LAYER3_H
-# define LIBMAD_LAYER3_H
-
-# include "stream.h"
-# include "frame.h"
-
-int mad_layer_III(struct mad_stream *, struct mad_frame *);
-
-# endif
diff --git a/libmad/src/qc_table.dat b/libmad/src/qc_table.dat
deleted file mode 100644
index 35a2223..0000000
--- a/libmad/src/qc_table.dat
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: qc_table.dat,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-/*
- * These are the Layer II classes of quantization.
- * The table is derived from Table B.4 of ISO/IEC 11172-3.
- */
-
- { 3, 2, 5,
- MAD_F(0x15555555) /* 1.33333333333 => 1.33333333209, e 0.00000000124 */,
- MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ },
- { 5, 3, 7,
- MAD_F(0x1999999a) /* 1.60000000000 => 1.60000000149, e -0.00000000149 */,
- MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ },
- { 7, 0, 3,
- MAD_F(0x12492492) /* 1.14285714286 => 1.14285714179, e 0.00000000107 */,
- MAD_F(0x04000000) /* 0.25000000000 => 0.25000000000, e 0.00000000000 */ },
- { 9, 4, 10,
- MAD_F(0x1c71c71c) /* 1.77777777777 => 1.77777777612, e 0.00000000165 */,
- MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ },
- { 15, 0, 4,
- MAD_F(0x11111111) /* 1.06666666666 => 1.06666666642, e 0.00000000024 */,
- MAD_F(0x02000000) /* 0.12500000000 => 0.12500000000, e 0.00000000000 */ },
- { 31, 0, 5,
- MAD_F(0x10842108) /* 1.03225806452 => 1.03225806355, e 0.00000000097 */,
- MAD_F(0x01000000) /* 0.06250000000 => 0.06250000000, e 0.00000000000 */ },
- { 63, 0, 6,
- MAD_F(0x10410410) /* 1.01587301587 => 1.01587301493, e 0.00000000094 */,
- MAD_F(0x00800000) /* 0.03125000000 => 0.03125000000, e 0.00000000000 */ },
- { 127, 0, 7,
- MAD_F(0x10204081) /* 1.00787401575 => 1.00787401572, e 0.00000000003 */,
- MAD_F(0x00400000) /* 0.01562500000 => 0.01562500000, e 0.00000000000 */ },
- { 255, 0, 8,
- MAD_F(0x10101010) /* 1.00392156863 => 1.00392156839, e 0.00000000024 */,
- MAD_F(0x00200000) /* 0.00781250000 => 0.00781250000, e 0.00000000000 */ },
- { 511, 0, 9,
- MAD_F(0x10080402) /* 1.00195694716 => 1.00195694715, e 0.00000000001 */,
- MAD_F(0x00100000) /* 0.00390625000 => 0.00390625000, e 0.00000000000 */ },
- { 1023, 0, 10,
- MAD_F(0x10040100) /* 1.00097751711 => 1.00097751617, e 0.00000000094 */,
- MAD_F(0x00080000) /* 0.00195312500 => 0.00195312500, e 0.00000000000 */ },
- { 2047, 0, 11,
- MAD_F(0x10020040) /* 1.00048851979 => 1.00048851967, e 0.00000000012 */,
- MAD_F(0x00040000) /* 0.00097656250 => 0.00097656250, e 0.00000000000 */ },
- { 4095, 0, 12,
- MAD_F(0x10010010) /* 1.00024420024 => 1.00024420023, e 0.00000000001 */,
- MAD_F(0x00020000) /* 0.00048828125 => 0.00048828125, e 0.00000000000 */ },
- { 8191, 0, 13,
- MAD_F(0x10008004) /* 1.00012208522 => 1.00012208521, e 0.00000000001 */,
- MAD_F(0x00010000) /* 0.00024414063 => 0.00024414062, e 0.00000000000 */ },
- { 16383, 0, 14,
- MAD_F(0x10004001) /* 1.00006103888 => 1.00006103888, e -0.00000000000 */,
- MAD_F(0x00008000) /* 0.00012207031 => 0.00012207031, e -0.00000000000 */ },
- { 32767, 0, 15,
- MAD_F(0x10002000) /* 1.00003051851 => 1.00003051758, e 0.00000000093 */,
- MAD_F(0x00004000) /* 0.00006103516 => 0.00006103516, e 0.00000000000 */ },
- { 65535, 0, 16,
- MAD_F(0x10001000) /* 1.00001525902 => 1.00001525879, e 0.00000000023 */,
- MAD_F(0x00002000) /* 0.00003051758 => 0.00003051758, e 0.00000000000 */ }
diff --git a/libmad/src/rq_table.dat b/libmad/src/rq_table.dat
deleted file mode 100644
index 059c4f3..0000000
--- a/libmad/src/rq_table.dat
+++ /dev/null
@@ -1,8747 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: rq_table.dat,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-/*
- * This is the lookup table used to compute x^(4/3) for Layer III
- * requantization. To maintain the best possible accuracy, the value is
- * stored as a normalized mantissa with exponent. The requantization
- * algorithm recombines these parts with appropriate scaling.
- */
-
- /* 0 */ { MAD_F(0x00000000) /* 0.000000000 */, 0 },
- /* 1 */ { MAD_F(0x04000000) /* 0.250000000 */, 2 },
- /* 2 */ { MAD_F(0x050a28be) /* 0.314980262 */, 3 },
- /* 3 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 4 },
- /* 4 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 4 },
- /* 5 */ { MAD_F(0x04466275) /* 0.267183742 */, 5 },
- /* 6 */ { MAD_F(0x05738c72) /* 0.340710111 */, 5 },
- /* 7 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 5 },
- /* 8 */ { MAD_F(0x04000000) /* 0.250000000 */, 6 },
- /* 9 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 6 },
- /* 10 */ { MAD_F(0x0562d694) /* 0.336630420 */, 6 },
- /* 11 */ { MAD_F(0x061dae96) /* 0.382246578 */, 6 },
- /* 12 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 6 },
- /* 13 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 6 },
- /* 14 */ { MAD_F(0x0437be65) /* 0.263609310 */, 7 },
- /* 15 */ { MAD_F(0x049fc824) /* 0.289009227 */, 7 },
-
- /* 16 */ { MAD_F(0x050a28be) /* 0.314980262 */, 7 },
- /* 17 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 7 },
- /* 18 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 7 },
- /* 19 */ { MAD_F(0x06566361) /* 0.396090870 */, 7 },
- /* 20 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 7 },
- /* 21 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 7 },
- /* 22 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 7 },
- /* 23 */ { MAD_F(0x04168b05) /* 0.255503674 */, 8 },
- /* 24 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 8 },
- /* 25 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 8 },
- /* 26 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 8 },
- /* 27 */ { MAD_F(0x05100000) /* 0.316406250 */, 8 },
- /* 28 */ { MAD_F(0x05506451) /* 0.332126919 */, 8 },
- /* 29 */ { MAD_F(0x05918e15) /* 0.348035890 */, 8 },
- /* 30 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 8 },
- /* 31 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 8 },
-
- /* 32 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 8 },
- /* 33 */ { MAD_F(0x069d9400) /* 0.413471222 */, 8 },
- /* 34 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 8 },
- /* 35 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 8 },
- /* 36 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 8 },
- /* 37 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 8 },
- /* 38 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 8 },
- /* 39 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 9 },
- /* 40 */ { MAD_F(0x04466275) /* 0.267183742 */, 9 },
- /* 41 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 9 },
- /* 42 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 9 },
- /* 43 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 9 },
- /* 44 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 9 },
- /* 45 */ { MAD_F(0x05007b49) /* 0.312617576 */, 9 },
- /* 46 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 9 },
- /* 47 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 9 },
-
- /* 48 */ { MAD_F(0x05738c72) /* 0.340710111 */, 9 },
- /* 49 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 9 },
- /* 50 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 9 },
- /* 51 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 9 },
- /* 52 */ { MAD_F(0x0610b982) /* 0.379083164 */, 9 },
- /* 53 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 9 },
- /* 54 */ { MAD_F(0x0660db91) /* 0.398646895 */, 9 },
- /* 55 */ { MAD_F(0x06894c90) /* 0.408520284 */, 9 },
- /* 56 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 9 },
- /* 57 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 9 },
- /* 58 */ { MAD_F(0x07041636) /* 0.438497744 */, 9 },
- /* 59 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 9 },
- /* 60 */ { MAD_F(0x075722ef) /* 0.458773552 */, 9 },
- /* 61 */ { MAD_F(0x078102b8) /* 0.468996735 */, 9 },
- /* 62 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 9 },
- /* 63 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 9 },
-
- /* 64 */ { MAD_F(0x04000000) /* 0.250000000 */, 10 },
- /* 65 */ { MAD_F(0x04156381) /* 0.255221850 */, 10 },
- /* 66 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 10 },
- /* 67 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 10 },
- /* 68 */ { MAD_F(0x045635cf) /* 0.271047409 */, 10 },
- /* 69 */ { MAD_F(0x046c083e) /* 0.276375048 */, 10 },
- /* 70 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 10 },
- /* 71 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 10 },
- /* 72 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 10 },
- /* 73 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 10 },
- /* 74 */ { MAD_F(0x04dab524) /* 0.303395408 */, 10 },
- /* 75 */ { MAD_F(0x04f12624) /* 0.308874267 */, 10 },
- /* 76 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 10 },
- /* 77 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 10 },
- /* 78 */ { MAD_F(0x053511cb) /* 0.325456423 */, 10 },
- /* 79 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 10 },
-
- /* 80 */ { MAD_F(0x0562d694) /* 0.336630420 */, 10 },
- /* 81 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 10 },
- /* 82 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 10 },
- /* 83 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 10 },
- /* 84 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 10 },
- /* 85 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 10 },
- /* 86 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 10 },
- /* 87 */ { MAD_F(0x0606012b) /* 0.376465960 */, 10 },
- /* 88 */ { MAD_F(0x061dae96) /* 0.382246578 */, 10 },
- /* 89 */ { MAD_F(0x06357302) /* 0.388049134 */, 10 },
- /* 90 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 10 },
- /* 91 */ { MAD_F(0x0665402d) /* 0.399719406 */, 10 },
- /* 92 */ { MAD_F(0x067d4896) /* 0.405586801 */, 10 },
- /* 93 */ { MAD_F(0x06956753) /* 0.411475493 */, 10 },
- /* 94 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 10 },
- /* 95 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 10 },
-
- /* 96 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 10 },
- /* 97 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 10 },
- /* 98 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 10 },
- /* 99 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 10 },
- /* 100 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 10 },
- /* 101 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 10 },
- /* 102 */ { MAD_F(0x07724f64) /* 0.465407744 */, 10 },
- /* 103 */ { MAD_F(0x078b4514) /* 0.471501425 */, 10 },
- /* 104 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 10 },
- /* 105 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 10 },
- /* 106 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 10 },
- /* 107 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 10 },
- /* 108 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 11 },
- /* 109 */ { MAD_F(0x04115aca) /* 0.254236974 */, 11 },
- /* 110 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 11 },
- /* 111 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 11 },
-
- /* 112 */ { MAD_F(0x0437be65) /* 0.263609310 */, 11 },
- /* 113 */ { MAD_F(0x04449dee) /* 0.266752177 */, 11 },
- /* 114 */ { MAD_F(0x04518733) /* 0.269904329 */, 11 },
- /* 115 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 11 },
- /* 116 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 11 },
- /* 117 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 11 },
- /* 118 */ { MAD_F(0x04858c83) /* 0.282604707 */, 11 },
- /* 119 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 11 },
- /* 120 */ { MAD_F(0x049fc824) /* 0.289009227 */, 11 },
- /* 121 */ { MAD_F(0x04acf402) /* 0.292224893 */, 11 },
- /* 122 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 11 },
- /* 123 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 11 },
- /* 124 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 11 },
- /* 125 */ { MAD_F(0x04e20000) /* 0.305175781 */, 11 },
- /* 126 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 11 },
- /* 127 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 11 },
-
- /* 128 */ { MAD_F(0x050a28be) /* 0.314980262 */, 11 },
- /* 129 */ { MAD_F(0x05179da4) /* 0.318265572 */, 11 },
- /* 130 */ { MAD_F(0x05251b73) /* 0.321559381 */, 11 },
- /* 131 */ { MAD_F(0x0532a220) /* 0.324861647 */, 11 },
- /* 132 */ { MAD_F(0x054031a0) /* 0.328172327 */, 11 },
- /* 133 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 11 },
- /* 134 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 11 },
- /* 135 */ { MAD_F(0x0569149c) /* 0.338154423 */, 11 },
- /* 136 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 11 },
- /* 137 */ { MAD_F(0x058481e9) /* 0.344850455 */, 11 },
- /* 138 */ { MAD_F(0x0592456d) /* 0.348210741 */, 11 },
- /* 139 */ { MAD_F(0x05a01176) /* 0.351579152 */, 11 },
- /* 140 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 11 },
- /* 141 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 11 },
- /* 142 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 11 },
- /* 143 */ { MAD_F(0x05d79601) /* 0.365133291 */, 11 },
-
- /* 144 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 11 },
- /* 145 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 11 },
- /* 146 */ { MAD_F(0x060190ee) /* 0.375382356 */, 11 },
- /* 147 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 11 },
- /* 148 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 11 },
- /* 149 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 11 },
- /* 150 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 11 },
- /* 151 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 11 },
- /* 152 */ { MAD_F(0x06566361) /* 0.396090870 */, 11 },
- /* 153 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 11 },
- /* 154 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 11 },
- /* 155 */ { MAD_F(0x068138f3) /* 0.406548452 */, 11 },
- /* 156 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 11 },
- /* 157 */ { MAD_F(0x069deed1) /* 0.413557833 */, 11 },
- /* 158 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 11 },
- /* 159 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 11 },
-
- /* 160 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 11 },
- /* 161 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 11 },
- /* 162 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 11 },
- /* 163 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 11 },
- /* 164 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 11 },
- /* 165 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 11 },
- /* 166 */ { MAD_F(0x0720a087) /* 0.445465593 */, 11 },
- /* 167 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 11 },
- /* 168 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 11 },
- /* 169 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 11 },
- /* 170 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 11 },
- /* 171 */ { MAD_F(0x076a454c) /* 0.463444993 */, 11 },
- /* 172 */ { MAD_F(0x07791620) /* 0.467062117 */, 11 },
- /* 173 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 11 },
- /* 174 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 11 },
- /* 175 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 11 },
-
- /* 176 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 11 },
- /* 177 */ { MAD_F(0x07c39812) /* 0.485252449 */, 11 },
- /* 178 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 11 },
- /* 179 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 11 },
- /* 180 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 11 },
- /* 181 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 11 },
- /* 182 */ { MAD_F(0x0407673f) /* 0.251807447 */, 12 },
- /* 183 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 12 },
- /* 184 */ { MAD_F(0x04168b05) /* 0.255503674 */, 12 },
- /* 185 */ { MAD_F(0x041e2230) /* 0.257356825 */, 12 },
- /* 186 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 12 },
- /* 187 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 12 },
- /* 188 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 12 },
- /* 189 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 12 },
- /* 190 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 12 },
- /* 191 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 12 },
-
- /* 192 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 12 },
- /* 193 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 12 },
- /* 194 */ { MAD_F(0x04630eed) /* 0.274184158 */, 12 },
- /* 195 */ { MAD_F(0x046ac896) /* 0.276070203 */, 12 },
- /* 196 */ { MAD_F(0x047285a2) /* 0.277959474 */, 12 },
- /* 197 */ { MAD_F(0x047a460c) /* 0.279851960 */, 12 },
- /* 198 */ { MAD_F(0x048209d3) /* 0.281747652 */, 12 },
- /* 199 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 12 },
- /* 200 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 12 },
- /* 201 */ { MAD_F(0x04996935) /* 0.287453849 */, 12 },
- /* 202 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 12 },
- /* 203 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 12 },
- /* 204 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 12 },
- /* 205 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 12 },
- /* 206 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 12 },
- /* 207 */ { MAD_F(0x04c88135) /* 0.298951346 */, 12 },
-
- /* 208 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 12 },
- /* 209 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 12 },
- /* 210 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 12 },
- /* 211 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 12 },
- /* 212 */ { MAD_F(0x04f01963) /* 0.308617963 */, 12 },
- /* 213 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 12 },
- /* 214 */ { MAD_F(0x05000655) /* 0.312506041 */, 12 },
- /* 215 */ { MAD_F(0x05080195) /* 0.314454634 */, 12 },
- /* 216 */ { MAD_F(0x05100000) /* 0.316406250 */, 12 },
- /* 217 */ { MAD_F(0x05180194) /* 0.318360880 */, 12 },
- /* 218 */ { MAD_F(0x0520064f) /* 0.320318516 */, 12 },
- /* 219 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 12 },
- /* 220 */ { MAD_F(0x0530192e) /* 0.324242764 */, 12 },
- /* 221 */ { MAD_F(0x0538274e) /* 0.326209359 */, 12 },
- /* 222 */ { MAD_F(0x0540388a) /* 0.328178922 */, 12 },
- /* 223 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 12 },
-
- /* 224 */ { MAD_F(0x05506451) /* 0.332126919 */, 12 },
- /* 225 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 12 },
- /* 226 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 12 },
- /* 227 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 12 },
- /* 228 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 12 },
- /* 229 */ { MAD_F(0x05790793) /* 0.342048241 */, 12 },
- /* 230 */ { MAD_F(0x05813162) /* 0.344041237 */, 12 },
- /* 231 */ { MAD_F(0x05895e39) /* 0.346037122 */, 12 },
- /* 232 */ { MAD_F(0x05918e15) /* 0.348035890 */, 12 },
- /* 233 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 12 },
- /* 234 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 12 },
- /* 235 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 12 },
- /* 236 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 12 },
- /* 237 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 12 },
- /* 238 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 12 },
- /* 239 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 12 },
-
- /* 240 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 12 },
- /* 241 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 12 },
- /* 242 */ { MAD_F(0x05e41105) /* 0.368180294 */, 12 },
- /* 243 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 12 },
- /* 244 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 12 },
- /* 245 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 12 },
- /* 246 */ { MAD_F(0x060564b1) /* 0.376316732 */, 12 },
- /* 247 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 12 },
- /* 248 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 12 },
- /* 249 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 12 },
- /* 250 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 12 },
- /* 251 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 12 },
- /* 252 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 12 },
- /* 253 */ { MAD_F(0x06402666) /* 0.390661620 */, 12 },
- /* 254 */ { MAD_F(0x064896a7) /* 0.392721798 */, 12 },
- /* 255 */ { MAD_F(0x065109be) /* 0.394784681 */, 12 },
-
- /* 256 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 12 },
- /* 257 */ { MAD_F(0x0661f867) /* 0.398918536 */, 12 },
- /* 258 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 12 },
- /* 259 */ { MAD_F(0x0672f252) /* 0.403063128 */, 12 },
- /* 260 */ { MAD_F(0x067b737c) /* 0.405139433 */, 12 },
- /* 261 */ { MAD_F(0x0683f771) /* 0.407218402 */, 12 },
- /* 262 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 12 },
- /* 263 */ { MAD_F(0x069507b5) /* 0.411384303 */, 12 },
- /* 264 */ { MAD_F(0x069d9400) /* 0.413471222 */, 12 },
- /* 265 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 12 },
- /* 266 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 12 },
- /* 267 */ { MAD_F(0x06b74971) /* 0.419747773 */, 12 },
- /* 268 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 12 },
- /* 269 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 12 },
- /* 270 */ { MAD_F(0x06d11794) /* 0.426047876 */, 12 },
- /* 271 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 12 },
-
- /* 272 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 12 },
- /* 273 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 12 },
- /* 274 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 12 },
- /* 275 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 12 },
- /* 276 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 12 },
- /* 277 */ { MAD_F(0x070dacea) /* 0.440838732 */, 12 },
- /* 278 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 12 },
- /* 279 */ { MAD_F(0x071f1459) /* 0.445087765 */, 12 },
- /* 280 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 12 },
- /* 281 */ { MAD_F(0x07308671) /* 0.449346964 */, 12 },
- /* 282 */ { MAD_F(0x07394378) /* 0.451480360 */, 12 },
- /* 283 */ { MAD_F(0x07420325) /* 0.453616280 */, 12 },
- /* 284 */ { MAD_F(0x074ac575) /* 0.455754717 */, 12 },
- /* 285 */ { MAD_F(0x07538a67) /* 0.457895665 */, 12 },
- /* 286 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 12 },
- /* 287 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 12 },
-
- /* 288 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 12 },
- /* 289 */ { MAD_F(0x0776b867) /* 0.466484455 */, 12 },
- /* 290 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 12 },
- /* 291 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 12 },
- /* 292 */ { MAD_F(0x07913641) /* 0.472952132 */, 12 },
- /* 293 */ { MAD_F(0x079a100c) /* 0.475112962 */, 12 },
- /* 294 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 12 },
- /* 295 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 12 },
- /* 296 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 12 },
- /* 297 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 12 },
- /* 298 */ { MAD_F(0x07c67798) /* 0.485953899 */, 12 },
- /* 299 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 12 },
- /* 300 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 12 },
- /* 301 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 12 },
- /* 302 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 12 },
- /* 303 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 12 },
-
- /* 304 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 12 },
- /* 305 */ { MAD_F(0x0402868e) /* 0.250616605 */, 13 },
- /* 306 */ { MAD_F(0x040703ff) /* 0.251712795 */, 13 },
- /* 307 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 13 },
- /* 308 */ { MAD_F(0x041002a1) /* 0.253908756 */, 13 },
- /* 309 */ { MAD_F(0x041483d1) /* 0.255008523 */, 13 },
- /* 310 */ { MAD_F(0x04190640) /* 0.256109476 */, 13 },
- /* 311 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 13 },
- /* 312 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 13 },
- /* 313 */ { MAD_F(0x042694fe) /* 0.259419433 */, 13 },
- /* 314 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 13 },
- /* 315 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 13 },
- /* 316 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 13 },
- /* 317 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 13 },
- /* 318 */ { MAD_F(0x043d4635) /* 0.264959533 */, 13 },
- /* 319 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 13 },
-
- /* 320 */ { MAD_F(0x04466275) /* 0.267183742 */, 13 },
- /* 321 */ { MAD_F(0x044af269) /* 0.268297587 */, 13 },
- /* 322 */ { MAD_F(0x044f8393) /* 0.269412589 */, 13 },
- /* 323 */ { MAD_F(0x045415f3) /* 0.270528746 */, 13 },
- /* 324 */ { MAD_F(0x0458a989) /* 0.271646056 */, 13 },
- /* 325 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 13 },
- /* 326 */ { MAD_F(0x0461d451) /* 0.273884123 */, 13 },
- /* 327 */ { MAD_F(0x04666b83) /* 0.275004875 */, 13 },
- /* 328 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 13 },
- /* 329 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 13 },
- /* 330 */ { MAD_F(0x04743847) /* 0.278373983 */, 13 },
- /* 331 */ { MAD_F(0x0478d440) /* 0.279499294 */, 13 },
- /* 332 */ { MAD_F(0x047d716a) /* 0.280625739 */, 13 },
- /* 333 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 13 },
- /* 334 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 13 },
- /* 335 */ { MAD_F(0x048b5003) /* 0.284011853 */, 13 },
-
- /* 336 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 13 },
- /* 337 */ { MAD_F(0x049494fb) /* 0.286274891 */, 13 },
- /* 338 */ { MAD_F(0x0499393a) /* 0.287408091 */, 13 },
- /* 339 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 13 },
- /* 340 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 13 },
- /* 341 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 13 },
- /* 342 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 13 },
- /* 343 */ { MAD_F(0x04b08000) /* 0.293090820 */, 13 },
- /* 344 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 13 },
- /* 345 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 13 },
- /* 346 */ { MAD_F(0x04be8537) /* 0.296513762 */, 13 },
- /* 347 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 13 },
- /* 348 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 13 },
- /* 349 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 13 },
- /* 350 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 13 },
- /* 351 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 13 },
-
- /* 352 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 13 },
- /* 353 */ { MAD_F(0x04df6458) /* 0.304539056 */, 13 },
- /* 354 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 13 },
- /* 355 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 13 },
- /* 356 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 13 },
- /* 357 */ { MAD_F(0x04f24618) /* 0.309148880 */, 13 },
- /* 358 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 13 },
- /* 359 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 13 },
- /* 360 */ { MAD_F(0x05007b49) /* 0.312617576 */, 13 },
- /* 361 */ { MAD_F(0x050539ef) /* 0.313775954 */, 13 },
- /* 362 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 13 },
- /* 363 */ { MAD_F(0x050eba98) /* 0.316095920 */, 13 },
- /* 364 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 13 },
- /* 365 */ { MAD_F(0x05183fba) /* 0.318420150 */, 13 },
- /* 366 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 13 },
- /* 367 */ { MAD_F(0x0521c950) /* 0.320748629 */, 13 },
-
- /* 368 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 13 },
- /* 369 */ { MAD_F(0x052b5757) /* 0.323081342 */, 13 },
- /* 370 */ { MAD_F(0x05302003) /* 0.324249281 */, 13 },
- /* 371 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 13 },
- /* 372 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 13 },
- /* 373 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 13 },
- /* 374 */ { MAD_F(0x05434db9) /* 0.328931546 */, 13 },
- /* 375 */ { MAD_F(0x05481be5) /* 0.330104730 */, 13 },
- /* 376 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 13 },
- /* 377 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 13 },
- /* 378 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 13 },
- /* 379 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 13 },
- /* 380 */ { MAD_F(0x05603321) /* 0.335986261 */, 13 },
- /* 381 */ { MAD_F(0x056507d6) /* 0.337165677 */, 13 },
- /* 382 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 13 },
- /* 383 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 13 },
-
- /* 384 */ { MAD_F(0x05738c72) /* 0.340710111 */, 13 },
- /* 385 */ { MAD_F(0x05786578) /* 0.341893646 */, 13 },
- /* 386 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 13 },
- /* 387 */ { MAD_F(0x05821abf) /* 0.344263788 */, 13 },
- /* 388 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 13 },
- /* 389 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 13 },
- /* 390 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 13 },
- /* 391 */ { MAD_F(0x05959222) /* 0.349016318 */, 13 },
- /* 392 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 13 },
- /* 393 */ { MAD_F(0x059f5438) /* 0.351398678 */, 13 },
- /* 394 */ { MAD_F(0x05a436da) /* 0.352591376 */, 13 },
- /* 395 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 13 },
- /* 396 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 13 },
- /* 397 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 13 },
- /* 398 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 13 },
- /* 399 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 13 },
-
- /* 400 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 13 },
- /* 401 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 13 },
- /* 402 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 13 },
- /* 403 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 13 },
- /* 404 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 13 },
- /* 405 */ { MAD_F(0x05da394d) /* 0.365777304 */, 13 },
- /* 406 */ { MAD_F(0x05df2885) /* 0.366982004 */, 13 },
- /* 407 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 13 },
- /* 408 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 13 },
- /* 409 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 13 },
- /* 410 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 13 },
- /* 411 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 13 },
- /* 412 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 13 },
- /* 413 */ { MAD_F(0x0601d004) /* 0.375442522 */, 13 },
- /* 414 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 13 },
- /* 415 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 13 },
-
- /* 416 */ { MAD_F(0x0610b982) /* 0.379083164 */, 13 },
- /* 417 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 13 },
- /* 418 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 13 },
- /* 419 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 13 },
- /* 420 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 13 },
- /* 421 */ { MAD_F(0x0629a863) /* 0.385170352 */, 13 },
- /* 422 */ { MAD_F(0x062ea802) /* 0.386390694 */, 13 },
- /* 423 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 13 },
- /* 424 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 13 },
- /* 425 */ { MAD_F(0x063dacee) /* 0.390057497 */, 13 },
- /* 426 */ { MAD_F(0x0642b096) /* 0.391281687 */, 13 },
- /* 427 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 13 },
- /* 428 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 13 },
- /* 429 */ { MAD_F(0x0651c193) /* 0.394959999 */, 13 },
- /* 430 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 13 },
- /* 431 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 13 },
-
- /* 432 */ { MAD_F(0x0660db91) /* 0.398646895 */, 13 },
- /* 433 */ { MAD_F(0x0665e639) /* 0.399877761 */, 13 },
- /* 434 */ { MAD_F(0x066af1df) /* 0.401109575 */, 13 },
- /* 435 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 13 },
- /* 436 */ { MAD_F(0x06750c26) /* 0.403576041 */, 13 },
- /* 437 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 13 },
- /* 438 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 13 },
- /* 439 */ { MAD_F(0x06843afb) /* 0.407282813 */, 13 },
- /* 440 */ { MAD_F(0x06894c90) /* 0.408520284 */, 13 },
- /* 441 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 13 },
- /* 442 */ { MAD_F(0x069372ae) /* 0.410998038 */, 13 },
- /* 443 */ { MAD_F(0x06988735) /* 0.412238319 */, 13 },
- /* 444 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 13 },
- /* 445 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 13 },
- /* 446 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 13 },
- /* 447 */ { MAD_F(0x06ace318) /* 0.417208762 */, 13 },
-
- /* 448 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 13 },
- /* 449 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 13 },
- /* 450 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 13 },
- /* 451 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 13 },
- /* 452 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 13 },
- /* 453 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 13 },
- /* 454 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 13 },
- /* 455 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 13 },
- /* 456 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 13 },
- /* 457 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 13 },
- /* 458 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 13 },
- /* 459 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 13 },
- /* 460 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 13 },
- /* 461 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 13 },
- /* 462 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 13 },
- /* 463 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 13 },
-
- /* 464 */ { MAD_F(0x07041636) /* 0.438497744 */, 13 },
- /* 465 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 13 },
- /* 466 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 13 },
- /* 467 */ { MAD_F(0x07139641) /* 0.442281965 */, 13 },
- /* 468 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 13 },
- /* 469 */ { MAD_F(0x071df058) /* 0.444809288 */, 13 },
- /* 470 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 13 },
- /* 471 */ { MAD_F(0x07284e34) /* 0.447340205 */, 13 },
- /* 472 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 13 },
- /* 473 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 13 },
- /* 474 */ { MAD_F(0x0737e209) /* 0.451143300 */, 13 },
- /* 475 */ { MAD_F(0x073d1530) /* 0.452412785 */, 13 },
- /* 476 */ { MAD_F(0x07424946) /* 0.453683161 */, 13 },
- /* 477 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 13 },
- /* 478 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 13 },
- /* 479 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 13 },
-
- /* 480 */ { MAD_F(0x075722ef) /* 0.458773552 */, 13 },
- /* 481 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 13 },
- /* 482 */ { MAD_F(0x07619557) /* 0.461324062 */, 13 },
- /* 483 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 13 },
- /* 484 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 13 },
- /* 485 */ { MAD_F(0x077147e2) /* 0.465156443 */, 13 },
- /* 486 */ { MAD_F(0x0776853e) /* 0.466435663 */, 13 },
- /* 487 */ { MAD_F(0x077bc385) /* 0.467715761 */, 13 },
- /* 488 */ { MAD_F(0x078102b8) /* 0.468996735 */, 13 },
- /* 489 */ { MAD_F(0x078642d6) /* 0.470278584 */, 13 },
- /* 490 */ { MAD_F(0x078b83de) /* 0.471561307 */, 13 },
- /* 491 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 13 },
- /* 492 */ { MAD_F(0x079608ae) /* 0.474129372 */, 13 },
- /* 493 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 13 },
- /* 494 */ { MAD_F(0x07a09124) /* 0.476700918 */, 13 },
- /* 495 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 13 },
-
- /* 496 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 13 },
- /* 497 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 13 },
- /* 498 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 13 },
- /* 499 */ { MAD_F(0x07baf635) /* 0.483144957 */, 13 },
- /* 500 */ { MAD_F(0x07c04056) /* 0.484436356 */, 13 },
- /* 501 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 13 },
- /* 502 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 13 },
- /* 503 */ { MAD_F(0x07d02424) /* 0.488315717 */, 13 },
- /* 504 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 13 },
- /* 505 */ { MAD_F(0x07dac083) /* 0.490906249 */, 13 },
- /* 506 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 13 },
- /* 507 */ { MAD_F(0x07e56078) /* 0.493500203 */, 13 },
- /* 508 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 13 },
- /* 509 */ { MAD_F(0x07f00401) /* 0.496097570 */, 13 },
- /* 510 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 13 },
- /* 511 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 13 },
-
- /* 512 */ { MAD_F(0x04000000) /* 0.250000000 */, 14 },
- /* 513 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 14 },
- /* 514 */ { MAD_F(0x04055638) /* 0.251302930 */, 14 },
- /* 515 */ { MAD_F(0x040801ff) /* 0.251955030 */, 14 },
- /* 516 */ { MAD_F(0x040aae37) /* 0.252607552 */, 14 },
- /* 517 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 14 },
- /* 518 */ { MAD_F(0x041007fa) /* 0.253913860 */, 14 },
- /* 519 */ { MAD_F(0x0412b586) /* 0.254567645 */, 14 },
- /* 520 */ { MAD_F(0x04156381) /* 0.255221850 */, 14 },
- /* 521 */ { MAD_F(0x041811ee) /* 0.255876475 */, 14 },
- /* 522 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 14 },
- /* 523 */ { MAD_F(0x041d7018) /* 0.257186980 */, 14 },
- /* 524 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 14 },
- /* 525 */ { MAD_F(0x0422d003) /* 0.258499157 */, 14 },
- /* 526 */ { MAD_F(0x042580a0) /* 0.259155872 */, 14 },
- /* 527 */ { MAD_F(0x042831ad) /* 0.259813002 */, 14 },
-
- /* 528 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 14 },
- /* 529 */ { MAD_F(0x042d9516) /* 0.261128510 */, 14 },
- /* 530 */ { MAD_F(0x04304772) /* 0.261786886 */, 14 },
- /* 531 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 14 },
- /* 532 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 14 },
- /* 533 */ { MAD_F(0x0438611f) /* 0.263764497 */, 14 },
- /* 534 */ { MAD_F(0x043b1536) /* 0.264424527 */, 14 },
- /* 535 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 14 },
- /* 536 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 14 },
- /* 537 */ { MAD_F(0x04433414) /* 0.266407088 */, 14 },
- /* 538 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 14 },
- /* 539 */ { MAD_F(0x0448a024) /* 0.267730848 */, 14 },
- /* 540 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 14 },
- /* 541 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 14 },
- /* 542 */ { MAD_F(0x0450c575) /* 0.269719560 */, 14 },
- /* 543 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 14 },
-
- /* 544 */ { MAD_F(0x045635cf) /* 0.271047409 */, 14 },
- /* 545 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 14 },
- /* 546 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 14 },
- /* 547 */ { MAD_F(0x045e6188) /* 0.273042234 */, 14 },
- /* 548 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 14 },
- /* 549 */ { MAD_F(0x0463d625) /* 0.274374147 */, 14 },
- /* 550 */ { MAD_F(0x04669116) /* 0.275040710 */, 14 },
- /* 551 */ { MAD_F(0x04694c74) /* 0.275707677 */, 14 },
- /* 552 */ { MAD_F(0x046c083e) /* 0.276375048 */, 14 },
- /* 553 */ { MAD_F(0x046ec474) /* 0.277042822 */, 14 },
- /* 554 */ { MAD_F(0x04718116) /* 0.277710999 */, 14 },
- /* 555 */ { MAD_F(0x04743e25) /* 0.278379578 */, 14 },
- /* 556 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 14 },
- /* 557 */ { MAD_F(0x0479b984) /* 0.279717940 */, 14 },
- /* 558 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 14 },
- /* 559 */ { MAD_F(0x047f3693) /* 0.281057905 */, 14 },
-
- /* 560 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 14 },
- /* 561 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 14 },
- /* 562 */ { MAD_F(0x0487754c) /* 0.283070849 */, 14 },
- /* 563 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 14 },
- /* 564 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 14 },
- /* 565 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 14 },
- /* 566 */ { MAD_F(0x04927972) /* 0.285760350 */, 14 },
- /* 567 */ { MAD_F(0x04953b85) /* 0.286433717 */, 14 },
- /* 568 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 14 },
- /* 569 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 14 },
- /* 570 */ { MAD_F(0x049d843e) /* 0.288456194 */, 14 },
- /* 571 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 14 },
- /* 572 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 14 },
- /* 573 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 14 },
- /* 574 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 14 },
- /* 575 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 14 },
-
- /* 576 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 14 },
- /* 577 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 14 },
- /* 578 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 14 },
- /* 579 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 14 },
- /* 580 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 14 },
- /* 581 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 14 },
- /* 582 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 14 },
- /* 583 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 14 },
- /* 584 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 14 },
- /* 585 */ { MAD_F(0x04c72771) /* 0.298621598 */, 14 },
- /* 586 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 14 },
- /* 587 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 14 },
- /* 588 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 14 },
- /* 589 */ { MAD_F(0x04d25169) /* 0.301347172 */, 14 },
- /* 590 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 14 },
- /* 591 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 14 },
-
- /* 592 */ { MAD_F(0x04dab524) /* 0.303395408 */, 14 },
- /* 593 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 14 },
- /* 594 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 14 },
- /* 595 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 14 },
- /* 596 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 14 },
- /* 597 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 14 },
- /* 598 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 14 },
- /* 599 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 14 },
- /* 600 */ { MAD_F(0x04f12624) /* 0.308874267 */, 14 },
- /* 601 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 14 },
- /* 602 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 14 },
- /* 603 */ { MAD_F(0x04f99721) /* 0.310935143 */, 14 },
- /* 604 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 14 },
- /* 605 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 14 },
- /* 606 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 14 },
- /* 607 */ { MAD_F(0x0504de05) /* 0.313688296 */, 14 },
-
- /* 608 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 14 },
- /* 609 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 14 },
- /* 610 */ { MAD_F(0x050d575b) /* 0.315757136 */, 14 },
- /* 611 */ { MAD_F(0x05102b42) /* 0.316447504 */, 14 },
- /* 612 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 14 },
- /* 613 */ { MAD_F(0x0515d440) /* 0.317829370 */, 14 },
- /* 614 */ { MAD_F(0x0518a956) /* 0.318520867 */, 14 },
- /* 615 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 14 },
- /* 616 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 14 },
- /* 617 */ { MAD_F(0x05212af5) /* 0.320597609 */, 14 },
- /* 618 */ { MAD_F(0x0524019e) /* 0.321290606 */, 14 },
- /* 619 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 14 },
- /* 620 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 14 },
- /* 621 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 14 },
- /* 622 */ { MAD_F(0x052f602c) /* 0.324066327 */, 14 },
- /* 623 */ { MAD_F(0x053238ca) /* 0.324761189 */, 14 },
-
- /* 624 */ { MAD_F(0x053511cb) /* 0.325456423 */, 14 },
- /* 625 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 14 },
- /* 626 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 14 },
- /* 627 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 14 },
- /* 628 */ { MAD_F(0x054079b5) /* 0.328241070 */, 14 },
- /* 629 */ { MAD_F(0x054354a8) /* 0.328938157 */, 14 },
- /* 630 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 14 },
- /* 631 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 14 },
- /* 632 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 14 },
- /* 633 */ { MAD_F(0x054ec453) /* 0.331730198 */, 14 },
- /* 634 */ { MAD_F(0x0551a134) /* 0.332429129 */, 14 },
- /* 635 */ { MAD_F(0x05547e79) /* 0.333128427 */, 14 },
- /* 636 */ { MAD_F(0x05575c20) /* 0.333828093 */, 14 },
- /* 637 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 14 },
- /* 638 */ { MAD_F(0x055d1896) /* 0.335228525 */, 14 },
- /* 639 */ { MAD_F(0x055ff764) /* 0.335929290 */, 14 },
-
- /* 640 */ { MAD_F(0x0562d694) /* 0.336630420 */, 14 },
- /* 641 */ { MAD_F(0x0565b627) /* 0.337331916 */, 14 },
- /* 642 */ { MAD_F(0x0568961b) /* 0.338033777 */, 14 },
- /* 643 */ { MAD_F(0x056b7671) /* 0.338736002 */, 14 },
- /* 644 */ { MAD_F(0x056e5729) /* 0.339438592 */, 14 },
- /* 645 */ { MAD_F(0x05713843) /* 0.340141545 */, 14 },
- /* 646 */ { MAD_F(0x057419be) /* 0.340844862 */, 14 },
- /* 647 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 14 },
- /* 648 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 14 },
- /* 649 */ { MAD_F(0x057cc077) /* 0.342956988 */, 14 },
- /* 650 */ { MAD_F(0x057fa378) /* 0.343661754 */, 14 },
- /* 651 */ { MAD_F(0x058286d9) /* 0.344366882 */, 14 },
- /* 652 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 14 },
- /* 653 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 14 },
- /* 654 */ { MAD_F(0x058b3342) /* 0.346484431 */, 14 },
- /* 655 */ { MAD_F(0x058e1827) /* 0.347191002 */, 14 },
-
- /* 656 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 14 },
- /* 657 */ { MAD_F(0x0593e311) /* 0.348605221 */, 14 },
- /* 658 */ { MAD_F(0x0596c917) /* 0.349312869 */, 14 },
- /* 659 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 14 },
- /* 660 */ { MAD_F(0x059c9643) /* 0.350729240 */, 14 },
- /* 661 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 14 },
- /* 662 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 14 },
- /* 663 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 14 },
- /* 664 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 14 },
- /* 665 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 14 },
- /* 666 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 14 },
- /* 667 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 14 },
- /* 668 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 14 },
- /* 669 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 14 },
- /* 670 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 14 },
- /* 671 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 14 },
-
- /* 672 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 14 },
- /* 673 */ { MAD_F(0x05c27057) /* 0.359970419 */, 14 },
- /* 674 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 14 },
- /* 675 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 14 },
- /* 676 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 14 },
- /* 677 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 14 },
- /* 678 */ { MAD_F(0x05d11001) /* 0.363540655 */, 14 },
- /* 679 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 14 },
- /* 680 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 14 },
- /* 681 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 14 },
- /* 682 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 14 },
- /* 683 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 14 },
- /* 684 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 14 },
- /* 685 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 14 },
- /* 686 */ { MAD_F(0x05e88904) /* 0.369271294 */, 14 },
- /* 687 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 14 },
-
- /* 688 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 14 },
- /* 689 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 14 },
- /* 690 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 14 },
- /* 691 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 14 },
- /* 692 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 14 },
- /* 693 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 14 },
- /* 694 */ { MAD_F(0x0600196e) /* 0.375024253 */, 14 },
- /* 695 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 14 },
- /* 696 */ { MAD_F(0x0606012b) /* 0.376465960 */, 14 },
- /* 697 */ { MAD_F(0x0608f595) /* 0.377187332 */, 14 },
- /* 698 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 14 },
- /* 699 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 14 },
- /* 700 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 14 },
- /* 701 */ { MAD_F(0x0614cada) /* 0.380076266 */, 14 },
- /* 702 */ { MAD_F(0x0617c112) /* 0.380799360 */, 14 },
- /* 703 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 14 },
-
- /* 704 */ { MAD_F(0x061dae96) /* 0.382246578 */, 14 },
- /* 705 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 14 },
- /* 706 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 14 },
- /* 707 */ { MAD_F(0x0626958f) /* 0.384419975 */, 14 },
- /* 708 */ { MAD_F(0x06298def) /* 0.385145124 */, 14 },
- /* 709 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 14 },
- /* 710 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 14 },
- /* 711 */ { MAD_F(0x06327934) /* 0.387322621 */, 14 },
- /* 712 */ { MAD_F(0x06357302) /* 0.388049134 */, 14 },
- /* 713 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 14 },
- /* 714 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 14 },
- /* 715 */ { MAD_F(0x063e6290) /* 0.390230715 */, 14 },
- /* 716 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 14 },
- /* 717 */ { MAD_F(0x06445960) /* 0.391686799 */, 14 },
- /* 718 */ { MAD_F(0x06475551) /* 0.392415349 */, 14 },
- /* 719 */ { MAD_F(0x064a519c) /* 0.393144238 */, 14 },
-
- /* 720 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 14 },
- /* 721 */ { MAD_F(0x06504b44) /* 0.394603028 */, 14 },
- /* 722 */ { MAD_F(0x0653489f) /* 0.395332930 */, 14 },
- /* 723 */ { MAD_F(0x06564655) /* 0.396063168 */, 14 },
- /* 724 */ { MAD_F(0x06594465) /* 0.396793743 */, 14 },
- /* 725 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 14 },
- /* 726 */ { MAD_F(0x065f4195) /* 0.398255903 */, 14 },
- /* 727 */ { MAD_F(0x066240b4) /* 0.398987487 */, 14 },
- /* 728 */ { MAD_F(0x0665402d) /* 0.399719406 */, 14 },
- /* 729 */ { MAD_F(0x06684000) /* 0.400451660 */, 14 },
- /* 730 */ { MAD_F(0x066b402d) /* 0.401184249 */, 14 },
- /* 731 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 14 },
- /* 732 */ { MAD_F(0x06714194) /* 0.402650431 */, 14 },
- /* 733 */ { MAD_F(0x067442ce) /* 0.403384024 */, 14 },
- /* 734 */ { MAD_F(0x06774462) /* 0.404117949 */, 14 },
- /* 735 */ { MAD_F(0x067a464f) /* 0.404852209 */, 14 },
-
- /* 736 */ { MAD_F(0x067d4896) /* 0.405586801 */, 14 },
- /* 737 */ { MAD_F(0x06804b36) /* 0.406321726 */, 14 },
- /* 738 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 14 },
- /* 739 */ { MAD_F(0x06865181) /* 0.407792573 */, 14 },
- /* 740 */ { MAD_F(0x0689552c) /* 0.408528495 */, 14 },
- /* 741 */ { MAD_F(0x068c5931) /* 0.409264748 */, 14 },
- /* 742 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 14 },
- /* 743 */ { MAD_F(0x06926245) /* 0.410738247 */, 14 },
- /* 744 */ { MAD_F(0x06956753) /* 0.411475493 */, 14 },
- /* 745 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 14 },
- /* 746 */ { MAD_F(0x069b727b) /* 0.412950976 */, 14 },
- /* 747 */ { MAD_F(0x069e7894) /* 0.413689213 */, 14 },
- /* 748 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 14 },
- /* 749 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 14 },
- /* 750 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 14 },
- /* 751 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 14 },
-
- /* 752 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 14 },
- /* 753 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 14 },
- /* 754 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 14 },
- /* 755 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 14 },
- /* 756 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 14 },
- /* 757 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 14 },
- /* 758 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 14 },
- /* 759 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 14 },
- /* 760 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 14 },
- /* 761 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 14 },
- /* 762 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 14 },
- /* 763 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 14 },
- /* 764 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 14 },
- /* 765 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 14 },
- /* 766 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 14 },
- /* 767 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 14 },
-
- /* 768 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 14 },
- /* 769 */ { MAD_F(0x06e15595) /* 0.430013259 */, 14 },
- /* 770 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 14 },
- /* 771 */ { MAD_F(0x06e771db) /* 0.431505065 */, 14 },
- /* 772 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 14 },
- /* 773 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 14 },
- /* 774 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 14 },
- /* 775 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 14 },
- /* 776 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 14 },
- /* 777 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 14 },
- /* 778 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 14 },
- /* 779 */ { MAD_F(0x06fff073) /* 0.437485172 */, 14 },
- /* 780 */ { MAD_F(0x070301ca) /* 0.438234130 */, 14 },
- /* 781 */ { MAD_F(0x07061377) /* 0.438983408 */, 14 },
- /* 782 */ { MAD_F(0x0709257a) /* 0.439733006 */, 14 },
- /* 783 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 14 },
-
- /* 784 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 14 },
- /* 785 */ { MAD_F(0x07125d84) /* 0.441983717 */, 14 },
- /* 786 */ { MAD_F(0x071570de) /* 0.442734592 */, 14 },
- /* 787 */ { MAD_F(0x0718848d) /* 0.443485785 */, 14 },
- /* 788 */ { MAD_F(0x071b9891) /* 0.444237296 */, 14 },
- /* 789 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 14 },
- /* 790 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 14 },
- /* 791 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 14 },
- /* 792 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 14 },
- /* 793 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 14 },
- /* 794 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 14 },
- /* 795 */ { MAD_F(0x07312e01) /* 0.449506765 */, 14 },
- /* 796 */ { MAD_F(0x073444ae) /* 0.450260813 */, 14 },
- /* 797 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 14 },
- /* 798 */ { MAD_F(0x073a7307) /* 0.451769856 */, 14 },
- /* 799 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 14 },
-
- /* 800 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 14 },
- /* 801 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 14 },
- /* 802 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 14 },
- /* 803 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 14 },
- /* 804 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 14 },
- /* 805 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 14 },
- /* 806 */ { MAD_F(0x0753399d) /* 0.457818618 */, 14 },
- /* 807 */ { MAD_F(0x075653eb) /* 0.458576125 */, 14 },
- /* 808 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 14 },
- /* 809 */ { MAD_F(0x075c8983) /* 0.460092079 */, 14 },
- /* 810 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 14 },
- /* 811 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 14 },
- /* 812 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 14 },
- /* 813 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 14 },
- /* 814 */ { MAD_F(0x076c1538) /* 0.463887426 */, 14 },
- /* 815 */ { MAD_F(0x076f3224) /* 0.464647430 */, 14 },
-
- /* 816 */ { MAD_F(0x07724f64) /* 0.465407744 */, 14 },
- /* 817 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 14 },
- /* 818 */ { MAD_F(0x07788add) /* 0.466929306 */, 14 },
- /* 819 */ { MAD_F(0x077ba916) /* 0.467690552 */, 14 },
- /* 820 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 14 },
- /* 821 */ { MAD_F(0x0781e683) /* 0.469213973 */, 14 },
- /* 822 */ { MAD_F(0x078505b5) /* 0.469976148 */, 14 },
- /* 823 */ { MAD_F(0x0788253b) /* 0.470738632 */, 14 },
- /* 824 */ { MAD_F(0x078b4514) /* 0.471501425 */, 14 },
- /* 825 */ { MAD_F(0x078e653f) /* 0.472264527 */, 14 },
- /* 826 */ { MAD_F(0x079185be) /* 0.473027937 */, 14 },
- /* 827 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 14 },
- /* 828 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 14 },
- /* 829 */ { MAD_F(0x079ae929) /* 0.475320014 */, 14 },
- /* 830 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 14 },
- /* 831 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 14 },
-
- /* 832 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 14 },
- /* 833 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 14 },
- /* 834 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 14 },
- /* 835 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 14 },
- /* 836 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 14 },
- /* 837 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 14 },
- /* 838 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 14 },
- /* 839 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 14 },
- /* 840 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 14 },
- /* 841 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 14 },
- /* 842 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 14 },
- /* 843 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 14 },
- /* 844 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 14 },
- /* 845 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 14 },
- /* 846 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 14 },
- /* 847 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 14 },
-
- /* 848 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 14 },
- /* 849 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 14 },
- /* 850 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 14 },
- /* 851 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 14 },
- /* 852 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 14 },
- /* 853 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 14 },
- /* 854 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 14 },
- /* 855 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 14 },
- /* 856 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 14 },
- /* 857 */ { MAD_F(0x07f31405) /* 0.496845266 */, 14 },
- /* 858 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 14 },
- /* 859 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 14 },
- /* 860 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 14 },
- /* 861 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 14 },
- /* 862 */ { MAD_F(0x04017659) /* 0.250357008 */, 15 },
- /* 863 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 15 },
-
- /* 864 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 15 },
- /* 865 */ { MAD_F(0x0406393d) /* 0.251519431 */, 15 },
- /* 866 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 15 },
- /* 867 */ { MAD_F(0x0409669d) /* 0.252295127 */, 15 },
- /* 868 */ { MAD_F(0x040afd89) /* 0.252683198 */, 15 },
- /* 869 */ { MAD_F(0x040c949e) /* 0.253071419 */, 15 },
- /* 870 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 15 },
- /* 871 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 15 },
- /* 872 */ { MAD_F(0x04115aca) /* 0.254236974 */, 15 },
- /* 873 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 15 },
- /* 874 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 15 },
- /* 875 */ { MAD_F(0x0416225d) /* 0.255403867 */, 15 },
- /* 876 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 15 },
- /* 877 */ { MAD_F(0x041952dc) /* 0.256182537 */, 15 },
- /* 878 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 15 },
- /* 879 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 15 },
-
- /* 880 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 15 },
- /* 881 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 15 },
- /* 882 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 15 },
- /* 883 */ { MAD_F(0x0422e811) /* 0.258522097 */, 15 },
- /* 884 */ { MAD_F(0x04248179) /* 0.258912540 */, 15 },
- /* 885 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 15 },
- /* 886 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 15 },
- /* 887 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 15 },
- /* 888 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 15 },
- /* 889 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 15 },
- /* 890 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 15 },
- /* 891 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 15 },
- /* 892 */ { MAD_F(0x0431524c) /* 0.262041376 */, 15 },
- /* 893 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 15 },
- /* 894 */ { MAD_F(0x0434880a) /* 0.262825051 */, 15 },
- /* 895 */ { MAD_F(0x04362324) /* 0.263217107 */, 15 },
-
- /* 896 */ { MAD_F(0x0437be65) /* 0.263609310 */, 15 },
- /* 897 */ { MAD_F(0x043959cd) /* 0.264001659 */, 15 },
- /* 898 */ { MAD_F(0x043af55d) /* 0.264394153 */, 15 },
- /* 899 */ { MAD_F(0x043c9113) /* 0.264786794 */, 15 },
- /* 900 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 15 },
- /* 901 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 15 },
- /* 902 */ { MAD_F(0x04416522) /* 0.265965588 */, 15 },
- /* 903 */ { MAD_F(0x04430174) /* 0.266358810 */, 15 },
- /* 904 */ { MAD_F(0x04449dee) /* 0.266752177 */, 15 },
- /* 905 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 15 },
- /* 906 */ { MAD_F(0x0447d756) /* 0.267539347 */, 15 },
- /* 907 */ { MAD_F(0x04497445) /* 0.267933149 */, 15 },
- /* 908 */ { MAD_F(0x044b115a) /* 0.268327096 */, 15 },
- /* 909 */ { MAD_F(0x044cae96) /* 0.268721187 */, 15 },
- /* 910 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 15 },
- /* 911 */ { MAD_F(0x044fe983) /* 0.269509804 */, 15 },
-
- /* 912 */ { MAD_F(0x04518733) /* 0.269904329 */, 15 },
- /* 913 */ { MAD_F(0x0453250a) /* 0.270298998 */, 15 },
- /* 914 */ { MAD_F(0x0454c308) /* 0.270693811 */, 15 },
- /* 915 */ { MAD_F(0x0456612d) /* 0.271088768 */, 15 },
- /* 916 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 15 },
- /* 917 */ { MAD_F(0x04599dea) /* 0.271879114 */, 15 },
- /* 918 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 15 },
- /* 919 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 15 },
- /* 920 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 15 },
- /* 921 */ { MAD_F(0x04601932) /* 0.273461530 */, 15 },
- /* 922 */ { MAD_F(0x0461b864) /* 0.273857492 */, 15 },
- /* 923 */ { MAD_F(0x046357bd) /* 0.274253597 */, 15 },
- /* 924 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 15 },
- /* 925 */ { MAD_F(0x046696e2) /* 0.275046238 */, 15 },
- /* 926 */ { MAD_F(0x046836ae) /* 0.275442772 */, 15 },
- /* 927 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 15 },
-
- /* 928 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 15 },
- /* 929 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 15 },
- /* 930 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 15 },
- /* 931 */ { MAD_F(0x047057e8) /* 0.277427584 */, 15 },
- /* 932 */ { MAD_F(0x0471f899) /* 0.277824973 */, 15 },
- /* 933 */ { MAD_F(0x04739971) /* 0.278222505 */, 15 },
- /* 934 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 15 },
- /* 935 */ { MAD_F(0x0476db92) /* 0.279017995 */, 15 },
- /* 936 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 15 },
- /* 937 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 15 },
- /* 938 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 15 },
- /* 939 */ { MAD_F(0x047d619e) /* 0.280610675 */, 15 },
- /* 940 */ { MAD_F(0x047f0380) /* 0.281009199 */, 15 },
- /* 941 */ { MAD_F(0x0480a588) /* 0.281407864 */, 15 },
- /* 942 */ { MAD_F(0x048247b6) /* 0.281806670 */, 15 },
- /* 943 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 15 },
-
- /* 944 */ { MAD_F(0x04858c83) /* 0.282604707 */, 15 },
- /* 945 */ { MAD_F(0x04872f22) /* 0.283003936 */, 15 },
- /* 946 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 15 },
- /* 947 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 15 },
- /* 948 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 15 },
- /* 949 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 15 },
- /* 950 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 15 },
- /* 951 */ { MAD_F(0x049101f8) /* 0.285402269 */, 15 },
- /* 952 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 15 },
- /* 953 */ { MAD_F(0x0494496c) /* 0.286202836 */, 15 },
- /* 954 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 15 },
- /* 955 */ { MAD_F(0x04979177) /* 0.287003963 */, 15 },
- /* 956 */ { MAD_F(0x049935b5) /* 0.287404737 */, 15 },
- /* 957 */ { MAD_F(0x049ada19) /* 0.287805650 */, 15 },
- /* 958 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 15 },
- /* 959 */ { MAD_F(0x049e2350) /* 0.288607895 */, 15 },
-
- /* 960 */ { MAD_F(0x049fc824) /* 0.289009227 */, 15 },
- /* 961 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 15 },
- /* 962 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 15 },
- /* 963 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 15 },
- /* 964 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 15 },
- /* 965 */ { MAD_F(0x04a80277) /* 0.291017976 */, 15 },
- /* 966 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 15 },
- /* 967 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 15 },
- /* 968 */ { MAD_F(0x04acf402) /* 0.292224893 */, 15 },
- /* 969 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 15 },
- /* 970 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 15 },
- /* 971 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 15 },
- /* 972 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 15 },
- /* 973 */ { MAD_F(0x04b53427) /* 0.294239192 */, 15 },
- /* 974 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 15 },
- /* 975 */ { MAD_F(0x04b88207) /* 0.295045879 */, 15 },
-
- /* 976 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 15 },
- /* 977 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 15 },
- /* 978 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 15 },
- /* 979 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 15 },
- /* 980 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 15 },
- /* 981 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 15 },
- /* 982 */ { MAD_F(0x04c41722) /* 0.297873624 */, 15 },
- /* 983 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 15 },
- /* 984 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 15 },
- /* 985 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 15 },
- /* 986 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 15 },
- /* 987 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 15 },
- /* 988 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 15 },
- /* 989 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 15 },
- /* 990 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 15 },
- /* 991 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 15 },
-
- /* 992 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 15 },
- /* 993 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 15 },
- /* 994 */ { MAD_F(0x04d80290) /* 0.302736820 */, 15 },
- /* 995 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 15 },
- /* 996 */ { MAD_F(0x04db5679) /* 0.303549263 */, 15 },
- /* 997 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 15 },
- /* 998 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 15 },
- /* 999 */ { MAD_F(0x04e05567) /* 0.304768948 */, 15 },
- /* 1000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 15 },
- /* 1001 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 15 },
- /* 1002 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 15 },
- /* 1003 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 15 },
- /* 1004 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 15 },
- /* 1005 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 15 },
- /* 1006 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 15 },
- /* 1007 */ { MAD_F(0x04edae25) /* 0.308027406 */, 15 },
-
- /* 1008 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 15 },
- /* 1009 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 15 },
- /* 1010 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 15 },
- /* 1011 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 15 },
- /* 1012 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 15 },
- /* 1013 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 15 },
- /* 1014 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 15 },
- /* 1015 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 15 },
- /* 1016 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 15 },
- /* 1017 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 15 },
- /* 1018 */ { MAD_F(0x050016f3) /* 0.312521885 */, 15 },
- /* 1019 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 15 },
- /* 1020 */ { MAD_F(0x050371a7) /* 0.313340809 */, 15 },
- /* 1021 */ { MAD_F(0x05051f37) /* 0.313750472 */, 15 },
- /* 1022 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 15 },
- /* 1023 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 15 },
-
- /* 1024 */ { MAD_F(0x050a28be) /* 0.314980262 */, 15 },
- /* 1025 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 15 },
- /* 1026 */ { MAD_F(0x050d8521) /* 0.315800790 */, 15 },
- /* 1027 */ { MAD_F(0x050f3388) /* 0.316211255 */, 15 },
- /* 1028 */ { MAD_F(0x0510e213) /* 0.316621852 */, 15 },
- /* 1029 */ { MAD_F(0x051290c2) /* 0.317032582 */, 15 },
- /* 1030 */ { MAD_F(0x05143f94) /* 0.317443446 */, 15 },
- /* 1031 */ { MAD_F(0x0515ee8a) /* 0.317854442 */, 15 },
- /* 1032 */ { MAD_F(0x05179da4) /* 0.318265572 */, 15 },
- /* 1033 */ { MAD_F(0x05194ce1) /* 0.318676834 */, 15 },
- /* 1034 */ { MAD_F(0x051afc42) /* 0.319088229 */, 15 },
- /* 1035 */ { MAD_F(0x051cabc7) /* 0.319499756 */, 15 },
- /* 1036 */ { MAD_F(0x051e5b6f) /* 0.319911417 */, 15 },
- /* 1037 */ { MAD_F(0x05200b3a) /* 0.320323209 */, 15 },
- /* 1038 */ { MAD_F(0x0521bb2a) /* 0.320735134 */, 15 },
- /* 1039 */ { MAD_F(0x05236b3d) /* 0.321147192 */, 15 },
-
- /* 1040 */ { MAD_F(0x05251b73) /* 0.321559381 */, 15 },
- /* 1041 */ { MAD_F(0x0526cbcd) /* 0.321971703 */, 15 },
- /* 1042 */ { MAD_F(0x05287c4a) /* 0.322384156 */, 15 },
- /* 1043 */ { MAD_F(0x052a2cea) /* 0.322796742 */, 15 },
- /* 1044 */ { MAD_F(0x052bddae) /* 0.323209460 */, 15 },
- /* 1045 */ { MAD_F(0x052d8e96) /* 0.323622309 */, 15 },
- /* 1046 */ { MAD_F(0x052f3fa1) /* 0.324035290 */, 15 },
- /* 1047 */ { MAD_F(0x0530f0cf) /* 0.324448403 */, 15 },
- /* 1048 */ { MAD_F(0x0532a220) /* 0.324861647 */, 15 },
- /* 1049 */ { MAD_F(0x05345395) /* 0.325275023 */, 15 },
- /* 1050 */ { MAD_F(0x0536052d) /* 0.325688530 */, 15 },
- /* 1051 */ { MAD_F(0x0537b6e8) /* 0.326102168 */, 15 },
- /* 1052 */ { MAD_F(0x053968c6) /* 0.326515938 */, 15 },
- /* 1053 */ { MAD_F(0x053b1ac8) /* 0.326929839 */, 15 },
- /* 1054 */ { MAD_F(0x053ccced) /* 0.327343870 */, 15 },
- /* 1055 */ { MAD_F(0x053e7f35) /* 0.327758033 */, 15 },
-
- /* 1056 */ { MAD_F(0x054031a0) /* 0.328172327 */, 15 },
- /* 1057 */ { MAD_F(0x0541e42e) /* 0.328586751 */, 15 },
- /* 1058 */ { MAD_F(0x054396df) /* 0.329001306 */, 15 },
- /* 1059 */ { MAD_F(0x054549b4) /* 0.329415992 */, 15 },
- /* 1060 */ { MAD_F(0x0546fcab) /* 0.329830808 */, 15 },
- /* 1061 */ { MAD_F(0x0548afc6) /* 0.330245755 */, 15 },
- /* 1062 */ { MAD_F(0x054a6303) /* 0.330660832 */, 15 },
- /* 1063 */ { MAD_F(0x054c1663) /* 0.331076039 */, 15 },
- /* 1064 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 15 },
- /* 1065 */ { MAD_F(0x054f7d8d) /* 0.331906845 */, 15 },
- /* 1066 */ { MAD_F(0x05513156) /* 0.332322443 */, 15 },
- /* 1067 */ { MAD_F(0x0552e542) /* 0.332738170 */, 15 },
- /* 1068 */ { MAD_F(0x05549951) /* 0.333154028 */, 15 },
- /* 1069 */ { MAD_F(0x05564d83) /* 0.333570016 */, 15 },
- /* 1070 */ { MAD_F(0x055801d8) /* 0.333986133 */, 15 },
- /* 1071 */ { MAD_F(0x0559b64f) /* 0.334402380 */, 15 },
-
- /* 1072 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 15 },
- /* 1073 */ { MAD_F(0x055d1fa6) /* 0.335235262 */, 15 },
- /* 1074 */ { MAD_F(0x055ed486) /* 0.335651898 */, 15 },
- /* 1075 */ { MAD_F(0x05608988) /* 0.336068662 */, 15 },
- /* 1076 */ { MAD_F(0x05623ead) /* 0.336485556 */, 15 },
- /* 1077 */ { MAD_F(0x0563f3f5) /* 0.336902579 */, 15 },
- /* 1078 */ { MAD_F(0x0565a960) /* 0.337319732 */, 15 },
- /* 1079 */ { MAD_F(0x05675eed) /* 0.337737013 */, 15 },
- /* 1080 */ { MAD_F(0x0569149c) /* 0.338154423 */, 15 },
- /* 1081 */ { MAD_F(0x056aca6f) /* 0.338571962 */, 15 },
- /* 1082 */ { MAD_F(0x056c8064) /* 0.338989630 */, 15 },
- /* 1083 */ { MAD_F(0x056e367b) /* 0.339407426 */, 15 },
- /* 1084 */ { MAD_F(0x056fecb5) /* 0.339825351 */, 15 },
- /* 1085 */ { MAD_F(0x0571a311) /* 0.340243405 */, 15 },
- /* 1086 */ { MAD_F(0x05735990) /* 0.340661587 */, 15 },
- /* 1087 */ { MAD_F(0x05751032) /* 0.341079898 */, 15 },
-
- /* 1088 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 15 },
- /* 1089 */ { MAD_F(0x05787ddc) /* 0.341916903 */, 15 },
- /* 1090 */ { MAD_F(0x057a34e4) /* 0.342335598 */, 15 },
- /* 1091 */ { MAD_F(0x057bec0f) /* 0.342754421 */, 15 },
- /* 1092 */ { MAD_F(0x057da35d) /* 0.343173373 */, 15 },
- /* 1093 */ { MAD_F(0x057f5acc) /* 0.343592452 */, 15 },
- /* 1094 */ { MAD_F(0x0581125e) /* 0.344011659 */, 15 },
- /* 1095 */ { MAD_F(0x0582ca12) /* 0.344430993 */, 15 },
- /* 1096 */ { MAD_F(0x058481e9) /* 0.344850455 */, 15 },
- /* 1097 */ { MAD_F(0x058639e2) /* 0.345270045 */, 15 },
- /* 1098 */ { MAD_F(0x0587f1fd) /* 0.345689763 */, 15 },
- /* 1099 */ { MAD_F(0x0589aa3a) /* 0.346109608 */, 15 },
- /* 1100 */ { MAD_F(0x058b629a) /* 0.346529580 */, 15 },
- /* 1101 */ { MAD_F(0x058d1b1b) /* 0.346949679 */, 15 },
- /* 1102 */ { MAD_F(0x058ed3bf) /* 0.347369906 */, 15 },
- /* 1103 */ { MAD_F(0x05908c85) /* 0.347790260 */, 15 },
-
- /* 1104 */ { MAD_F(0x0592456d) /* 0.348210741 */, 15 },
- /* 1105 */ { MAD_F(0x0593fe77) /* 0.348631348 */, 15 },
- /* 1106 */ { MAD_F(0x0595b7a3) /* 0.349052083 */, 15 },
- /* 1107 */ { MAD_F(0x059770f1) /* 0.349472945 */, 15 },
- /* 1108 */ { MAD_F(0x05992a61) /* 0.349893933 */, 15 },
- /* 1109 */ { MAD_F(0x059ae3f3) /* 0.350315048 */, 15 },
- /* 1110 */ { MAD_F(0x059c9da8) /* 0.350736290 */, 15 },
- /* 1111 */ { MAD_F(0x059e577e) /* 0.351157658 */, 15 },
- /* 1112 */ { MAD_F(0x05a01176) /* 0.351579152 */, 15 },
- /* 1113 */ { MAD_F(0x05a1cb90) /* 0.352000773 */, 15 },
- /* 1114 */ { MAD_F(0x05a385cc) /* 0.352422520 */, 15 },
- /* 1115 */ { MAD_F(0x05a5402a) /* 0.352844394 */, 15 },
- /* 1116 */ { MAD_F(0x05a6faa9) /* 0.353266393 */, 15 },
- /* 1117 */ { MAD_F(0x05a8b54b) /* 0.353688519 */, 15 },
- /* 1118 */ { MAD_F(0x05aa700e) /* 0.354110771 */, 15 },
- /* 1119 */ { MAD_F(0x05ac2af3) /* 0.354533148 */, 15 },
-
- /* 1120 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 15 },
- /* 1121 */ { MAD_F(0x05afa123) /* 0.355378281 */, 15 },
- /* 1122 */ { MAD_F(0x05b15c6d) /* 0.355801035 */, 15 },
- /* 1123 */ { MAD_F(0x05b317d9) /* 0.356223916 */, 15 },
- /* 1124 */ { MAD_F(0x05b4d367) /* 0.356646922 */, 15 },
- /* 1125 */ { MAD_F(0x05b68f16) /* 0.357070053 */, 15 },
- /* 1126 */ { MAD_F(0x05b84ae7) /* 0.357493310 */, 15 },
- /* 1127 */ { MAD_F(0x05ba06da) /* 0.357916692 */, 15 },
- /* 1128 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 15 },
- /* 1129 */ { MAD_F(0x05bd7f25) /* 0.358763832 */, 15 },
- /* 1130 */ { MAD_F(0x05bf3b7c) /* 0.359187590 */, 15 },
- /* 1131 */ { MAD_F(0x05c0f7f5) /* 0.359611472 */, 15 },
- /* 1132 */ { MAD_F(0x05c2b490) /* 0.360035480 */, 15 },
- /* 1133 */ { MAD_F(0x05c4714c) /* 0.360459613 */, 15 },
- /* 1134 */ { MAD_F(0x05c62e2a) /* 0.360883870 */, 15 },
- /* 1135 */ { MAD_F(0x05c7eb29) /* 0.361308252 */, 15 },
-
- /* 1136 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 15 },
- /* 1137 */ { MAD_F(0x05cb658c) /* 0.362157390 */, 15 },
- /* 1138 */ { MAD_F(0x05cd22ef) /* 0.362582145 */, 15 },
- /* 1139 */ { MAD_F(0x05cee074) /* 0.363007026 */, 15 },
- /* 1140 */ { MAD_F(0x05d09e1b) /* 0.363432030 */, 15 },
- /* 1141 */ { MAD_F(0x05d25be2) /* 0.363857159 */, 15 },
- /* 1142 */ { MAD_F(0x05d419cb) /* 0.364282412 */, 15 },
- /* 1143 */ { MAD_F(0x05d5d7d5) /* 0.364707789 */, 15 },
- /* 1144 */ { MAD_F(0x05d79601) /* 0.365133291 */, 15 },
- /* 1145 */ { MAD_F(0x05d9544e) /* 0.365558916 */, 15 },
- /* 1146 */ { MAD_F(0x05db12bc) /* 0.365984665 */, 15 },
- /* 1147 */ { MAD_F(0x05dcd14c) /* 0.366410538 */, 15 },
- /* 1148 */ { MAD_F(0x05de8ffc) /* 0.366836535 */, 15 },
- /* 1149 */ { MAD_F(0x05e04ece) /* 0.367262655 */, 15 },
- /* 1150 */ { MAD_F(0x05e20dc1) /* 0.367688900 */, 15 },
- /* 1151 */ { MAD_F(0x05e3ccd5) /* 0.368115267 */, 15 },
-
- /* 1152 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 15 },
- /* 1153 */ { MAD_F(0x05e74b61) /* 0.368968373 */, 15 },
- /* 1154 */ { MAD_F(0x05e90ad9) /* 0.369395111 */, 15 },
- /* 1155 */ { MAD_F(0x05eaca72) /* 0.369821973 */, 15 },
- /* 1156 */ { MAD_F(0x05ec8a2b) /* 0.370248957 */, 15 },
- /* 1157 */ { MAD_F(0x05ee4a06) /* 0.370676065 */, 15 },
- /* 1158 */ { MAD_F(0x05f00a02) /* 0.371103295 */, 15 },
- /* 1159 */ { MAD_F(0x05f1ca1f) /* 0.371530649 */, 15 },
- /* 1160 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 15 },
- /* 1161 */ { MAD_F(0x05f54abc) /* 0.372385725 */, 15 },
- /* 1162 */ { MAD_F(0x05f70b3c) /* 0.372813448 */, 15 },
- /* 1163 */ { MAD_F(0x05f8cbdc) /* 0.373241292 */, 15 },
- /* 1164 */ { MAD_F(0x05fa8c9e) /* 0.373669260 */, 15 },
- /* 1165 */ { MAD_F(0x05fc4d81) /* 0.374097350 */, 15 },
- /* 1166 */ { MAD_F(0x05fe0e84) /* 0.374525563 */, 15 },
- /* 1167 */ { MAD_F(0x05ffcfa8) /* 0.374953898 */, 15 },
-
- /* 1168 */ { MAD_F(0x060190ee) /* 0.375382356 */, 15 },
- /* 1169 */ { MAD_F(0x06035254) /* 0.375810936 */, 15 },
- /* 1170 */ { MAD_F(0x060513da) /* 0.376239638 */, 15 },
- /* 1171 */ { MAD_F(0x0606d582) /* 0.376668462 */, 15 },
- /* 1172 */ { MAD_F(0x0608974a) /* 0.377097408 */, 15 },
- /* 1173 */ { MAD_F(0x060a5934) /* 0.377526476 */, 15 },
- /* 1174 */ { MAD_F(0x060c1b3d) /* 0.377955667 */, 15 },
- /* 1175 */ { MAD_F(0x060ddd68) /* 0.378384979 */, 15 },
- /* 1176 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 15 },
- /* 1177 */ { MAD_F(0x0611621f) /* 0.379243968 */, 15 },
- /* 1178 */ { MAD_F(0x061324ac) /* 0.379673646 */, 15 },
- /* 1179 */ { MAD_F(0x0614e759) /* 0.380103444 */, 15 },
- /* 1180 */ { MAD_F(0x0616aa27) /* 0.380533365 */, 15 },
- /* 1181 */ { MAD_F(0x06186d16) /* 0.380963407 */, 15 },
- /* 1182 */ { MAD_F(0x061a3025) /* 0.381393570 */, 15 },
- /* 1183 */ { MAD_F(0x061bf354) /* 0.381823855 */, 15 },
-
- /* 1184 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 15 },
- /* 1185 */ { MAD_F(0x061f7a15) /* 0.382684788 */, 15 },
- /* 1186 */ { MAD_F(0x06213da7) /* 0.383115436 */, 15 },
- /* 1187 */ { MAD_F(0x06230158) /* 0.383546205 */, 15 },
- /* 1188 */ { MAD_F(0x0624c52a) /* 0.383977096 */, 15 },
- /* 1189 */ { MAD_F(0x0626891d) /* 0.384408107 */, 15 },
- /* 1190 */ { MAD_F(0x06284d30) /* 0.384839239 */, 15 },
- /* 1191 */ { MAD_F(0x062a1164) /* 0.385270492 */, 15 },
- /* 1192 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 15 },
- /* 1193 */ { MAD_F(0x062d9a2c) /* 0.386133359 */, 15 },
- /* 1194 */ { MAD_F(0x062f5ec1) /* 0.386564974 */, 15 },
- /* 1195 */ { MAD_F(0x06312376) /* 0.386996709 */, 15 },
- /* 1196 */ { MAD_F(0x0632e84b) /* 0.387428565 */, 15 },
- /* 1197 */ { MAD_F(0x0634ad41) /* 0.387860541 */, 15 },
- /* 1198 */ { MAD_F(0x06367257) /* 0.388292637 */, 15 },
- /* 1199 */ { MAD_F(0x0638378d) /* 0.388724854 */, 15 },
-
- /* 1200 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 15 },
- /* 1201 */ { MAD_F(0x063bc25b) /* 0.389589648 */, 15 },
- /* 1202 */ { MAD_F(0x063d87f2) /* 0.390022225 */, 15 },
- /* 1203 */ { MAD_F(0x063f4da9) /* 0.390454922 */, 15 },
- /* 1204 */ { MAD_F(0x06411380) /* 0.390887739 */, 15 },
- /* 1205 */ { MAD_F(0x0642d978) /* 0.391320675 */, 15 },
- /* 1206 */ { MAD_F(0x06449f8f) /* 0.391753732 */, 15 },
- /* 1207 */ { MAD_F(0x064665c7) /* 0.392186908 */, 15 },
- /* 1208 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 15 },
- /* 1209 */ { MAD_F(0x0649f297) /* 0.393053619 */, 15 },
- /* 1210 */ { MAD_F(0x064bb92f) /* 0.393487154 */, 15 },
- /* 1211 */ { MAD_F(0x064d7fe8) /* 0.393920808 */, 15 },
- /* 1212 */ { MAD_F(0x064f46c0) /* 0.394354582 */, 15 },
- /* 1213 */ { MAD_F(0x06510db8) /* 0.394788475 */, 15 },
- /* 1214 */ { MAD_F(0x0652d4d0) /* 0.395222488 */, 15 },
- /* 1215 */ { MAD_F(0x06549c09) /* 0.395656619 */, 15 },
-
- /* 1216 */ { MAD_F(0x06566361) /* 0.396090870 */, 15 },
- /* 1217 */ { MAD_F(0x06582ad9) /* 0.396525239 */, 15 },
- /* 1218 */ { MAD_F(0x0659f271) /* 0.396959728 */, 15 },
- /* 1219 */ { MAD_F(0x065bba29) /* 0.397394336 */, 15 },
- /* 1220 */ { MAD_F(0x065d8201) /* 0.397829062 */, 15 },
- /* 1221 */ { MAD_F(0x065f49f9) /* 0.398263907 */, 15 },
- /* 1222 */ { MAD_F(0x06611211) /* 0.398698871 */, 15 },
- /* 1223 */ { MAD_F(0x0662da49) /* 0.399133954 */, 15 },
- /* 1224 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 15 },
- /* 1225 */ { MAD_F(0x06666b17) /* 0.400004475 */, 15 },
- /* 1226 */ { MAD_F(0x066833ae) /* 0.400439913 */, 15 },
- /* 1227 */ { MAD_F(0x0669fc65) /* 0.400875470 */, 15 },
- /* 1228 */ { MAD_F(0x066bc53c) /* 0.401311145 */, 15 },
- /* 1229 */ { MAD_F(0x066d8e32) /* 0.401746938 */, 15 },
- /* 1230 */ { MAD_F(0x066f5748) /* 0.402182850 */, 15 },
- /* 1231 */ { MAD_F(0x0671207e) /* 0.402618879 */, 15 },
-
- /* 1232 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 15 },
- /* 1233 */ { MAD_F(0x0674b349) /* 0.403491293 */, 15 },
- /* 1234 */ { MAD_F(0x06767cde) /* 0.403927676 */, 15 },
- /* 1235 */ { MAD_F(0x06784692) /* 0.404364178 */, 15 },
- /* 1236 */ { MAD_F(0x067a1066) /* 0.404800797 */, 15 },
- /* 1237 */ { MAD_F(0x067bda5a) /* 0.405237535 */, 15 },
- /* 1238 */ { MAD_F(0x067da46d) /* 0.405674390 */, 15 },
- /* 1239 */ { MAD_F(0x067f6ea0) /* 0.406111362 */, 15 },
- /* 1240 */ { MAD_F(0x068138f3) /* 0.406548452 */, 15 },
- /* 1241 */ { MAD_F(0x06830365) /* 0.406985660 */, 15 },
- /* 1242 */ { MAD_F(0x0684cdf6) /* 0.407422985 */, 15 },
- /* 1243 */ { MAD_F(0x068698a8) /* 0.407860427 */, 15 },
- /* 1244 */ { MAD_F(0x06886378) /* 0.408297987 */, 15 },
- /* 1245 */ { MAD_F(0x068a2e68) /* 0.408735664 */, 15 },
- /* 1246 */ { MAD_F(0x068bf978) /* 0.409173458 */, 15 },
- /* 1247 */ { MAD_F(0x068dc4a7) /* 0.409611370 */, 15 },
-
- /* 1248 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 15 },
- /* 1249 */ { MAD_F(0x06915b63) /* 0.410487544 */, 15 },
- /* 1250 */ { MAD_F(0x069326f0) /* 0.410925806 */, 15 },
- /* 1251 */ { MAD_F(0x0694f29c) /* 0.411364185 */, 15 },
- /* 1252 */ { MAD_F(0x0696be68) /* 0.411802681 */, 15 },
- /* 1253 */ { MAD_F(0x06988a54) /* 0.412241294 */, 15 },
- /* 1254 */ { MAD_F(0x069a565e) /* 0.412680024 */, 15 },
- /* 1255 */ { MAD_F(0x069c2288) /* 0.413118870 */, 15 },
- /* 1256 */ { MAD_F(0x069deed1) /* 0.413557833 */, 15 },
- /* 1257 */ { MAD_F(0x069fbb3a) /* 0.413996912 */, 15 },
- /* 1258 */ { MAD_F(0x06a187c1) /* 0.414436108 */, 15 },
- /* 1259 */ { MAD_F(0x06a35468) /* 0.414875420 */, 15 },
- /* 1260 */ { MAD_F(0x06a5212f) /* 0.415314849 */, 15 },
- /* 1261 */ { MAD_F(0x06a6ee14) /* 0.415754393 */, 15 },
- /* 1262 */ { MAD_F(0x06a8bb18) /* 0.416194054 */, 15 },
- /* 1263 */ { MAD_F(0x06aa883c) /* 0.416633831 */, 15 },
-
- /* 1264 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 15 },
- /* 1265 */ { MAD_F(0x06ae22e1) /* 0.417513734 */, 15 },
- /* 1266 */ { MAD_F(0x06aff062) /* 0.417953859 */, 15 },
- /* 1267 */ { MAD_F(0x06b1be03) /* 0.418394100 */, 15 },
- /* 1268 */ { MAD_F(0x06b38bc2) /* 0.418834457 */, 15 },
- /* 1269 */ { MAD_F(0x06b559a1) /* 0.419274929 */, 15 },
- /* 1270 */ { MAD_F(0x06b7279e) /* 0.419715518 */, 15 },
- /* 1271 */ { MAD_F(0x06b8f5bb) /* 0.420156222 */, 15 },
- /* 1272 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 15 },
- /* 1273 */ { MAD_F(0x06bc9251) /* 0.421037977 */, 15 },
- /* 1274 */ { MAD_F(0x06be60cb) /* 0.421479027 */, 15 },
- /* 1275 */ { MAD_F(0x06c02f63) /* 0.421920193 */, 15 },
- /* 1276 */ { MAD_F(0x06c1fe1b) /* 0.422361475 */, 15 },
- /* 1277 */ { MAD_F(0x06c3ccf1) /* 0.422802871 */, 15 },
- /* 1278 */ { MAD_F(0x06c59be7) /* 0.423244383 */, 15 },
- /* 1279 */ { MAD_F(0x06c76afb) /* 0.423686010 */, 15 },
-
- /* 1280 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 15 },
- /* 1281 */ { MAD_F(0x06cb0981) /* 0.424569610 */, 15 },
- /* 1282 */ { MAD_F(0x06ccd8f2) /* 0.425011582 */, 15 },
- /* 1283 */ { MAD_F(0x06cea881) /* 0.425453669 */, 15 },
- /* 1284 */ { MAD_F(0x06d07830) /* 0.425895871 */, 15 },
- /* 1285 */ { MAD_F(0x06d247fe) /* 0.426338188 */, 15 },
- /* 1286 */ { MAD_F(0x06d417ea) /* 0.426780620 */, 15 },
- /* 1287 */ { MAD_F(0x06d5e7f5) /* 0.427223166 */, 15 },
- /* 1288 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 15 },
- /* 1289 */ { MAD_F(0x06d98868) /* 0.428108603 */, 15 },
- /* 1290 */ { MAD_F(0x06db58cf) /* 0.428551493 */, 15 },
- /* 1291 */ { MAD_F(0x06dd2955) /* 0.428994497 */, 15 },
- /* 1292 */ { MAD_F(0x06def9fa) /* 0.429437616 */, 15 },
- /* 1293 */ { MAD_F(0x06e0cabe) /* 0.429880849 */, 15 },
- /* 1294 */ { MAD_F(0x06e29ba0) /* 0.430324197 */, 15 },
- /* 1295 */ { MAD_F(0x06e46ca1) /* 0.430767659 */, 15 },
-
- /* 1296 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 15 },
- /* 1297 */ { MAD_F(0x06e80efe) /* 0.431654924 */, 15 },
- /* 1298 */ { MAD_F(0x06e9e05b) /* 0.432098728 */, 15 },
- /* 1299 */ { MAD_F(0x06ebb1d6) /* 0.432542647 */, 15 },
- /* 1300 */ { MAD_F(0x06ed8370) /* 0.432986678 */, 15 },
- /* 1301 */ { MAD_F(0x06ef5529) /* 0.433430824 */, 15 },
- /* 1302 */ { MAD_F(0x06f12700) /* 0.433875084 */, 15 },
- /* 1303 */ { MAD_F(0x06f2f8f5) /* 0.434319457 */, 15 },
- /* 1304 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 15 },
- /* 1305 */ { MAD_F(0x06f69d3c) /* 0.435208545 */, 15 },
- /* 1306 */ { MAD_F(0x06f86f8d) /* 0.435653259 */, 15 },
- /* 1307 */ { MAD_F(0x06fa41fd) /* 0.436098087 */, 15 },
- /* 1308 */ { MAD_F(0x06fc148b) /* 0.436543029 */, 15 },
- /* 1309 */ { MAD_F(0x06fde737) /* 0.436988083 */, 15 },
- /* 1310 */ { MAD_F(0x06ffba02) /* 0.437433251 */, 15 },
- /* 1311 */ { MAD_F(0x07018ceb) /* 0.437878533 */, 15 },
-
- /* 1312 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 15 },
- /* 1313 */ { MAD_F(0x07053319) /* 0.438769435 */, 15 },
- /* 1314 */ { MAD_F(0x0707065d) /* 0.439215056 */, 15 },
- /* 1315 */ { MAD_F(0x0708d9c0) /* 0.439660790 */, 15 },
- /* 1316 */ { MAD_F(0x070aad41) /* 0.440106636 */, 15 },
- /* 1317 */ { MAD_F(0x070c80e1) /* 0.440552596 */, 15 },
- /* 1318 */ { MAD_F(0x070e549f) /* 0.440998669 */, 15 },
- /* 1319 */ { MAD_F(0x0710287b) /* 0.441444855 */, 15 },
- /* 1320 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 15 },
- /* 1321 */ { MAD_F(0x0713d08d) /* 0.442337564 */, 15 },
- /* 1322 */ { MAD_F(0x0715a4c4) /* 0.442784088 */, 15 },
- /* 1323 */ { MAD_F(0x07177919) /* 0.443230724 */, 15 },
- /* 1324 */ { MAD_F(0x07194d8c) /* 0.443677473 */, 15 },
- /* 1325 */ { MAD_F(0x071b221e) /* 0.444124334 */, 15 },
- /* 1326 */ { MAD_F(0x071cf6ce) /* 0.444571308 */, 15 },
- /* 1327 */ { MAD_F(0x071ecb9b) /* 0.445018394 */, 15 },
-
- /* 1328 */ { MAD_F(0x0720a087) /* 0.445465593 */, 15 },
- /* 1329 */ { MAD_F(0x07227591) /* 0.445912903 */, 15 },
- /* 1330 */ { MAD_F(0x07244ab9) /* 0.446360326 */, 15 },
- /* 1331 */ { MAD_F(0x07262000) /* 0.446807861 */, 15 },
- /* 1332 */ { MAD_F(0x0727f564) /* 0.447255509 */, 15 },
- /* 1333 */ { MAD_F(0x0729cae7) /* 0.447703268 */, 15 },
- /* 1334 */ { MAD_F(0x072ba087) /* 0.448151139 */, 15 },
- /* 1335 */ { MAD_F(0x072d7646) /* 0.448599122 */, 15 },
- /* 1336 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 15 },
- /* 1337 */ { MAD_F(0x0731221d) /* 0.449495424 */, 15 },
- /* 1338 */ { MAD_F(0x0732f835) /* 0.449943742 */, 15 },
- /* 1339 */ { MAD_F(0x0734ce6c) /* 0.450392173 */, 15 },
- /* 1340 */ { MAD_F(0x0736a4c1) /* 0.450840715 */, 15 },
- /* 1341 */ { MAD_F(0x07387b33) /* 0.451289368 */, 15 },
- /* 1342 */ { MAD_F(0x073a51c4) /* 0.451738133 */, 15 },
- /* 1343 */ { MAD_F(0x073c2872) /* 0.452187010 */, 15 },
-
- /* 1344 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 15 },
- /* 1345 */ { MAD_F(0x073fd628) /* 0.453085097 */, 15 },
- /* 1346 */ { MAD_F(0x0741ad30) /* 0.453534308 */, 15 },
- /* 1347 */ { MAD_F(0x07438456) /* 0.453983630 */, 15 },
- /* 1348 */ { MAD_F(0x07455b9a) /* 0.454433063 */, 15 },
- /* 1349 */ { MAD_F(0x074732fc) /* 0.454882607 */, 15 },
- /* 1350 */ { MAD_F(0x07490a7b) /* 0.455332262 */, 15 },
- /* 1351 */ { MAD_F(0x074ae218) /* 0.455782029 */, 15 },
- /* 1352 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 15 },
- /* 1353 */ { MAD_F(0x074e91ac) /* 0.456681894 */, 15 },
- /* 1354 */ { MAD_F(0x075069a3) /* 0.457131993 */, 15 },
- /* 1355 */ { MAD_F(0x075241b7) /* 0.457582203 */, 15 },
- /* 1356 */ { MAD_F(0x075419e9) /* 0.458032524 */, 15 },
- /* 1357 */ { MAD_F(0x0755f239) /* 0.458482956 */, 15 },
- /* 1358 */ { MAD_F(0x0757caa7) /* 0.458933498 */, 15 },
- /* 1359 */ { MAD_F(0x0759a332) /* 0.459384151 */, 15 },
-
- /* 1360 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 15 },
- /* 1361 */ { MAD_F(0x075d54a1) /* 0.460285788 */, 15 },
- /* 1362 */ { MAD_F(0x075f2d85) /* 0.460736772 */, 15 },
- /* 1363 */ { MAD_F(0x07610687) /* 0.461187867 */, 15 },
- /* 1364 */ { MAD_F(0x0762dfa6) /* 0.461639071 */, 15 },
- /* 1365 */ { MAD_F(0x0764b8e3) /* 0.462090387 */, 15 },
- /* 1366 */ { MAD_F(0x0766923e) /* 0.462541812 */, 15 },
- /* 1367 */ { MAD_F(0x07686bb6) /* 0.462993348 */, 15 },
- /* 1368 */ { MAD_F(0x076a454c) /* 0.463444993 */, 15 },
- /* 1369 */ { MAD_F(0x076c1eff) /* 0.463896749 */, 15 },
- /* 1370 */ { MAD_F(0x076df8d0) /* 0.464348615 */, 15 },
- /* 1371 */ { MAD_F(0x076fd2be) /* 0.464800591 */, 15 },
- /* 1372 */ { MAD_F(0x0771acca) /* 0.465252676 */, 15 },
- /* 1373 */ { MAD_F(0x077386f3) /* 0.465704872 */, 15 },
- /* 1374 */ { MAD_F(0x0775613a) /* 0.466157177 */, 15 },
- /* 1375 */ { MAD_F(0x07773b9e) /* 0.466609592 */, 15 },
-
- /* 1376 */ { MAD_F(0x07791620) /* 0.467062117 */, 15 },
- /* 1377 */ { MAD_F(0x077af0bf) /* 0.467514751 */, 15 },
- /* 1378 */ { MAD_F(0x077ccb7c) /* 0.467967495 */, 15 },
- /* 1379 */ { MAD_F(0x077ea656) /* 0.468420349 */, 15 },
- /* 1380 */ { MAD_F(0x0780814d) /* 0.468873312 */, 15 },
- /* 1381 */ { MAD_F(0x07825c62) /* 0.469326384 */, 15 },
- /* 1382 */ { MAD_F(0x07843794) /* 0.469779566 */, 15 },
- /* 1383 */ { MAD_F(0x078612e3) /* 0.470232857 */, 15 },
- /* 1384 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 15 },
- /* 1385 */ { MAD_F(0x0789c9da) /* 0.471139767 */, 15 },
- /* 1386 */ { MAD_F(0x078ba581) /* 0.471593386 */, 15 },
- /* 1387 */ { MAD_F(0x078d8146) /* 0.472047114 */, 15 },
- /* 1388 */ { MAD_F(0x078f5d28) /* 0.472500951 */, 15 },
- /* 1389 */ { MAD_F(0x07913927) /* 0.472954896 */, 15 },
- /* 1390 */ { MAD_F(0x07931543) /* 0.473408951 */, 15 },
- /* 1391 */ { MAD_F(0x0794f17d) /* 0.473863115 */, 15 },
-
- /* 1392 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 15 },
- /* 1393 */ { MAD_F(0x0798aa48) /* 0.474771769 */, 15 },
- /* 1394 */ { MAD_F(0x079a86d9) /* 0.475226259 */, 15 },
- /* 1395 */ { MAD_F(0x079c6388) /* 0.475680858 */, 15 },
- /* 1396 */ { MAD_F(0x079e4053) /* 0.476135565 */, 15 },
- /* 1397 */ { MAD_F(0x07a01d3c) /* 0.476590381 */, 15 },
- /* 1398 */ { MAD_F(0x07a1fa42) /* 0.477045306 */, 15 },
- /* 1399 */ { MAD_F(0x07a3d765) /* 0.477500339 */, 15 },
- /* 1400 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 15 },
- /* 1401 */ { MAD_F(0x07a79202) /* 0.478410731 */, 15 },
- /* 1402 */ { MAD_F(0x07a96f7d) /* 0.478866089 */, 15 },
- /* 1403 */ { MAD_F(0x07ab4d14) /* 0.479321555 */, 15 },
- /* 1404 */ { MAD_F(0x07ad2ac8) /* 0.479777130 */, 15 },
- /* 1405 */ { MAD_F(0x07af089a) /* 0.480232813 */, 15 },
- /* 1406 */ { MAD_F(0x07b0e688) /* 0.480688604 */, 15 },
- /* 1407 */ { MAD_F(0x07b2c494) /* 0.481144503 */, 15 },
-
- /* 1408 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 15 },
- /* 1409 */ { MAD_F(0x07b68102) /* 0.482056625 */, 15 },
- /* 1410 */ { MAD_F(0x07b85f64) /* 0.482512848 */, 15 },
- /* 1411 */ { MAD_F(0x07ba3de4) /* 0.482969179 */, 15 },
- /* 1412 */ { MAD_F(0x07bc1c80) /* 0.483425618 */, 15 },
- /* 1413 */ { MAD_F(0x07bdfb39) /* 0.483882164 */, 15 },
- /* 1414 */ { MAD_F(0x07bfda0f) /* 0.484338818 */, 15 },
- /* 1415 */ { MAD_F(0x07c1b902) /* 0.484795580 */, 15 },
- /* 1416 */ { MAD_F(0x07c39812) /* 0.485252449 */, 15 },
- /* 1417 */ { MAD_F(0x07c5773f) /* 0.485709426 */, 15 },
- /* 1418 */ { MAD_F(0x07c75689) /* 0.486166511 */, 15 },
- /* 1419 */ { MAD_F(0x07c935ef) /* 0.486623703 */, 15 },
- /* 1420 */ { MAD_F(0x07cb1573) /* 0.487081002 */, 15 },
- /* 1421 */ { MAD_F(0x07ccf513) /* 0.487538409 */, 15 },
- /* 1422 */ { MAD_F(0x07ced4d0) /* 0.487995923 */, 15 },
- /* 1423 */ { MAD_F(0x07d0b4aa) /* 0.488453544 */, 15 },
-
- /* 1424 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 15 },
- /* 1425 */ { MAD_F(0x07d474b3) /* 0.489369108 */, 15 },
- /* 1426 */ { MAD_F(0x07d654e4) /* 0.489827051 */, 15 },
- /* 1427 */ { MAD_F(0x07d83530) /* 0.490285101 */, 15 },
- /* 1428 */ { MAD_F(0x07da159a) /* 0.490743258 */, 15 },
- /* 1429 */ { MAD_F(0x07dbf620) /* 0.491201522 */, 15 },
- /* 1430 */ { MAD_F(0x07ddd6c3) /* 0.491659892 */, 15 },
- /* 1431 */ { MAD_F(0x07dfb783) /* 0.492118370 */, 15 },
- /* 1432 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 15 },
- /* 1433 */ { MAD_F(0x07e37958) /* 0.493035645 */, 15 },
- /* 1434 */ { MAD_F(0x07e55a6e) /* 0.493494443 */, 15 },
- /* 1435 */ { MAD_F(0x07e73ba0) /* 0.493953348 */, 15 },
- /* 1436 */ { MAD_F(0x07e91cef) /* 0.494412359 */, 15 },
- /* 1437 */ { MAD_F(0x07eafe5a) /* 0.494871476 */, 15 },
- /* 1438 */ { MAD_F(0x07ecdfe2) /* 0.495330701 */, 15 },
- /* 1439 */ { MAD_F(0x07eec187) /* 0.495790031 */, 15 },
-
- /* 1440 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 15 },
- /* 1441 */ { MAD_F(0x07f28526) /* 0.496709012 */, 15 },
- /* 1442 */ { MAD_F(0x07f46720) /* 0.497168662 */, 15 },
- /* 1443 */ { MAD_F(0x07f64937) /* 0.497628418 */, 15 },
- /* 1444 */ { MAD_F(0x07f82b6a) /* 0.498088280 */, 15 },
- /* 1445 */ { MAD_F(0x07fa0dba) /* 0.498548248 */, 15 },
- /* 1446 */ { MAD_F(0x07fbf026) /* 0.499008323 */, 15 },
- /* 1447 */ { MAD_F(0x07fdd2af) /* 0.499468503 */, 15 },
- /* 1448 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 15 },
- /* 1449 */ { MAD_F(0x0400cc0b) /* 0.250194591 */, 16 },
- /* 1450 */ { MAD_F(0x0401bd7a) /* 0.250424840 */, 16 },
- /* 1451 */ { MAD_F(0x0402aef7) /* 0.250655143 */, 16 },
- /* 1452 */ { MAD_F(0x0403a083) /* 0.250885498 */, 16 },
- /* 1453 */ { MAD_F(0x0404921c) /* 0.251115906 */, 16 },
- /* 1454 */ { MAD_F(0x040583c4) /* 0.251346367 */, 16 },
- /* 1455 */ { MAD_F(0x0406757a) /* 0.251576880 */, 16 },
-
- /* 1456 */ { MAD_F(0x0407673f) /* 0.251807447 */, 16 },
- /* 1457 */ { MAD_F(0x04085911) /* 0.252038066 */, 16 },
- /* 1458 */ { MAD_F(0x04094af1) /* 0.252268738 */, 16 },
- /* 1459 */ { MAD_F(0x040a3ce0) /* 0.252499463 */, 16 },
- /* 1460 */ { MAD_F(0x040b2edd) /* 0.252730240 */, 16 },
- /* 1461 */ { MAD_F(0x040c20e8) /* 0.252961071 */, 16 },
- /* 1462 */ { MAD_F(0x040d1301) /* 0.253191953 */, 16 },
- /* 1463 */ { MAD_F(0x040e0529) /* 0.253422889 */, 16 },
- /* 1464 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 16 },
- /* 1465 */ { MAD_F(0x040fe9a1) /* 0.253884918 */, 16 },
- /* 1466 */ { MAD_F(0x0410dbf3) /* 0.254116011 */, 16 },
- /* 1467 */ { MAD_F(0x0411ce53) /* 0.254347157 */, 16 },
- /* 1468 */ { MAD_F(0x0412c0c1) /* 0.254578356 */, 16 },
- /* 1469 */ { MAD_F(0x0413b33d) /* 0.254809606 */, 16 },
- /* 1470 */ { MAD_F(0x0414a5c7) /* 0.255040910 */, 16 },
- /* 1471 */ { MAD_F(0x0415985f) /* 0.255272266 */, 16 },
-
- /* 1472 */ { MAD_F(0x04168b05) /* 0.255503674 */, 16 },
- /* 1473 */ { MAD_F(0x04177db9) /* 0.255735135 */, 16 },
- /* 1474 */ { MAD_F(0x0418707c) /* 0.255966648 */, 16 },
- /* 1475 */ { MAD_F(0x0419634c) /* 0.256198213 */, 16 },
- /* 1476 */ { MAD_F(0x041a562a) /* 0.256429831 */, 16 },
- /* 1477 */ { MAD_F(0x041b4917) /* 0.256661501 */, 16 },
- /* 1478 */ { MAD_F(0x041c3c11) /* 0.256893223 */, 16 },
- /* 1479 */ { MAD_F(0x041d2f1a) /* 0.257124998 */, 16 },
- /* 1480 */ { MAD_F(0x041e2230) /* 0.257356825 */, 16 },
- /* 1481 */ { MAD_F(0x041f1555) /* 0.257588704 */, 16 },
- /* 1482 */ { MAD_F(0x04200888) /* 0.257820635 */, 16 },
- /* 1483 */ { MAD_F(0x0420fbc8) /* 0.258052619 */, 16 },
- /* 1484 */ { MAD_F(0x0421ef17) /* 0.258284654 */, 16 },
- /* 1485 */ { MAD_F(0x0422e273) /* 0.258516742 */, 16 },
- /* 1486 */ { MAD_F(0x0423d5de) /* 0.258748882 */, 16 },
- /* 1487 */ { MAD_F(0x0424c956) /* 0.258981074 */, 16 },
-
- /* 1488 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 16 },
- /* 1489 */ { MAD_F(0x0426b071) /* 0.259445614 */, 16 },
- /* 1490 */ { MAD_F(0x0427a414) /* 0.259677962 */, 16 },
- /* 1491 */ { MAD_F(0x042897c4) /* 0.259910362 */, 16 },
- /* 1492 */ { MAD_F(0x04298b83) /* 0.260142814 */, 16 },
- /* 1493 */ { MAD_F(0x042a7f4f) /* 0.260375318 */, 16 },
- /* 1494 */ { MAD_F(0x042b7329) /* 0.260607874 */, 16 },
- /* 1495 */ { MAD_F(0x042c6711) /* 0.260840481 */, 16 },
- /* 1496 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 16 },
- /* 1497 */ { MAD_F(0x042e4f0b) /* 0.261305852 */, 16 },
- /* 1498 */ { MAD_F(0x042f431d) /* 0.261538616 */, 16 },
- /* 1499 */ { MAD_F(0x0430373d) /* 0.261771431 */, 16 },
- /* 1500 */ { MAD_F(0x04312b6b) /* 0.262004297 */, 16 },
- /* 1501 */ { MAD_F(0x04321fa6) /* 0.262237216 */, 16 },
- /* 1502 */ { MAD_F(0x043313f0) /* 0.262470186 */, 16 },
- /* 1503 */ { MAD_F(0x04340847) /* 0.262703208 */, 16 },
-
- /* 1504 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 16 },
- /* 1505 */ { MAD_F(0x0435f120) /* 0.263169407 */, 16 },
- /* 1506 */ { MAD_F(0x0436e5a1) /* 0.263402584 */, 16 },
- /* 1507 */ { MAD_F(0x0437da2f) /* 0.263635813 */, 16 },
- /* 1508 */ { MAD_F(0x0438cecc) /* 0.263869093 */, 16 },
- /* 1509 */ { MAD_F(0x0439c377) /* 0.264102425 */, 16 },
- /* 1510 */ { MAD_F(0x043ab82f) /* 0.264335808 */, 16 },
- /* 1511 */ { MAD_F(0x043bacf5) /* 0.264569243 */, 16 },
- /* 1512 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 16 },
- /* 1513 */ { MAD_F(0x043d96ab) /* 0.265036267 */, 16 },
- /* 1514 */ { MAD_F(0x043e8b9b) /* 0.265269857 */, 16 },
- /* 1515 */ { MAD_F(0x043f8098) /* 0.265503498 */, 16 },
- /* 1516 */ { MAD_F(0x044075a3) /* 0.265737190 */, 16 },
- /* 1517 */ { MAD_F(0x04416abc) /* 0.265970933 */, 16 },
- /* 1518 */ { MAD_F(0x04425fe3) /* 0.266204728 */, 16 },
- /* 1519 */ { MAD_F(0x04435518) /* 0.266438574 */, 16 },
-
- /* 1520 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 16 },
- /* 1521 */ { MAD_F(0x04453fab) /* 0.266906421 */, 16 },
- /* 1522 */ { MAD_F(0x04463508) /* 0.267140421 */, 16 },
- /* 1523 */ { MAD_F(0x04472a74) /* 0.267374472 */, 16 },
- /* 1524 */ { MAD_F(0x04481fee) /* 0.267608575 */, 16 },
- /* 1525 */ { MAD_F(0x04491575) /* 0.267842729 */, 16 },
- /* 1526 */ { MAD_F(0x044a0b0a) /* 0.268076934 */, 16 },
- /* 1527 */ { MAD_F(0x044b00ac) /* 0.268311190 */, 16 },
- /* 1528 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 16 },
- /* 1529 */ { MAD_F(0x044cec1b) /* 0.268779856 */, 16 },
- /* 1530 */ { MAD_F(0x044de1e7) /* 0.269014265 */, 16 },
- /* 1531 */ { MAD_F(0x044ed7c0) /* 0.269248726 */, 16 },
- /* 1532 */ { MAD_F(0x044fcda8) /* 0.269483238 */, 16 },
- /* 1533 */ { MAD_F(0x0450c39c) /* 0.269717800 */, 16 },
- /* 1534 */ { MAD_F(0x0451b99f) /* 0.269952414 */, 16 },
- /* 1535 */ { MAD_F(0x0452afaf) /* 0.270187079 */, 16 },
-
- /* 1536 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 16 },
- /* 1537 */ { MAD_F(0x04549bf9) /* 0.270656561 */, 16 },
- /* 1538 */ { MAD_F(0x04559232) /* 0.270891379 */, 16 },
- /* 1539 */ { MAD_F(0x04568879) /* 0.271126247 */, 16 },
- /* 1540 */ { MAD_F(0x04577ece) /* 0.271361166 */, 16 },
- /* 1541 */ { MAD_F(0x04587530) /* 0.271596136 */, 16 },
- /* 1542 */ { MAD_F(0x04596ba0) /* 0.271831157 */, 16 },
- /* 1543 */ { MAD_F(0x045a621e) /* 0.272066229 */, 16 },
- /* 1544 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 16 },
- /* 1545 */ { MAD_F(0x045c4f42) /* 0.272536525 */, 16 },
- /* 1546 */ { MAD_F(0x045d45e9) /* 0.272771749 */, 16 },
- /* 1547 */ { MAD_F(0x045e3c9d) /* 0.273007024 */, 16 },
- /* 1548 */ { MAD_F(0x045f335e) /* 0.273242350 */, 16 },
- /* 1549 */ { MAD_F(0x04602a2e) /* 0.273477726 */, 16 },
- /* 1550 */ { MAD_F(0x0461210b) /* 0.273713153 */, 16 },
- /* 1551 */ { MAD_F(0x046217f5) /* 0.273948630 */, 16 },
-
- /* 1552 */ { MAD_F(0x04630eed) /* 0.274184158 */, 16 },
- /* 1553 */ { MAD_F(0x046405f3) /* 0.274419737 */, 16 },
- /* 1554 */ { MAD_F(0x0464fd06) /* 0.274655366 */, 16 },
- /* 1555 */ { MAD_F(0x0465f427) /* 0.274891046 */, 16 },
- /* 1556 */ { MAD_F(0x0466eb55) /* 0.275126776 */, 16 },
- /* 1557 */ { MAD_F(0x0467e291) /* 0.275362557 */, 16 },
- /* 1558 */ { MAD_F(0x0468d9db) /* 0.275598389 */, 16 },
- /* 1559 */ { MAD_F(0x0469d132) /* 0.275834270 */, 16 },
- /* 1560 */ { MAD_F(0x046ac896) /* 0.276070203 */, 16 },
- /* 1561 */ { MAD_F(0x046bc009) /* 0.276306185 */, 16 },
- /* 1562 */ { MAD_F(0x046cb788) /* 0.276542218 */, 16 },
- /* 1563 */ { MAD_F(0x046daf15) /* 0.276778302 */, 16 },
- /* 1564 */ { MAD_F(0x046ea6b0) /* 0.277014435 */, 16 },
- /* 1565 */ { MAD_F(0x046f9e58) /* 0.277250619 */, 16 },
- /* 1566 */ { MAD_F(0x0470960e) /* 0.277486854 */, 16 },
- /* 1567 */ { MAD_F(0x04718dd1) /* 0.277723139 */, 16 },
-
- /* 1568 */ { MAD_F(0x047285a2) /* 0.277959474 */, 16 },
- /* 1569 */ { MAD_F(0x04737d80) /* 0.278195859 */, 16 },
- /* 1570 */ { MAD_F(0x0474756c) /* 0.278432294 */, 16 },
- /* 1571 */ { MAD_F(0x04756d65) /* 0.278668780 */, 16 },
- /* 1572 */ { MAD_F(0x0476656b) /* 0.278905316 */, 16 },
- /* 1573 */ { MAD_F(0x04775d7f) /* 0.279141902 */, 16 },
- /* 1574 */ { MAD_F(0x047855a1) /* 0.279378538 */, 16 },
- /* 1575 */ { MAD_F(0x04794dd0) /* 0.279615224 */, 16 },
- /* 1576 */ { MAD_F(0x047a460c) /* 0.279851960 */, 16 },
- /* 1577 */ { MAD_F(0x047b3e56) /* 0.280088747 */, 16 },
- /* 1578 */ { MAD_F(0x047c36ae) /* 0.280325583 */, 16 },
- /* 1579 */ { MAD_F(0x047d2f12) /* 0.280562470 */, 16 },
- /* 1580 */ { MAD_F(0x047e2784) /* 0.280799406 */, 16 },
- /* 1581 */ { MAD_F(0x047f2004) /* 0.281036393 */, 16 },
- /* 1582 */ { MAD_F(0x04801891) /* 0.281273429 */, 16 },
- /* 1583 */ { MAD_F(0x0481112b) /* 0.281510516 */, 16 },
-
- /* 1584 */ { MAD_F(0x048209d3) /* 0.281747652 */, 16 },
- /* 1585 */ { MAD_F(0x04830288) /* 0.281984838 */, 16 },
- /* 1586 */ { MAD_F(0x0483fb4b) /* 0.282222075 */, 16 },
- /* 1587 */ { MAD_F(0x0484f41b) /* 0.282459361 */, 16 },
- /* 1588 */ { MAD_F(0x0485ecf8) /* 0.282696697 */, 16 },
- /* 1589 */ { MAD_F(0x0486e5e3) /* 0.282934082 */, 16 },
- /* 1590 */ { MAD_F(0x0487dedb) /* 0.283171518 */, 16 },
- /* 1591 */ { MAD_F(0x0488d7e1) /* 0.283409003 */, 16 },
- /* 1592 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 16 },
- /* 1593 */ { MAD_F(0x048aca14) /* 0.283884123 */, 16 },
- /* 1594 */ { MAD_F(0x048bc341) /* 0.284121757 */, 16 },
- /* 1595 */ { MAD_F(0x048cbc7c) /* 0.284359441 */, 16 },
- /* 1596 */ { MAD_F(0x048db5c4) /* 0.284597175 */, 16 },
- /* 1597 */ { MAD_F(0x048eaf1a) /* 0.284834959 */, 16 },
- /* 1598 */ { MAD_F(0x048fa87d) /* 0.285072792 */, 16 },
- /* 1599 */ { MAD_F(0x0490a1ed) /* 0.285310675 */, 16 },
-
- /* 1600 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 16 },
- /* 1601 */ { MAD_F(0x049294f5) /* 0.285786589 */, 16 },
- /* 1602 */ { MAD_F(0x04938e8d) /* 0.286024621 */, 16 },
- /* 1603 */ { MAD_F(0x04948833) /* 0.286262702 */, 16 },
- /* 1604 */ { MAD_F(0x049581e5) /* 0.286500832 */, 16 },
- /* 1605 */ { MAD_F(0x04967ba5) /* 0.286739012 */, 16 },
- /* 1606 */ { MAD_F(0x04977573) /* 0.286977242 */, 16 },
- /* 1607 */ { MAD_F(0x04986f4d) /* 0.287215521 */, 16 },
- /* 1608 */ { MAD_F(0x04996935) /* 0.287453849 */, 16 },
- /* 1609 */ { MAD_F(0x049a632a) /* 0.287692227 */, 16 },
- /* 1610 */ { MAD_F(0x049b5d2c) /* 0.287930654 */, 16 },
- /* 1611 */ { MAD_F(0x049c573c) /* 0.288169131 */, 16 },
- /* 1612 */ { MAD_F(0x049d5159) /* 0.288407657 */, 16 },
- /* 1613 */ { MAD_F(0x049e4b83) /* 0.288646232 */, 16 },
- /* 1614 */ { MAD_F(0x049f45ba) /* 0.288884857 */, 16 },
- /* 1615 */ { MAD_F(0x04a03ffe) /* 0.289123530 */, 16 },
-
- /* 1616 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 16 },
- /* 1617 */ { MAD_F(0x04a234af) /* 0.289601026 */, 16 },
- /* 1618 */ { MAD_F(0x04a32f1b) /* 0.289839847 */, 16 },
- /* 1619 */ { MAD_F(0x04a42995) /* 0.290078718 */, 16 },
- /* 1620 */ { MAD_F(0x04a5241b) /* 0.290317638 */, 16 },
- /* 1621 */ { MAD_F(0x04a61eaf) /* 0.290556607 */, 16 },
- /* 1622 */ { MAD_F(0x04a71950) /* 0.290795626 */, 16 },
- /* 1623 */ { MAD_F(0x04a813fe) /* 0.291034693 */, 16 },
- /* 1624 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 16 },
- /* 1625 */ { MAD_F(0x04aa0982) /* 0.291512975 */, 16 },
- /* 1626 */ { MAD_F(0x04ab0458) /* 0.291752190 */, 16 },
- /* 1627 */ { MAD_F(0x04abff3b) /* 0.291991453 */, 16 },
- /* 1628 */ { MAD_F(0x04acfa2b) /* 0.292230766 */, 16 },
- /* 1629 */ { MAD_F(0x04adf528) /* 0.292470128 */, 16 },
- /* 1630 */ { MAD_F(0x04aef032) /* 0.292709539 */, 16 },
- /* 1631 */ { MAD_F(0x04afeb4a) /* 0.292948998 */, 16 },
-
- /* 1632 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 16 },
- /* 1633 */ { MAD_F(0x04b1e1a0) /* 0.293428065 */, 16 },
- /* 1634 */ { MAD_F(0x04b2dcdf) /* 0.293667671 */, 16 },
- /* 1635 */ { MAD_F(0x04b3d82b) /* 0.293907326 */, 16 },
- /* 1636 */ { MAD_F(0x04b4d384) /* 0.294147031 */, 16 },
- /* 1637 */ { MAD_F(0x04b5ceea) /* 0.294386784 */, 16 },
- /* 1638 */ { MAD_F(0x04b6ca5e) /* 0.294626585 */, 16 },
- /* 1639 */ { MAD_F(0x04b7c5de) /* 0.294866436 */, 16 },
- /* 1640 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 16 },
- /* 1641 */ { MAD_F(0x04b9bd06) /* 0.295346284 */, 16 },
- /* 1642 */ { MAD_F(0x04bab8ae) /* 0.295586281 */, 16 },
- /* 1643 */ { MAD_F(0x04bbb463) /* 0.295826327 */, 16 },
- /* 1644 */ { MAD_F(0x04bcb024) /* 0.296066421 */, 16 },
- /* 1645 */ { MAD_F(0x04bdabf3) /* 0.296306564 */, 16 },
- /* 1646 */ { MAD_F(0x04bea7cf) /* 0.296546756 */, 16 },
- /* 1647 */ { MAD_F(0x04bfa3b8) /* 0.296786996 */, 16 },
-
- /* 1648 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 16 },
- /* 1649 */ { MAD_F(0x04c19bb2) /* 0.297267623 */, 16 },
- /* 1650 */ { MAD_F(0x04c297c2) /* 0.297508009 */, 16 },
- /* 1651 */ { MAD_F(0x04c393df) /* 0.297748444 */, 16 },
- /* 1652 */ { MAD_F(0x04c49009) /* 0.297988927 */, 16 },
- /* 1653 */ { MAD_F(0x04c58c41) /* 0.298229459 */, 16 },
- /* 1654 */ { MAD_F(0x04c68885) /* 0.298470039 */, 16 },
- /* 1655 */ { MAD_F(0x04c784d6) /* 0.298710668 */, 16 },
- /* 1656 */ { MAD_F(0x04c88135) /* 0.298951346 */, 16 },
- /* 1657 */ { MAD_F(0x04c97da0) /* 0.299192071 */, 16 },
- /* 1658 */ { MAD_F(0x04ca7a18) /* 0.299432846 */, 16 },
- /* 1659 */ { MAD_F(0x04cb769e) /* 0.299673668 */, 16 },
- /* 1660 */ { MAD_F(0x04cc7330) /* 0.299914539 */, 16 },
- /* 1661 */ { MAD_F(0x04cd6fcf) /* 0.300155459 */, 16 },
- /* 1662 */ { MAD_F(0x04ce6c7b) /* 0.300396426 */, 16 },
- /* 1663 */ { MAD_F(0x04cf6935) /* 0.300637443 */, 16 },
-
- /* 1664 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 16 },
- /* 1665 */ { MAD_F(0x04d162ce) /* 0.301119620 */, 16 },
- /* 1666 */ { MAD_F(0x04d25fae) /* 0.301360781 */, 16 },
- /* 1667 */ { MAD_F(0x04d35c9b) /* 0.301601990 */, 16 },
- /* 1668 */ { MAD_F(0x04d45995) /* 0.301843247 */, 16 },
- /* 1669 */ { MAD_F(0x04d5569c) /* 0.302084553 */, 16 },
- /* 1670 */ { MAD_F(0x04d653b0) /* 0.302325907 */, 16 },
- /* 1671 */ { MAD_F(0x04d750d1) /* 0.302567309 */, 16 },
- /* 1672 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 16 },
- /* 1673 */ { MAD_F(0x04d94b3a) /* 0.303050257 */, 16 },
- /* 1674 */ { MAD_F(0x04da4881) /* 0.303291804 */, 16 },
- /* 1675 */ { MAD_F(0x04db45d6) /* 0.303533399 */, 16 },
- /* 1676 */ { MAD_F(0x04dc4337) /* 0.303775041 */, 16 },
- /* 1677 */ { MAD_F(0x04dd40a6) /* 0.304016732 */, 16 },
- /* 1678 */ { MAD_F(0x04de3e21) /* 0.304258471 */, 16 },
- /* 1679 */ { MAD_F(0x04df3ba9) /* 0.304500257 */, 16 },
-
- /* 1680 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 16 },
- /* 1681 */ { MAD_F(0x04e136e0) /* 0.304983975 */, 16 },
- /* 1682 */ { MAD_F(0x04e2348f) /* 0.305225906 */, 16 },
- /* 1683 */ { MAD_F(0x04e3324b) /* 0.305467885 */, 16 },
- /* 1684 */ { MAD_F(0x04e43013) /* 0.305709911 */, 16 },
- /* 1685 */ { MAD_F(0x04e52de9) /* 0.305951986 */, 16 },
- /* 1686 */ { MAD_F(0x04e62bcb) /* 0.306194108 */, 16 },
- /* 1687 */ { MAD_F(0x04e729ba) /* 0.306436279 */, 16 },
- /* 1688 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 16 },
- /* 1689 */ { MAD_F(0x04e925bf) /* 0.306920763 */, 16 },
- /* 1690 */ { MAD_F(0x04ea23d4) /* 0.307163077 */, 16 },
- /* 1691 */ { MAD_F(0x04eb21f7) /* 0.307405438 */, 16 },
- /* 1692 */ { MAD_F(0x04ec2026) /* 0.307647848 */, 16 },
- /* 1693 */ { MAD_F(0x04ed1e62) /* 0.307890305 */, 16 },
- /* 1694 */ { MAD_F(0x04ee1cab) /* 0.308132810 */, 16 },
- /* 1695 */ { MAD_F(0x04ef1b01) /* 0.308375362 */, 16 },
-
- /* 1696 */ { MAD_F(0x04f01963) /* 0.308617963 */, 16 },
- /* 1697 */ { MAD_F(0x04f117d3) /* 0.308860611 */, 16 },
- /* 1698 */ { MAD_F(0x04f2164f) /* 0.309103306 */, 16 },
- /* 1699 */ { MAD_F(0x04f314d8) /* 0.309346050 */, 16 },
- /* 1700 */ { MAD_F(0x04f4136d) /* 0.309588841 */, 16 },
- /* 1701 */ { MAD_F(0x04f51210) /* 0.309831679 */, 16 },
- /* 1702 */ { MAD_F(0x04f610bf) /* 0.310074565 */, 16 },
- /* 1703 */ { MAD_F(0x04f70f7b) /* 0.310317499 */, 16 },
- /* 1704 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 16 },
- /* 1705 */ { MAD_F(0x04f90d19) /* 0.310803509 */, 16 },
- /* 1706 */ { MAD_F(0x04fa0bfc) /* 0.311046586 */, 16 },
- /* 1707 */ { MAD_F(0x04fb0aeb) /* 0.311289710 */, 16 },
- /* 1708 */ { MAD_F(0x04fc09e7) /* 0.311532881 */, 16 },
- /* 1709 */ { MAD_F(0x04fd08ef) /* 0.311776100 */, 16 },
- /* 1710 */ { MAD_F(0x04fe0805) /* 0.312019366 */, 16 },
- /* 1711 */ { MAD_F(0x04ff0727) /* 0.312262680 */, 16 },
-
- /* 1712 */ { MAD_F(0x05000655) /* 0.312506041 */, 16 },
- /* 1713 */ { MAD_F(0x05010591) /* 0.312749449 */, 16 },
- /* 1714 */ { MAD_F(0x050204d9) /* 0.312992905 */, 16 },
- /* 1715 */ { MAD_F(0x0503042e) /* 0.313236408 */, 16 },
- /* 1716 */ { MAD_F(0x0504038f) /* 0.313479959 */, 16 },
- /* 1717 */ { MAD_F(0x050502fe) /* 0.313723556 */, 16 },
- /* 1718 */ { MAD_F(0x05060279) /* 0.313967202 */, 16 },
- /* 1719 */ { MAD_F(0x05070200) /* 0.314210894 */, 16 },
- /* 1720 */ { MAD_F(0x05080195) /* 0.314454634 */, 16 },
- /* 1721 */ { MAD_F(0x05090136) /* 0.314698420 */, 16 },
- /* 1722 */ { MAD_F(0x050a00e3) /* 0.314942255 */, 16 },
- /* 1723 */ { MAD_F(0x050b009e) /* 0.315186136 */, 16 },
- /* 1724 */ { MAD_F(0x050c0065) /* 0.315430064 */, 16 },
- /* 1725 */ { MAD_F(0x050d0039) /* 0.315674040 */, 16 },
- /* 1726 */ { MAD_F(0x050e0019) /* 0.315918063 */, 16 },
- /* 1727 */ { MAD_F(0x050f0006) /* 0.316162133 */, 16 },
-
- /* 1728 */ { MAD_F(0x05100000) /* 0.316406250 */, 16 },
- /* 1729 */ { MAD_F(0x05110006) /* 0.316650414 */, 16 },
- /* 1730 */ { MAD_F(0x05120019) /* 0.316894625 */, 16 },
- /* 1731 */ { MAD_F(0x05130039) /* 0.317138884 */, 16 },
- /* 1732 */ { MAD_F(0x05140065) /* 0.317383189 */, 16 },
- /* 1733 */ { MAD_F(0x0515009e) /* 0.317627541 */, 16 },
- /* 1734 */ { MAD_F(0x051600e3) /* 0.317871941 */, 16 },
- /* 1735 */ { MAD_F(0x05170135) /* 0.318116387 */, 16 },
- /* 1736 */ { MAD_F(0x05180194) /* 0.318360880 */, 16 },
- /* 1737 */ { MAD_F(0x051901ff) /* 0.318605421 */, 16 },
- /* 1738 */ { MAD_F(0x051a0277) /* 0.318850008 */, 16 },
- /* 1739 */ { MAD_F(0x051b02fc) /* 0.319094642 */, 16 },
- /* 1740 */ { MAD_F(0x051c038d) /* 0.319339323 */, 16 },
- /* 1741 */ { MAD_F(0x051d042a) /* 0.319584051 */, 16 },
- /* 1742 */ { MAD_F(0x051e04d4) /* 0.319828826 */, 16 },
- /* 1743 */ { MAD_F(0x051f058b) /* 0.320073647 */, 16 },
-
- /* 1744 */ { MAD_F(0x0520064f) /* 0.320318516 */, 16 },
- /* 1745 */ { MAD_F(0x0521071f) /* 0.320563431 */, 16 },
- /* 1746 */ { MAD_F(0x052207fb) /* 0.320808393 */, 16 },
- /* 1747 */ { MAD_F(0x052308e4) /* 0.321053402 */, 16 },
- /* 1748 */ { MAD_F(0x052409da) /* 0.321298457 */, 16 },
- /* 1749 */ { MAD_F(0x05250adc) /* 0.321543560 */, 16 },
- /* 1750 */ { MAD_F(0x05260bea) /* 0.321788709 */, 16 },
- /* 1751 */ { MAD_F(0x05270d06) /* 0.322033904 */, 16 },
- /* 1752 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 16 },
- /* 1753 */ { MAD_F(0x05290f62) /* 0.322524436 */, 16 },
- /* 1754 */ { MAD_F(0x052a10a3) /* 0.322769771 */, 16 },
- /* 1755 */ { MAD_F(0x052b11f0) /* 0.323015154 */, 16 },
- /* 1756 */ { MAD_F(0x052c134a) /* 0.323260583 */, 16 },
- /* 1757 */ { MAD_F(0x052d14b0) /* 0.323506058 */, 16 },
- /* 1758 */ { MAD_F(0x052e1623) /* 0.323751580 */, 16 },
- /* 1759 */ { MAD_F(0x052f17a2) /* 0.323997149 */, 16 },
-
- /* 1760 */ { MAD_F(0x0530192e) /* 0.324242764 */, 16 },
- /* 1761 */ { MAD_F(0x05311ac6) /* 0.324488426 */, 16 },
- /* 1762 */ { MAD_F(0x05321c6b) /* 0.324734134 */, 16 },
- /* 1763 */ { MAD_F(0x05331e1c) /* 0.324979889 */, 16 },
- /* 1764 */ { MAD_F(0x05341fda) /* 0.325225690 */, 16 },
- /* 1765 */ { MAD_F(0x053521a4) /* 0.325471538 */, 16 },
- /* 1766 */ { MAD_F(0x0536237b) /* 0.325717432 */, 16 },
- /* 1767 */ { MAD_F(0x0537255e) /* 0.325963372 */, 16 },
- /* 1768 */ { MAD_F(0x0538274e) /* 0.326209359 */, 16 },
- /* 1769 */ { MAD_F(0x0539294a) /* 0.326455392 */, 16 },
- /* 1770 */ { MAD_F(0x053a2b52) /* 0.326701472 */, 16 },
- /* 1771 */ { MAD_F(0x053b2d67) /* 0.326947598 */, 16 },
- /* 1772 */ { MAD_F(0x053c2f89) /* 0.327193770 */, 16 },
- /* 1773 */ { MAD_F(0x053d31b6) /* 0.327439989 */, 16 },
- /* 1774 */ { MAD_F(0x053e33f1) /* 0.327686254 */, 16 },
- /* 1775 */ { MAD_F(0x053f3637) /* 0.327932565 */, 16 },
-
- /* 1776 */ { MAD_F(0x0540388a) /* 0.328178922 */, 16 },
- /* 1777 */ { MAD_F(0x05413aea) /* 0.328425326 */, 16 },
- /* 1778 */ { MAD_F(0x05423d56) /* 0.328671776 */, 16 },
- /* 1779 */ { MAD_F(0x05433fce) /* 0.328918272 */, 16 },
- /* 1780 */ { MAD_F(0x05444253) /* 0.329164814 */, 16 },
- /* 1781 */ { MAD_F(0x054544e4) /* 0.329411403 */, 16 },
- /* 1782 */ { MAD_F(0x05464781) /* 0.329658038 */, 16 },
- /* 1783 */ { MAD_F(0x05474a2b) /* 0.329904718 */, 16 },
- /* 1784 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 16 },
- /* 1785 */ { MAD_F(0x05494fa4) /* 0.330398218 */, 16 },
- /* 1786 */ { MAD_F(0x054a5273) /* 0.330645037 */, 16 },
- /* 1787 */ { MAD_F(0x054b554e) /* 0.330891903 */, 16 },
- /* 1788 */ { MAD_F(0x054c5836) /* 0.331138814 */, 16 },
- /* 1789 */ { MAD_F(0x054d5b2a) /* 0.331385771 */, 16 },
- /* 1790 */ { MAD_F(0x054e5e2b) /* 0.331632774 */, 16 },
- /* 1791 */ { MAD_F(0x054f6138) /* 0.331879824 */, 16 },
-
- /* 1792 */ { MAD_F(0x05506451) /* 0.332126919 */, 16 },
- /* 1793 */ { MAD_F(0x05516776) /* 0.332374060 */, 16 },
- /* 1794 */ { MAD_F(0x05526aa8) /* 0.332621247 */, 16 },
- /* 1795 */ { MAD_F(0x05536de6) /* 0.332868480 */, 16 },
- /* 1796 */ { MAD_F(0x05547131) /* 0.333115759 */, 16 },
- /* 1797 */ { MAD_F(0x05557487) /* 0.333363084 */, 16 },
- /* 1798 */ { MAD_F(0x055677ea) /* 0.333610455 */, 16 },
- /* 1799 */ { MAD_F(0x05577b5a) /* 0.333857872 */, 16 },
- /* 1800 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 16 },
- /* 1801 */ { MAD_F(0x0559825e) /* 0.334352843 */, 16 },
- /* 1802 */ { MAD_F(0x055a85f2) /* 0.334600397 */, 16 },
- /* 1803 */ { MAD_F(0x055b8992) /* 0.334847997 */, 16 },
- /* 1804 */ { MAD_F(0x055c8d3f) /* 0.335095642 */, 16 },
- /* 1805 */ { MAD_F(0x055d90f9) /* 0.335343334 */, 16 },
- /* 1806 */ { MAD_F(0x055e94be) /* 0.335591071 */, 16 },
- /* 1807 */ { MAD_F(0x055f9890) /* 0.335838854 */, 16 },
-
- /* 1808 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 16 },
- /* 1809 */ { MAD_F(0x0561a058) /* 0.336334557 */, 16 },
- /* 1810 */ { MAD_F(0x0562a44f) /* 0.336582477 */, 16 },
- /* 1811 */ { MAD_F(0x0563a851) /* 0.336830443 */, 16 },
- /* 1812 */ { MAD_F(0x0564ac60) /* 0.337078454 */, 16 },
- /* 1813 */ { MAD_F(0x0565b07c) /* 0.337326511 */, 16 },
- /* 1814 */ { MAD_F(0x0566b4a3) /* 0.337574614 */, 16 },
- /* 1815 */ { MAD_F(0x0567b8d7) /* 0.337822762 */, 16 },
- /* 1816 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 16 },
- /* 1817 */ { MAD_F(0x0569c163) /* 0.338319195 */, 16 },
- /* 1818 */ { MAD_F(0x056ac5bc) /* 0.338567480 */, 16 },
- /* 1819 */ { MAD_F(0x056bca20) /* 0.338815811 */, 16 },
- /* 1820 */ { MAD_F(0x056cce91) /* 0.339064186 */, 16 },
- /* 1821 */ { MAD_F(0x056dd30e) /* 0.339312608 */, 16 },
- /* 1822 */ { MAD_F(0x056ed798) /* 0.339561075 */, 16 },
- /* 1823 */ { MAD_F(0x056fdc2d) /* 0.339809587 */, 16 },
-
- /* 1824 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 16 },
- /* 1825 */ { MAD_F(0x0571e57d) /* 0.340306748 */, 16 },
- /* 1826 */ { MAD_F(0x0572ea37) /* 0.340555397 */, 16 },
- /* 1827 */ { MAD_F(0x0573eefd) /* 0.340804091 */, 16 },
- /* 1828 */ { MAD_F(0x0574f3d0) /* 0.341052830 */, 16 },
- /* 1829 */ { MAD_F(0x0575f8ae) /* 0.341301615 */, 16 },
- /* 1830 */ { MAD_F(0x0576fd99) /* 0.341550445 */, 16 },
- /* 1831 */ { MAD_F(0x05780290) /* 0.341799321 */, 16 },
- /* 1832 */ { MAD_F(0x05790793) /* 0.342048241 */, 16 },
- /* 1833 */ { MAD_F(0x057a0ca3) /* 0.342297207 */, 16 },
- /* 1834 */ { MAD_F(0x057b11be) /* 0.342546219 */, 16 },
- /* 1835 */ { MAD_F(0x057c16e6) /* 0.342795275 */, 16 },
- /* 1836 */ { MAD_F(0x057d1c1a) /* 0.343044377 */, 16 },
- /* 1837 */ { MAD_F(0x057e2159) /* 0.343293524 */, 16 },
- /* 1838 */ { MAD_F(0x057f26a6) /* 0.343542717 */, 16 },
- /* 1839 */ { MAD_F(0x05802bfe) /* 0.343791954 */, 16 },
-
- /* 1840 */ { MAD_F(0x05813162) /* 0.344041237 */, 16 },
- /* 1841 */ { MAD_F(0x058236d2) /* 0.344290564 */, 16 },
- /* 1842 */ { MAD_F(0x05833c4f) /* 0.344539937 */, 16 },
- /* 1843 */ { MAD_F(0x058441d8) /* 0.344789356 */, 16 },
- /* 1844 */ { MAD_F(0x0585476c) /* 0.345038819 */, 16 },
- /* 1845 */ { MAD_F(0x05864d0d) /* 0.345288327 */, 16 },
- /* 1846 */ { MAD_F(0x058752ba) /* 0.345537880 */, 16 },
- /* 1847 */ { MAD_F(0x05885873) /* 0.345787479 */, 16 },
- /* 1848 */ { MAD_F(0x05895e39) /* 0.346037122 */, 16 },
- /* 1849 */ { MAD_F(0x058a640a) /* 0.346286811 */, 16 },
- /* 1850 */ { MAD_F(0x058b69e7) /* 0.346536545 */, 16 },
- /* 1851 */ { MAD_F(0x058c6fd1) /* 0.346786323 */, 16 },
- /* 1852 */ { MAD_F(0x058d75c6) /* 0.347036147 */, 16 },
- /* 1853 */ { MAD_F(0x058e7bc8) /* 0.347286015 */, 16 },
- /* 1854 */ { MAD_F(0x058f81d5) /* 0.347535929 */, 16 },
- /* 1855 */ { MAD_F(0x059087ef) /* 0.347785887 */, 16 },
-
- /* 1856 */ { MAD_F(0x05918e15) /* 0.348035890 */, 16 },
- /* 1857 */ { MAD_F(0x05929447) /* 0.348285939 */, 16 },
- /* 1858 */ { MAD_F(0x05939a84) /* 0.348536032 */, 16 },
- /* 1859 */ { MAD_F(0x0594a0ce) /* 0.348786170 */, 16 },
- /* 1860 */ { MAD_F(0x0595a724) /* 0.349036353 */, 16 },
- /* 1861 */ { MAD_F(0x0596ad86) /* 0.349286580 */, 16 },
- /* 1862 */ { MAD_F(0x0597b3f4) /* 0.349536853 */, 16 },
- /* 1863 */ { MAD_F(0x0598ba6e) /* 0.349787170 */, 16 },
- /* 1864 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 16 },
- /* 1865 */ { MAD_F(0x059ac786) /* 0.350287939 */, 16 },
- /* 1866 */ { MAD_F(0x059bce25) /* 0.350538391 */, 16 },
- /* 1867 */ { MAD_F(0x059cd4cf) /* 0.350788887 */, 16 },
- /* 1868 */ { MAD_F(0x059ddb85) /* 0.351039428 */, 16 },
- /* 1869 */ { MAD_F(0x059ee247) /* 0.351290014 */, 16 },
- /* 1870 */ { MAD_F(0x059fe915) /* 0.351540645 */, 16 },
- /* 1871 */ { MAD_F(0x05a0efef) /* 0.351791320 */, 16 },
-
- /* 1872 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 16 },
- /* 1873 */ { MAD_F(0x05a2fdc7) /* 0.352292804 */, 16 },
- /* 1874 */ { MAD_F(0x05a404c5) /* 0.352543613 */, 16 },
- /* 1875 */ { MAD_F(0x05a50bcf) /* 0.352794467 */, 16 },
- /* 1876 */ { MAD_F(0x05a612e5) /* 0.353045365 */, 16 },
- /* 1877 */ { MAD_F(0x05a71a07) /* 0.353296308 */, 16 },
- /* 1878 */ { MAD_F(0x05a82135) /* 0.353547296 */, 16 },
- /* 1879 */ { MAD_F(0x05a9286f) /* 0.353798328 */, 16 },
- /* 1880 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 16 },
- /* 1881 */ { MAD_F(0x05ab3707) /* 0.354300526 */, 16 },
- /* 1882 */ { MAD_F(0x05ac3e65) /* 0.354551691 */, 16 },
- /* 1883 */ { MAD_F(0x05ad45ce) /* 0.354802901 */, 16 },
- /* 1884 */ { MAD_F(0x05ae4d44) /* 0.355054156 */, 16 },
- /* 1885 */ { MAD_F(0x05af54c6) /* 0.355305455 */, 16 },
- /* 1886 */ { MAD_F(0x05b05c53) /* 0.355556799 */, 16 },
- /* 1887 */ { MAD_F(0x05b163ed) /* 0.355808187 */, 16 },
-
- /* 1888 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 16 },
- /* 1889 */ { MAD_F(0x05b37343) /* 0.356311096 */, 16 },
- /* 1890 */ { MAD_F(0x05b47b00) /* 0.356562617 */, 16 },
- /* 1891 */ { MAD_F(0x05b582c9) /* 0.356814182 */, 16 },
- /* 1892 */ { MAD_F(0x05b68a9e) /* 0.357065792 */, 16 },
- /* 1893 */ { MAD_F(0x05b7927f) /* 0.357317446 */, 16 },
- /* 1894 */ { MAD_F(0x05b89a6c) /* 0.357569145 */, 16 },
- /* 1895 */ { MAD_F(0x05b9a265) /* 0.357820887 */, 16 },
- /* 1896 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 16 },
- /* 1897 */ { MAD_F(0x05bbb27a) /* 0.358324506 */, 16 },
- /* 1898 */ { MAD_F(0x05bcba96) /* 0.358576381 */, 16 },
- /* 1899 */ { MAD_F(0x05bdc2be) /* 0.358828301 */, 16 },
- /* 1900 */ { MAD_F(0x05becaf2) /* 0.359080265 */, 16 },
- /* 1901 */ { MAD_F(0x05bfd332) /* 0.359332273 */, 16 },
- /* 1902 */ { MAD_F(0x05c0db7e) /* 0.359584326 */, 16 },
- /* 1903 */ { MAD_F(0x05c1e3d6) /* 0.359836423 */, 16 },
-
- /* 1904 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 16 },
- /* 1905 */ { MAD_F(0x05c3f4a9) /* 0.360340748 */, 16 },
- /* 1906 */ { MAD_F(0x05c4fd24) /* 0.360592977 */, 16 },
- /* 1907 */ { MAD_F(0x05c605ab) /* 0.360845251 */, 16 },
- /* 1908 */ { MAD_F(0x05c70e3e) /* 0.361097568 */, 16 },
- /* 1909 */ { MAD_F(0x05c816dd) /* 0.361349929 */, 16 },
- /* 1910 */ { MAD_F(0x05c91f87) /* 0.361602335 */, 16 },
- /* 1911 */ { MAD_F(0x05ca283e) /* 0.361854784 */, 16 },
- /* 1912 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 16 },
- /* 1913 */ { MAD_F(0x05cc39ce) /* 0.362359815 */, 16 },
- /* 1914 */ { MAD_F(0x05cd42a8) /* 0.362612397 */, 16 },
- /* 1915 */ { MAD_F(0x05ce4b8d) /* 0.362865022 */, 16 },
- /* 1916 */ { MAD_F(0x05cf547f) /* 0.363117692 */, 16 },
- /* 1917 */ { MAD_F(0x05d05d7c) /* 0.363370405 */, 16 },
- /* 1918 */ { MAD_F(0x05d16685) /* 0.363623163 */, 16 },
- /* 1919 */ { MAD_F(0x05d26f9a) /* 0.363875964 */, 16 },
-
- /* 1920 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 16 },
- /* 1921 */ { MAD_F(0x05d481e7) /* 0.364381698 */, 16 },
- /* 1922 */ { MAD_F(0x05d58b1f) /* 0.364634632 */, 16 },
- /* 1923 */ { MAD_F(0x05d69463) /* 0.364887608 */, 16 },
- /* 1924 */ { MAD_F(0x05d79db3) /* 0.365140629 */, 16 },
- /* 1925 */ { MAD_F(0x05d8a70f) /* 0.365393694 */, 16 },
- /* 1926 */ { MAD_F(0x05d9b076) /* 0.365646802 */, 16 },
- /* 1927 */ { MAD_F(0x05dab9e9) /* 0.365899955 */, 16 },
- /* 1928 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 16 },
- /* 1929 */ { MAD_F(0x05dcccf2) /* 0.366406390 */, 16 },
- /* 1930 */ { MAD_F(0x05ddd689) /* 0.366659674 */, 16 },
- /* 1931 */ { MAD_F(0x05dee02b) /* 0.366913001 */, 16 },
- /* 1932 */ { MAD_F(0x05dfe9d8) /* 0.367166372 */, 16 },
- /* 1933 */ { MAD_F(0x05e0f392) /* 0.367419787 */, 16 },
- /* 1934 */ { MAD_F(0x05e1fd57) /* 0.367673246 */, 16 },
- /* 1935 */ { MAD_F(0x05e30728) /* 0.367926748 */, 16 },
-
- /* 1936 */ { MAD_F(0x05e41105) /* 0.368180294 */, 16 },
- /* 1937 */ { MAD_F(0x05e51aed) /* 0.368433883 */, 16 },
- /* 1938 */ { MAD_F(0x05e624e1) /* 0.368687517 */, 16 },
- /* 1939 */ { MAD_F(0x05e72ee1) /* 0.368941193 */, 16 },
- /* 1940 */ { MAD_F(0x05e838ed) /* 0.369194914 */, 16 },
- /* 1941 */ { MAD_F(0x05e94304) /* 0.369448678 */, 16 },
- /* 1942 */ { MAD_F(0x05ea4d27) /* 0.369702485 */, 16 },
- /* 1943 */ { MAD_F(0x05eb5756) /* 0.369956336 */, 16 },
- /* 1944 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 16 },
- /* 1945 */ { MAD_F(0x05ed6bd6) /* 0.370464169 */, 16 },
- /* 1946 */ { MAD_F(0x05ee7628) /* 0.370718151 */, 16 },
- /* 1947 */ { MAD_F(0x05ef8085) /* 0.370972177 */, 16 },
- /* 1948 */ { MAD_F(0x05f08aee) /* 0.371226245 */, 16 },
- /* 1949 */ { MAD_F(0x05f19563) /* 0.371480358 */, 16 },
- /* 1950 */ { MAD_F(0x05f29fe3) /* 0.371734513 */, 16 },
- /* 1951 */ { MAD_F(0x05f3aa6f) /* 0.371988712 */, 16 },
-
- /* 1952 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 16 },
- /* 1953 */ { MAD_F(0x05f5bfab) /* 0.372497241 */, 16 },
- /* 1954 */ { MAD_F(0x05f6ca5a) /* 0.372751570 */, 16 },
- /* 1955 */ { MAD_F(0x05f7d514) /* 0.373005943 */, 16 },
- /* 1956 */ { MAD_F(0x05f8dfdb) /* 0.373260359 */, 16 },
- /* 1957 */ { MAD_F(0x05f9eaad) /* 0.373514819 */, 16 },
- /* 1958 */ { MAD_F(0x05faf58a) /* 0.373769322 */, 16 },
- /* 1959 */ { MAD_F(0x05fc0073) /* 0.374023868 */, 16 },
- /* 1960 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 16 },
- /* 1961 */ { MAD_F(0x05fe1669) /* 0.374533091 */, 16 },
- /* 1962 */ { MAD_F(0x05ff2175) /* 0.374787767 */, 16 },
- /* 1963 */ { MAD_F(0x06002c8d) /* 0.375042486 */, 16 },
- /* 1964 */ { MAD_F(0x060137b0) /* 0.375297249 */, 16 },
- /* 1965 */ { MAD_F(0x060242df) /* 0.375552055 */, 16 },
- /* 1966 */ { MAD_F(0x06034e19) /* 0.375806904 */, 16 },
- /* 1967 */ { MAD_F(0x0604595f) /* 0.376061796 */, 16 },
-
- /* 1968 */ { MAD_F(0x060564b1) /* 0.376316732 */, 16 },
- /* 1969 */ { MAD_F(0x0606700f) /* 0.376571710 */, 16 },
- /* 1970 */ { MAD_F(0x06077b77) /* 0.376826732 */, 16 },
- /* 1971 */ { MAD_F(0x060886ec) /* 0.377081797 */, 16 },
- /* 1972 */ { MAD_F(0x0609926c) /* 0.377336905 */, 16 },
- /* 1973 */ { MAD_F(0x060a9df8) /* 0.377592057 */, 16 },
- /* 1974 */ { MAD_F(0x060ba98f) /* 0.377847251 */, 16 },
- /* 1975 */ { MAD_F(0x060cb532) /* 0.378102489 */, 16 },
- /* 1976 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 16 },
- /* 1977 */ { MAD_F(0x060ecc9a) /* 0.378613093 */, 16 },
- /* 1978 */ { MAD_F(0x060fd860) /* 0.378868460 */, 16 },
- /* 1979 */ { MAD_F(0x0610e431) /* 0.379123870 */, 16 },
- /* 1980 */ { MAD_F(0x0611f00d) /* 0.379379322 */, 16 },
- /* 1981 */ { MAD_F(0x0612fbf5) /* 0.379634818 */, 16 },
- /* 1982 */ { MAD_F(0x061407e9) /* 0.379890357 */, 16 },
- /* 1983 */ { MAD_F(0x061513e8) /* 0.380145939 */, 16 },
-
- /* 1984 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 16 },
- /* 1985 */ { MAD_F(0x06172c09) /* 0.380657231 */, 16 },
- /* 1986 */ { MAD_F(0x0618382b) /* 0.380912942 */, 16 },
- /* 1987 */ { MAD_F(0x06194458) /* 0.381168695 */, 16 },
- /* 1988 */ { MAD_F(0x061a5091) /* 0.381424492 */, 16 },
- /* 1989 */ { MAD_F(0x061b5cd5) /* 0.381680331 */, 16 },
- /* 1990 */ { MAD_F(0x061c6925) /* 0.381936213 */, 16 },
- /* 1991 */ { MAD_F(0x061d7581) /* 0.382192138 */, 16 },
- /* 1992 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 16 },
- /* 1993 */ { MAD_F(0x061f8e5a) /* 0.382704117 */, 16 },
- /* 1994 */ { MAD_F(0x06209ad8) /* 0.382960171 */, 16 },
- /* 1995 */ { MAD_F(0x0621a761) /* 0.383216267 */, 16 },
- /* 1996 */ { MAD_F(0x0622b3f6) /* 0.383472406 */, 16 },
- /* 1997 */ { MAD_F(0x0623c096) /* 0.383728588 */, 16 },
- /* 1998 */ { MAD_F(0x0624cd42) /* 0.383984813 */, 16 },
- /* 1999 */ { MAD_F(0x0625d9f9) /* 0.384241080 */, 16 },
-
- /* 2000 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 16 },
- /* 2001 */ { MAD_F(0x0627f38a) /* 0.384753744 */, 16 },
- /* 2002 */ { MAD_F(0x06290064) /* 0.385010139 */, 16 },
- /* 2003 */ { MAD_F(0x062a0d49) /* 0.385266578 */, 16 },
- /* 2004 */ { MAD_F(0x062b1a3a) /* 0.385523059 */, 16 },
- /* 2005 */ { MAD_F(0x062c2736) /* 0.385779582 */, 16 },
- /* 2006 */ { MAD_F(0x062d343d) /* 0.386036149 */, 16 },
- /* 2007 */ { MAD_F(0x062e4150) /* 0.386292758 */, 16 },
- /* 2008 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 16 },
- /* 2009 */ { MAD_F(0x06305b99) /* 0.386806104 */, 16 },
- /* 2010 */ { MAD_F(0x063168ce) /* 0.387062840 */, 16 },
- /* 2011 */ { MAD_F(0x0632760f) /* 0.387319620 */, 16 },
- /* 2012 */ { MAD_F(0x0633835b) /* 0.387576442 */, 16 },
- /* 2013 */ { MAD_F(0x063490b2) /* 0.387833306 */, 16 },
- /* 2014 */ { MAD_F(0x06359e15) /* 0.388090213 */, 16 },
- /* 2015 */ { MAD_F(0x0636ab83) /* 0.388347163 */, 16 },
-
- /* 2016 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 16 },
- /* 2017 */ { MAD_F(0x0638c682) /* 0.388861190 */, 16 },
- /* 2018 */ { MAD_F(0x0639d413) /* 0.389118267 */, 16 },
- /* 2019 */ { MAD_F(0x063ae1af) /* 0.389375386 */, 16 },
- /* 2020 */ { MAD_F(0x063bef56) /* 0.389632548 */, 16 },
- /* 2021 */ { MAD_F(0x063cfd09) /* 0.389889752 */, 16 },
- /* 2022 */ { MAD_F(0x063e0ac7) /* 0.390146999 */, 16 },
- /* 2023 */ { MAD_F(0x063f1891) /* 0.390404289 */, 16 },
- /* 2024 */ { MAD_F(0x06402666) /* 0.390661620 */, 16 },
- /* 2025 */ { MAD_F(0x06413446) /* 0.390918994 */, 16 },
- /* 2026 */ { MAD_F(0x06424232) /* 0.391176411 */, 16 },
- /* 2027 */ { MAD_F(0x06435029) /* 0.391433869 */, 16 },
- /* 2028 */ { MAD_F(0x06445e2b) /* 0.391691371 */, 16 },
- /* 2029 */ { MAD_F(0x06456c39) /* 0.391948914 */, 16 },
- /* 2030 */ { MAD_F(0x06467a52) /* 0.392206500 */, 16 },
- /* 2031 */ { MAD_F(0x06478877) /* 0.392464128 */, 16 },
-
- /* 2032 */ { MAD_F(0x064896a7) /* 0.392721798 */, 16 },
- /* 2033 */ { MAD_F(0x0649a4e2) /* 0.392979511 */, 16 },
- /* 2034 */ { MAD_F(0x064ab328) /* 0.393237266 */, 16 },
- /* 2035 */ { MAD_F(0x064bc17a) /* 0.393495063 */, 16 },
- /* 2036 */ { MAD_F(0x064ccfd8) /* 0.393752902 */, 16 },
- /* 2037 */ { MAD_F(0x064dde40) /* 0.394010784 */, 16 },
- /* 2038 */ { MAD_F(0x064eecb4) /* 0.394268707 */, 16 },
- /* 2039 */ { MAD_F(0x064ffb33) /* 0.394526673 */, 16 },
- /* 2040 */ { MAD_F(0x065109be) /* 0.394784681 */, 16 },
- /* 2041 */ { MAD_F(0x06521854) /* 0.395042732 */, 16 },
- /* 2042 */ { MAD_F(0x065326f5) /* 0.395300824 */, 16 },
- /* 2043 */ { MAD_F(0x065435a1) /* 0.395558959 */, 16 },
- /* 2044 */ { MAD_F(0x06554459) /* 0.395817135 */, 16 },
- /* 2045 */ { MAD_F(0x0656531c) /* 0.396075354 */, 16 },
- /* 2046 */ { MAD_F(0x065761ea) /* 0.396333615 */, 16 },
- /* 2047 */ { MAD_F(0x065870c4) /* 0.396591918 */, 16 },
-
- /* 2048 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 16 },
- /* 2049 */ { MAD_F(0x065a8e99) /* 0.397108650 */, 16 },
- /* 2050 */ { MAD_F(0x065b9d95) /* 0.397367079 */, 16 },
- /* 2051 */ { MAD_F(0x065cac9c) /* 0.397625550 */, 16 },
- /* 2052 */ { MAD_F(0x065dbbae) /* 0.397884063 */, 16 },
- /* 2053 */ { MAD_F(0x065ecacb) /* 0.398142619 */, 16 },
- /* 2054 */ { MAD_F(0x065fd9f4) /* 0.398401216 */, 16 },
- /* 2055 */ { MAD_F(0x0660e928) /* 0.398659855 */, 16 },
- /* 2056 */ { MAD_F(0x0661f867) /* 0.398918536 */, 16 },
- /* 2057 */ { MAD_F(0x066307b1) /* 0.399177259 */, 16 },
- /* 2058 */ { MAD_F(0x06641707) /* 0.399436024 */, 16 },
- /* 2059 */ { MAD_F(0x06652668) /* 0.399694831 */, 16 },
- /* 2060 */ { MAD_F(0x066635d4) /* 0.399953679 */, 16 },
- /* 2061 */ { MAD_F(0x0667454c) /* 0.400212570 */, 16 },
- /* 2062 */ { MAD_F(0x066854ce) /* 0.400471503 */, 16 },
- /* 2063 */ { MAD_F(0x0669645c) /* 0.400730477 */, 16 },
-
- /* 2064 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 16 },
- /* 2065 */ { MAD_F(0x066b839a) /* 0.401248551 */, 16 },
- /* 2066 */ { MAD_F(0x066c9349) /* 0.401507651 */, 16 },
- /* 2067 */ { MAD_F(0x066da304) /* 0.401766793 */, 16 },
- /* 2068 */ { MAD_F(0x066eb2ca) /* 0.402025976 */, 16 },
- /* 2069 */ { MAD_F(0x066fc29b) /* 0.402285202 */, 16 },
- /* 2070 */ { MAD_F(0x0670d278) /* 0.402544469 */, 16 },
- /* 2071 */ { MAD_F(0x0671e25f) /* 0.402803777 */, 16 },
- /* 2072 */ { MAD_F(0x0672f252) /* 0.403063128 */, 16 },
- /* 2073 */ { MAD_F(0x06740250) /* 0.403322520 */, 16 },
- /* 2074 */ { MAD_F(0x0675125a) /* 0.403581954 */, 16 },
- /* 2075 */ { MAD_F(0x0676226e) /* 0.403841430 */, 16 },
- /* 2076 */ { MAD_F(0x0677328e) /* 0.404100947 */, 16 },
- /* 2077 */ { MAD_F(0x067842b9) /* 0.404360506 */, 16 },
- /* 2078 */ { MAD_F(0x067952ef) /* 0.404620107 */, 16 },
- /* 2079 */ { MAD_F(0x067a6330) /* 0.404879749 */, 16 },
-
- /* 2080 */ { MAD_F(0x067b737c) /* 0.405139433 */, 16 },
- /* 2081 */ { MAD_F(0x067c83d4) /* 0.405399159 */, 16 },
- /* 2082 */ { MAD_F(0x067d9436) /* 0.405658926 */, 16 },
- /* 2083 */ { MAD_F(0x067ea4a4) /* 0.405918735 */, 16 },
- /* 2084 */ { MAD_F(0x067fb51d) /* 0.406178585 */, 16 },
- /* 2085 */ { MAD_F(0x0680c5a2) /* 0.406438477 */, 16 },
- /* 2086 */ { MAD_F(0x0681d631) /* 0.406698410 */, 16 },
- /* 2087 */ { MAD_F(0x0682e6cb) /* 0.406958385 */, 16 },
- /* 2088 */ { MAD_F(0x0683f771) /* 0.407218402 */, 16 },
- /* 2089 */ { MAD_F(0x06850822) /* 0.407478460 */, 16 },
- /* 2090 */ { MAD_F(0x068618de) /* 0.407738559 */, 16 },
- /* 2091 */ { MAD_F(0x068729a5) /* 0.407998700 */, 16 },
- /* 2092 */ { MAD_F(0x06883a77) /* 0.408258883 */, 16 },
- /* 2093 */ { MAD_F(0x06894b55) /* 0.408519107 */, 16 },
- /* 2094 */ { MAD_F(0x068a5c3d) /* 0.408779372 */, 16 },
- /* 2095 */ { MAD_F(0x068b6d31) /* 0.409039679 */, 16 },
-
- /* 2096 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 16 },
- /* 2097 */ { MAD_F(0x068d8f39) /* 0.409560417 */, 16 },
- /* 2098 */ { MAD_F(0x068ea04e) /* 0.409820848 */, 16 },
- /* 2099 */ { MAD_F(0x068fb16e) /* 0.410081321 */, 16 },
- /* 2100 */ { MAD_F(0x0690c299) /* 0.410341834 */, 16 },
- /* 2101 */ { MAD_F(0x0691d3cf) /* 0.410602390 */, 16 },
- /* 2102 */ { MAD_F(0x0692e511) /* 0.410862986 */, 16 },
- /* 2103 */ { MAD_F(0x0693f65d) /* 0.411123624 */, 16 },
- /* 2104 */ { MAD_F(0x069507b5) /* 0.411384303 */, 16 },
- /* 2105 */ { MAD_F(0x06961917) /* 0.411645024 */, 16 },
- /* 2106 */ { MAD_F(0x06972a85) /* 0.411905785 */, 16 },
- /* 2107 */ { MAD_F(0x06983bfe) /* 0.412166588 */, 16 },
- /* 2108 */ { MAD_F(0x06994d82) /* 0.412427433 */, 16 },
- /* 2109 */ { MAD_F(0x069a5f11) /* 0.412688318 */, 16 },
- /* 2110 */ { MAD_F(0x069b70ab) /* 0.412949245 */, 16 },
- /* 2111 */ { MAD_F(0x069c8250) /* 0.413210213 */, 16 },
-
- /* 2112 */ { MAD_F(0x069d9400) /* 0.413471222 */, 16 },
- /* 2113 */ { MAD_F(0x069ea5bb) /* 0.413732273 */, 16 },
- /* 2114 */ { MAD_F(0x069fb781) /* 0.413993364 */, 16 },
- /* 2115 */ { MAD_F(0x06a0c953) /* 0.414254497 */, 16 },
- /* 2116 */ { MAD_F(0x06a1db2f) /* 0.414515671 */, 16 },
- /* 2117 */ { MAD_F(0x06a2ed16) /* 0.414776886 */, 16 },
- /* 2118 */ { MAD_F(0x06a3ff09) /* 0.415038142 */, 16 },
- /* 2119 */ { MAD_F(0x06a51106) /* 0.415299440 */, 16 },
- /* 2120 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 16 },
- /* 2121 */ { MAD_F(0x06a73522) /* 0.415822157 */, 16 },
- /* 2122 */ { MAD_F(0x06a84741) /* 0.416083578 */, 16 },
- /* 2123 */ { MAD_F(0x06a9596a) /* 0.416345040 */, 16 },
- /* 2124 */ { MAD_F(0x06aa6b9f) /* 0.416606542 */, 16 },
- /* 2125 */ { MAD_F(0x06ab7ddf) /* 0.416868086 */, 16 },
- /* 2126 */ { MAD_F(0x06ac9029) /* 0.417129671 */, 16 },
- /* 2127 */ { MAD_F(0x06ada27f) /* 0.417391297 */, 16 },
-
- /* 2128 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 16 },
- /* 2129 */ { MAD_F(0x06afc74b) /* 0.417914672 */, 16 },
- /* 2130 */ { MAD_F(0x06b0d9c2) /* 0.418176420 */, 16 },
- /* 2131 */ { MAD_F(0x06b1ec43) /* 0.418438210 */, 16 },
- /* 2132 */ { MAD_F(0x06b2fed0) /* 0.418700041 */, 16 },
- /* 2133 */ { MAD_F(0x06b41168) /* 0.418961912 */, 16 },
- /* 2134 */ { MAD_F(0x06b5240a) /* 0.419223825 */, 16 },
- /* 2135 */ { MAD_F(0x06b636b8) /* 0.419485778 */, 16 },
- /* 2136 */ { MAD_F(0x06b74971) /* 0.419747773 */, 16 },
- /* 2137 */ { MAD_F(0x06b85c34) /* 0.420009808 */, 16 },
- /* 2138 */ { MAD_F(0x06b96f03) /* 0.420271884 */, 16 },
- /* 2139 */ { MAD_F(0x06ba81dc) /* 0.420534001 */, 16 },
- /* 2140 */ { MAD_F(0x06bb94c1) /* 0.420796159 */, 16 },
- /* 2141 */ { MAD_F(0x06bca7b0) /* 0.421058358 */, 16 },
- /* 2142 */ { MAD_F(0x06bdbaaa) /* 0.421320597 */, 16 },
- /* 2143 */ { MAD_F(0x06becdb0) /* 0.421582878 */, 16 },
-
- /* 2144 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 16 },
- /* 2145 */ { MAD_F(0x06c0f3db) /* 0.422107561 */, 16 },
- /* 2146 */ { MAD_F(0x06c20702) /* 0.422369964 */, 16 },
- /* 2147 */ { MAD_F(0x06c31a33) /* 0.422632407 */, 16 },
- /* 2148 */ { MAD_F(0x06c42d6f) /* 0.422894891 */, 16 },
- /* 2149 */ { MAD_F(0x06c540b6) /* 0.423157416 */, 16 },
- /* 2150 */ { MAD_F(0x06c65408) /* 0.423419982 */, 16 },
- /* 2151 */ { MAD_F(0x06c76765) /* 0.423682588 */, 16 },
- /* 2152 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 16 },
- /* 2153 */ { MAD_F(0x06c98e3f) /* 0.424207923 */, 16 },
- /* 2154 */ { MAD_F(0x06caa1bd) /* 0.424470652 */, 16 },
- /* 2155 */ { MAD_F(0x06cbb545) /* 0.424733421 */, 16 },
- /* 2156 */ { MAD_F(0x06ccc8d9) /* 0.424996230 */, 16 },
- /* 2157 */ { MAD_F(0x06cddc77) /* 0.425259081 */, 16 },
- /* 2158 */ { MAD_F(0x06cef020) /* 0.425521972 */, 16 },
- /* 2159 */ { MAD_F(0x06d003d4) /* 0.425784903 */, 16 },
-
- /* 2160 */ { MAD_F(0x06d11794) /* 0.426047876 */, 16 },
- /* 2161 */ { MAD_F(0x06d22b5e) /* 0.426310889 */, 16 },
- /* 2162 */ { MAD_F(0x06d33f32) /* 0.426573942 */, 16 },
- /* 2163 */ { MAD_F(0x06d45312) /* 0.426837036 */, 16 },
- /* 2164 */ { MAD_F(0x06d566fd) /* 0.427100170 */, 16 },
- /* 2165 */ { MAD_F(0x06d67af2) /* 0.427363345 */, 16 },
- /* 2166 */ { MAD_F(0x06d78ef3) /* 0.427626561 */, 16 },
- /* 2167 */ { MAD_F(0x06d8a2fe) /* 0.427889817 */, 16 },
- /* 2168 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 16 },
- /* 2169 */ { MAD_F(0x06dacb35) /* 0.428416451 */, 16 },
- /* 2170 */ { MAD_F(0x06dbdf61) /* 0.428679828 */, 16 },
- /* 2171 */ { MAD_F(0x06dcf398) /* 0.428943246 */, 16 },
- /* 2172 */ { MAD_F(0x06de07d9) /* 0.429206704 */, 16 },
- /* 2173 */ { MAD_F(0x06df1c26) /* 0.429470203 */, 16 },
- /* 2174 */ { MAD_F(0x06e0307d) /* 0.429733743 */, 16 },
- /* 2175 */ { MAD_F(0x06e144df) /* 0.429997322 */, 16 },
-
- /* 2176 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 16 },
- /* 2177 */ { MAD_F(0x06e36dc4) /* 0.430524603 */, 16 },
- /* 2178 */ { MAD_F(0x06e48246) /* 0.430788304 */, 16 },
- /* 2179 */ { MAD_F(0x06e596d4) /* 0.431052045 */, 16 },
- /* 2180 */ { MAD_F(0x06e6ab6c) /* 0.431315826 */, 16 },
- /* 2181 */ { MAD_F(0x06e7c00f) /* 0.431579648 */, 16 },
- /* 2182 */ { MAD_F(0x06e8d4bd) /* 0.431843511 */, 16 },
- /* 2183 */ { MAD_F(0x06e9e976) /* 0.432107413 */, 16 },
- /* 2184 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 16 },
- /* 2185 */ { MAD_F(0x06ec1308) /* 0.432635339 */, 16 },
- /* 2186 */ { MAD_F(0x06ed27e2) /* 0.432899362 */, 16 },
- /* 2187 */ { MAD_F(0x06ee3cc6) /* 0.433163426 */, 16 },
- /* 2188 */ { MAD_F(0x06ef51b4) /* 0.433427530 */, 16 },
- /* 2189 */ { MAD_F(0x06f066ae) /* 0.433691674 */, 16 },
- /* 2190 */ { MAD_F(0x06f17bb3) /* 0.433955859 */, 16 },
- /* 2191 */ { MAD_F(0x06f290c2) /* 0.434220083 */, 16 },
-
- /* 2192 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 16 },
- /* 2193 */ { MAD_F(0x06f4bb01) /* 0.434748653 */, 16 },
- /* 2194 */ { MAD_F(0x06f5d030) /* 0.435012998 */, 16 },
- /* 2195 */ { MAD_F(0x06f6e56b) /* 0.435277383 */, 16 },
- /* 2196 */ { MAD_F(0x06f7fab0) /* 0.435541809 */, 16 },
- /* 2197 */ { MAD_F(0x06f91000) /* 0.435806274 */, 16 },
- /* 2198 */ { MAD_F(0x06fa255a) /* 0.436070780 */, 16 },
- /* 2199 */ { MAD_F(0x06fb3ac0) /* 0.436335326 */, 16 },
- /* 2200 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 16 },
- /* 2201 */ { MAD_F(0x06fd65ab) /* 0.436864538 */, 16 },
- /* 2202 */ { MAD_F(0x06fe7b31) /* 0.437129204 */, 16 },
- /* 2203 */ { MAD_F(0x06ff90c2) /* 0.437393910 */, 16 },
- /* 2204 */ { MAD_F(0x0700a65d) /* 0.437658657 */, 16 },
- /* 2205 */ { MAD_F(0x0701bc03) /* 0.437923443 */, 16 },
- /* 2206 */ { MAD_F(0x0702d1b4) /* 0.438188269 */, 16 },
- /* 2207 */ { MAD_F(0x0703e76f) /* 0.438453136 */, 16 },
-
- /* 2208 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 16 },
- /* 2209 */ { MAD_F(0x07061306) /* 0.438982988 */, 16 },
- /* 2210 */ { MAD_F(0x070728e2) /* 0.439247975 */, 16 },
- /* 2211 */ { MAD_F(0x07083ec9) /* 0.439513001 */, 16 },
- /* 2212 */ { MAD_F(0x070954ba) /* 0.439778067 */, 16 },
- /* 2213 */ { MAD_F(0x070a6ab6) /* 0.440043173 */, 16 },
- /* 2214 */ { MAD_F(0x070b80bc) /* 0.440308320 */, 16 },
- /* 2215 */ { MAD_F(0x070c96ce) /* 0.440573506 */, 16 },
- /* 2216 */ { MAD_F(0x070dacea) /* 0.440838732 */, 16 },
- /* 2217 */ { MAD_F(0x070ec310) /* 0.441103997 */, 16 },
- /* 2218 */ { MAD_F(0x070fd942) /* 0.441369303 */, 16 },
- /* 2219 */ { MAD_F(0x0710ef7e) /* 0.441634649 */, 16 },
- /* 2220 */ { MAD_F(0x071205c5) /* 0.441900034 */, 16 },
- /* 2221 */ { MAD_F(0x07131c17) /* 0.442165460 */, 16 },
- /* 2222 */ { MAD_F(0x07143273) /* 0.442430925 */, 16 },
- /* 2223 */ { MAD_F(0x071548da) /* 0.442696430 */, 16 },
-
- /* 2224 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 16 },
- /* 2225 */ { MAD_F(0x071775c8) /* 0.443227559 */, 16 },
- /* 2226 */ { MAD_F(0x07188c4f) /* 0.443493184 */, 16 },
- /* 2227 */ { MAD_F(0x0719a2e0) /* 0.443758848 */, 16 },
- /* 2228 */ { MAD_F(0x071ab97d) /* 0.444024552 */, 16 },
- /* 2229 */ { MAD_F(0x071bd024) /* 0.444290296 */, 16 },
- /* 2230 */ { MAD_F(0x071ce6d6) /* 0.444556079 */, 16 },
- /* 2231 */ { MAD_F(0x071dfd92) /* 0.444821902 */, 16 },
- /* 2232 */ { MAD_F(0x071f1459) /* 0.445087765 */, 16 },
- /* 2233 */ { MAD_F(0x07202b2b) /* 0.445353668 */, 16 },
- /* 2234 */ { MAD_F(0x07214207) /* 0.445619610 */, 16 },
- /* 2235 */ { MAD_F(0x072258ee) /* 0.445885592 */, 16 },
- /* 2236 */ { MAD_F(0x07236fe0) /* 0.446151614 */, 16 },
- /* 2237 */ { MAD_F(0x072486dc) /* 0.446417675 */, 16 },
- /* 2238 */ { MAD_F(0x07259de3) /* 0.446683776 */, 16 },
- /* 2239 */ { MAD_F(0x0726b4f4) /* 0.446949917 */, 16 },
-
- /* 2240 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 16 },
- /* 2241 */ { MAD_F(0x0728e338) /* 0.447482317 */, 16 },
- /* 2242 */ { MAD_F(0x0729fa69) /* 0.447748576 */, 16 },
- /* 2243 */ { MAD_F(0x072b11a5) /* 0.448014875 */, 16 },
- /* 2244 */ { MAD_F(0x072c28ec) /* 0.448281214 */, 16 },
- /* 2245 */ { MAD_F(0x072d403d) /* 0.448547592 */, 16 },
- /* 2246 */ { MAD_F(0x072e5799) /* 0.448814010 */, 16 },
- /* 2247 */ { MAD_F(0x072f6f00) /* 0.449080467 */, 16 },
- /* 2248 */ { MAD_F(0x07308671) /* 0.449346964 */, 16 },
- /* 2249 */ { MAD_F(0x07319ded) /* 0.449613501 */, 16 },
- /* 2250 */ { MAD_F(0x0732b573) /* 0.449880076 */, 16 },
- /* 2251 */ { MAD_F(0x0733cd04) /* 0.450146692 */, 16 },
- /* 2252 */ { MAD_F(0x0734e4a0) /* 0.450413347 */, 16 },
- /* 2253 */ { MAD_F(0x0735fc46) /* 0.450680041 */, 16 },
- /* 2254 */ { MAD_F(0x073713f7) /* 0.450946775 */, 16 },
- /* 2255 */ { MAD_F(0x07382bb2) /* 0.451213548 */, 16 },
-
- /* 2256 */ { MAD_F(0x07394378) /* 0.451480360 */, 16 },
- /* 2257 */ { MAD_F(0x073a5b49) /* 0.451747213 */, 16 },
- /* 2258 */ { MAD_F(0x073b7324) /* 0.452014104 */, 16 },
- /* 2259 */ { MAD_F(0x073c8b0a) /* 0.452281035 */, 16 },
- /* 2260 */ { MAD_F(0x073da2fa) /* 0.452548005 */, 16 },
- /* 2261 */ { MAD_F(0x073ebaf5) /* 0.452815015 */, 16 },
- /* 2262 */ { MAD_F(0x073fd2fa) /* 0.453082064 */, 16 },
- /* 2263 */ { MAD_F(0x0740eb0a) /* 0.453349152 */, 16 },
- /* 2264 */ { MAD_F(0x07420325) /* 0.453616280 */, 16 },
- /* 2265 */ { MAD_F(0x07431b4a) /* 0.453883447 */, 16 },
- /* 2266 */ { MAD_F(0x0744337a) /* 0.454150653 */, 16 },
- /* 2267 */ { MAD_F(0x07454bb4) /* 0.454417899 */, 16 },
- /* 2268 */ { MAD_F(0x074663f8) /* 0.454685184 */, 16 },
- /* 2269 */ { MAD_F(0x07477c48) /* 0.454952508 */, 16 },
- /* 2270 */ { MAD_F(0x074894a2) /* 0.455219872 */, 16 },
- /* 2271 */ { MAD_F(0x0749ad06) /* 0.455487275 */, 16 },
-
- /* 2272 */ { MAD_F(0x074ac575) /* 0.455754717 */, 16 },
- /* 2273 */ { MAD_F(0x074bddee) /* 0.456022198 */, 16 },
- /* 2274 */ { MAD_F(0x074cf672) /* 0.456289719 */, 16 },
- /* 2275 */ { MAD_F(0x074e0f01) /* 0.456557278 */, 16 },
- /* 2276 */ { MAD_F(0x074f279a) /* 0.456824877 */, 16 },
- /* 2277 */ { MAD_F(0x0750403e) /* 0.457092516 */, 16 },
- /* 2278 */ { MAD_F(0x075158ec) /* 0.457360193 */, 16 },
- /* 2279 */ { MAD_F(0x075271a4) /* 0.457627909 */, 16 },
- /* 2280 */ { MAD_F(0x07538a67) /* 0.457895665 */, 16 },
- /* 2281 */ { MAD_F(0x0754a335) /* 0.458163460 */, 16 },
- /* 2282 */ { MAD_F(0x0755bc0d) /* 0.458431294 */, 16 },
- /* 2283 */ { MAD_F(0x0756d4f0) /* 0.458699167 */, 16 },
- /* 2284 */ { MAD_F(0x0757eddd) /* 0.458967079 */, 16 },
- /* 2285 */ { MAD_F(0x075906d5) /* 0.459235030 */, 16 },
- /* 2286 */ { MAD_F(0x075a1fd7) /* 0.459503021 */, 16 },
- /* 2287 */ { MAD_F(0x075b38e3) /* 0.459771050 */, 16 },
-
- /* 2288 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 16 },
- /* 2289 */ { MAD_F(0x075d6b1c) /* 0.460307226 */, 16 },
- /* 2290 */ { MAD_F(0x075e8448) /* 0.460575373 */, 16 },
- /* 2291 */ { MAD_F(0x075f9d7f) /* 0.460843559 */, 16 },
- /* 2292 */ { MAD_F(0x0760b6c0) /* 0.461111783 */, 16 },
- /* 2293 */ { MAD_F(0x0761d00b) /* 0.461380047 */, 16 },
- /* 2294 */ { MAD_F(0x0762e961) /* 0.461648350 */, 16 },
- /* 2295 */ { MAD_F(0x076402c1) /* 0.461916691 */, 16 },
- /* 2296 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 16 },
- /* 2297 */ { MAD_F(0x076635a2) /* 0.462453492 */, 16 },
- /* 2298 */ { MAD_F(0x07674f22) /* 0.462721950 */, 16 },
- /* 2299 */ { MAD_F(0x076868ac) /* 0.462990448 */, 16 },
- /* 2300 */ { MAD_F(0x07698240) /* 0.463258984 */, 16 },
- /* 2301 */ { MAD_F(0x076a9be0) /* 0.463527560 */, 16 },
- /* 2302 */ { MAD_F(0x076bb589) /* 0.463796174 */, 16 },
- /* 2303 */ { MAD_F(0x076ccf3d) /* 0.464064827 */, 16 },
-
- /* 2304 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 16 },
- /* 2305 */ { MAD_F(0x076f02c5) /* 0.464602250 */, 16 },
- /* 2306 */ { MAD_F(0x07701c98) /* 0.464871020 */, 16 },
- /* 2307 */ { MAD_F(0x07713676) /* 0.465139829 */, 16 },
- /* 2308 */ { MAD_F(0x0772505e) /* 0.465408676 */, 16 },
- /* 2309 */ { MAD_F(0x07736a51) /* 0.465677563 */, 16 },
- /* 2310 */ { MAD_F(0x0774844e) /* 0.465946488 */, 16 },
- /* 2311 */ { MAD_F(0x07759e55) /* 0.466215452 */, 16 },
- /* 2312 */ { MAD_F(0x0776b867) /* 0.466484455 */, 16 },
- /* 2313 */ { MAD_F(0x0777d283) /* 0.466753496 */, 16 },
- /* 2314 */ { MAD_F(0x0778ecaa) /* 0.467022577 */, 16 },
- /* 2315 */ { MAD_F(0x077a06db) /* 0.467291696 */, 16 },
- /* 2316 */ { MAD_F(0x077b2117) /* 0.467560854 */, 16 },
- /* 2317 */ { MAD_F(0x077c3b5d) /* 0.467830050 */, 16 },
- /* 2318 */ { MAD_F(0x077d55ad) /* 0.468099285 */, 16 },
- /* 2319 */ { MAD_F(0x077e7008) /* 0.468368560 */, 16 },
-
- /* 2320 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 16 },
- /* 2321 */ { MAD_F(0x0780a4dc) /* 0.468907224 */, 16 },
- /* 2322 */ { MAD_F(0x0781bf56) /* 0.469176614 */, 16 },
- /* 2323 */ { MAD_F(0x0782d9da) /* 0.469446043 */, 16 },
- /* 2324 */ { MAD_F(0x0783f469) /* 0.469715510 */, 16 },
- /* 2325 */ { MAD_F(0x07850f02) /* 0.469985016 */, 16 },
- /* 2326 */ { MAD_F(0x078629a5) /* 0.470254561 */, 16 },
- /* 2327 */ { MAD_F(0x07874453) /* 0.470524145 */, 16 },
- /* 2328 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 16 },
- /* 2329 */ { MAD_F(0x078979ce) /* 0.471063427 */, 16 },
- /* 2330 */ { MAD_F(0x078a949a) /* 0.471333126 */, 16 },
- /* 2331 */ { MAD_F(0x078baf72) /* 0.471602864 */, 16 },
- /* 2332 */ { MAD_F(0x078cca53) /* 0.471872641 */, 16 },
- /* 2333 */ { MAD_F(0x078de53f) /* 0.472142456 */, 16 },
- /* 2334 */ { MAD_F(0x078f0035) /* 0.472412309 */, 16 },
- /* 2335 */ { MAD_F(0x07901b36) /* 0.472682201 */, 16 },
-
- /* 2336 */ { MAD_F(0x07913641) /* 0.472952132 */, 16 },
- /* 2337 */ { MAD_F(0x07925156) /* 0.473222101 */, 16 },
- /* 2338 */ { MAD_F(0x07936c76) /* 0.473492108 */, 16 },
- /* 2339 */ { MAD_F(0x079487a0) /* 0.473762155 */, 16 },
- /* 2340 */ { MAD_F(0x0795a2d4) /* 0.474032239 */, 16 },
- /* 2341 */ { MAD_F(0x0796be13) /* 0.474302362 */, 16 },
- /* 2342 */ { MAD_F(0x0797d95c) /* 0.474572524 */, 16 },
- /* 2343 */ { MAD_F(0x0798f4af) /* 0.474842724 */, 16 },
- /* 2344 */ { MAD_F(0x079a100c) /* 0.475112962 */, 16 },
- /* 2345 */ { MAD_F(0x079b2b74) /* 0.475383239 */, 16 },
- /* 2346 */ { MAD_F(0x079c46e7) /* 0.475653554 */, 16 },
- /* 2347 */ { MAD_F(0x079d6263) /* 0.475923908 */, 16 },
- /* 2348 */ { MAD_F(0x079e7dea) /* 0.476194300 */, 16 },
- /* 2349 */ { MAD_F(0x079f997b) /* 0.476464731 */, 16 },
- /* 2350 */ { MAD_F(0x07a0b516) /* 0.476735200 */, 16 },
- /* 2351 */ { MAD_F(0x07a1d0bc) /* 0.477005707 */, 16 },
-
- /* 2352 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 16 },
- /* 2353 */ { MAD_F(0x07a40827) /* 0.477546836 */, 16 },
- /* 2354 */ { MAD_F(0x07a523eb) /* 0.477817459 */, 16 },
- /* 2355 */ { MAD_F(0x07a63fba) /* 0.478088119 */, 16 },
- /* 2356 */ { MAD_F(0x07a75b93) /* 0.478358818 */, 16 },
- /* 2357 */ { MAD_F(0x07a87777) /* 0.478629555 */, 16 },
- /* 2358 */ { MAD_F(0x07a99364) /* 0.478900331 */, 16 },
- /* 2359 */ { MAD_F(0x07aaaf5c) /* 0.479171145 */, 16 },
- /* 2360 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 16 },
- /* 2361 */ { MAD_F(0x07ace76b) /* 0.479712887 */, 16 },
- /* 2362 */ { MAD_F(0x07ae0382) /* 0.479983816 */, 16 },
- /* 2363 */ { MAD_F(0x07af1fa3) /* 0.480254782 */, 16 },
- /* 2364 */ { MAD_F(0x07b03bcf) /* 0.480525787 */, 16 },
- /* 2365 */ { MAD_F(0x07b15804) /* 0.480796831 */, 16 },
- /* 2366 */ { MAD_F(0x07b27444) /* 0.481067912 */, 16 },
- /* 2367 */ { MAD_F(0x07b3908e) /* 0.481339032 */, 16 },
-
- /* 2368 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 16 },
- /* 2369 */ { MAD_F(0x07b5c941) /* 0.481881385 */, 16 },
- /* 2370 */ { MAD_F(0x07b6e5aa) /* 0.482152620 */, 16 },
- /* 2371 */ { MAD_F(0x07b8021d) /* 0.482423892 */, 16 },
- /* 2372 */ { MAD_F(0x07b91e9b) /* 0.482695202 */, 16 },
- /* 2373 */ { MAD_F(0x07ba3b22) /* 0.482966551 */, 16 },
- /* 2374 */ { MAD_F(0x07bb57b4) /* 0.483237938 */, 16 },
- /* 2375 */ { MAD_F(0x07bc7450) /* 0.483509362 */, 16 },
- /* 2376 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 16 },
- /* 2377 */ { MAD_F(0x07beada7) /* 0.484052326 */, 16 },
- /* 2378 */ { MAD_F(0x07bfca61) /* 0.484323865 */, 16 },
- /* 2379 */ { MAD_F(0x07c0e726) /* 0.484595443 */, 16 },
- /* 2380 */ { MAD_F(0x07c203f5) /* 0.484867058 */, 16 },
- /* 2381 */ { MAD_F(0x07c320cf) /* 0.485138711 */, 16 },
- /* 2382 */ { MAD_F(0x07c43db2) /* 0.485410402 */, 16 },
- /* 2383 */ { MAD_F(0x07c55aa0) /* 0.485682131 */, 16 },
-
- /* 2384 */ { MAD_F(0x07c67798) /* 0.485953899 */, 16 },
- /* 2385 */ { MAD_F(0x07c7949a) /* 0.486225704 */, 16 },
- /* 2386 */ { MAD_F(0x07c8b1a7) /* 0.486497547 */, 16 },
- /* 2387 */ { MAD_F(0x07c9cebd) /* 0.486769429 */, 16 },
- /* 2388 */ { MAD_F(0x07caebde) /* 0.487041348 */, 16 },
- /* 2389 */ { MAD_F(0x07cc0909) /* 0.487313305 */, 16 },
- /* 2390 */ { MAD_F(0x07cd263e) /* 0.487585300 */, 16 },
- /* 2391 */ { MAD_F(0x07ce437d) /* 0.487857333 */, 16 },
- /* 2392 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 16 },
- /* 2393 */ { MAD_F(0x07d07e1b) /* 0.488401513 */, 16 },
- /* 2394 */ { MAD_F(0x07d19b79) /* 0.488673660 */, 16 },
- /* 2395 */ { MAD_F(0x07d2b8e1) /* 0.488945845 */, 16 },
- /* 2396 */ { MAD_F(0x07d3d653) /* 0.489218067 */, 16 },
- /* 2397 */ { MAD_F(0x07d4f3cf) /* 0.489490328 */, 16 },
- /* 2398 */ { MAD_F(0x07d61156) /* 0.489762626 */, 16 },
- /* 2399 */ { MAD_F(0x07d72ee6) /* 0.490034962 */, 16 },
-
- /* 2400 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 16 },
- /* 2401 */ { MAD_F(0x07d96a26) /* 0.490579748 */, 16 },
- /* 2402 */ { MAD_F(0x07da87d5) /* 0.490852198 */, 16 },
- /* 2403 */ { MAD_F(0x07dba58f) /* 0.491124686 */, 16 },
- /* 2404 */ { MAD_F(0x07dcc352) /* 0.491397211 */, 16 },
- /* 2405 */ { MAD_F(0x07dde120) /* 0.491669774 */, 16 },
- /* 2406 */ { MAD_F(0x07defef7) /* 0.491942375 */, 16 },
- /* 2407 */ { MAD_F(0x07e01cd9) /* 0.492215014 */, 16 },
- /* 2408 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 16 },
- /* 2409 */ { MAD_F(0x07e258bc) /* 0.492760404 */, 16 },
- /* 2410 */ { MAD_F(0x07e376bc) /* 0.493033156 */, 16 },
- /* 2411 */ { MAD_F(0x07e494c6) /* 0.493305946 */, 16 },
- /* 2412 */ { MAD_F(0x07e5b2db) /* 0.493578773 */, 16 },
- /* 2413 */ { MAD_F(0x07e6d0f9) /* 0.493851638 */, 16 },
- /* 2414 */ { MAD_F(0x07e7ef22) /* 0.494124541 */, 16 },
- /* 2415 */ { MAD_F(0x07e90d55) /* 0.494397481 */, 16 },
-
- /* 2416 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 16 },
- /* 2417 */ { MAD_F(0x07eb49d9) /* 0.494943475 */, 16 },
- /* 2418 */ { MAD_F(0x07ec682a) /* 0.495216529 */, 16 },
- /* 2419 */ { MAD_F(0x07ed8686) /* 0.495489620 */, 16 },
- /* 2420 */ { MAD_F(0x07eea4eb) /* 0.495762748 */, 16 },
- /* 2421 */ { MAD_F(0x07efc35b) /* 0.496035915 */, 16 },
- /* 2422 */ { MAD_F(0x07f0e1d4) /* 0.496309119 */, 16 },
- /* 2423 */ { MAD_F(0x07f20058) /* 0.496582360 */, 16 },
- /* 2424 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 16 },
- /* 2425 */ { MAD_F(0x07f43d7e) /* 0.497128956 */, 16 },
- /* 2426 */ { MAD_F(0x07f55c20) /* 0.497402310 */, 16 },
- /* 2427 */ { MAD_F(0x07f67acc) /* 0.497675702 */, 16 },
- /* 2428 */ { MAD_F(0x07f79982) /* 0.497949132 */, 16 },
- /* 2429 */ { MAD_F(0x07f8b842) /* 0.498222598 */, 16 },
- /* 2430 */ { MAD_F(0x07f9d70c) /* 0.498496103 */, 16 },
- /* 2431 */ { MAD_F(0x07faf5e1) /* 0.498769645 */, 16 },
-
- /* 2432 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 16 },
- /* 2433 */ { MAD_F(0x07fd33a8) /* 0.499316841 */, 16 },
- /* 2434 */ { MAD_F(0x07fe529a) /* 0.499590496 */, 16 },
- /* 2435 */ { MAD_F(0x07ff7197) /* 0.499864188 */, 16 },
- /* 2436 */ { MAD_F(0x0400484f) /* 0.250068959 */, 17 },
- /* 2437 */ { MAD_F(0x0400d7d7) /* 0.250205842 */, 17 },
- /* 2438 */ { MAD_F(0x04016764) /* 0.250342744 */, 17 },
- /* 2439 */ { MAD_F(0x0401f6f7) /* 0.250479665 */, 17 },
- /* 2440 */ { MAD_F(0x0402868e) /* 0.250616605 */, 17 },
- /* 2441 */ { MAD_F(0x0403162b) /* 0.250753563 */, 17 },
- /* 2442 */ { MAD_F(0x0403a5cc) /* 0.250890540 */, 17 },
- /* 2443 */ { MAD_F(0x04043573) /* 0.251027536 */, 17 },
- /* 2444 */ { MAD_F(0x0404c51e) /* 0.251164550 */, 17 },
- /* 2445 */ { MAD_F(0x040554cf) /* 0.251301583 */, 17 },
- /* 2446 */ { MAD_F(0x0405e484) /* 0.251438635 */, 17 },
- /* 2447 */ { MAD_F(0x0406743f) /* 0.251575706 */, 17 },
-
- /* 2448 */ { MAD_F(0x040703ff) /* 0.251712795 */, 17 },
- /* 2449 */ { MAD_F(0x040793c3) /* 0.251849903 */, 17 },
- /* 2450 */ { MAD_F(0x0408238d) /* 0.251987029 */, 17 },
- /* 2451 */ { MAD_F(0x0408b35b) /* 0.252124174 */, 17 },
- /* 2452 */ { MAD_F(0x0409432f) /* 0.252261338 */, 17 },
- /* 2453 */ { MAD_F(0x0409d308) /* 0.252398520 */, 17 },
- /* 2454 */ { MAD_F(0x040a62e5) /* 0.252535721 */, 17 },
- /* 2455 */ { MAD_F(0x040af2c8) /* 0.252672941 */, 17 },
- /* 2456 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 17 },
- /* 2457 */ { MAD_F(0x040c129c) /* 0.252947436 */, 17 },
- /* 2458 */ { MAD_F(0x040ca28e) /* 0.253084712 */, 17 },
- /* 2459 */ { MAD_F(0x040d3284) /* 0.253222006 */, 17 },
- /* 2460 */ { MAD_F(0x040dc280) /* 0.253359319 */, 17 },
- /* 2461 */ { MAD_F(0x040e5281) /* 0.253496651 */, 17 },
- /* 2462 */ { MAD_F(0x040ee286) /* 0.253634001 */, 17 },
- /* 2463 */ { MAD_F(0x040f7291) /* 0.253771369 */, 17 },
-
- /* 2464 */ { MAD_F(0x041002a1) /* 0.253908756 */, 17 },
- /* 2465 */ { MAD_F(0x041092b5) /* 0.254046162 */, 17 },
- /* 2466 */ { MAD_F(0x041122cf) /* 0.254183587 */, 17 },
- /* 2467 */ { MAD_F(0x0411b2ed) /* 0.254321030 */, 17 },
- /* 2468 */ { MAD_F(0x04124311) /* 0.254458491 */, 17 },
- /* 2469 */ { MAD_F(0x0412d339) /* 0.254595971 */, 17 },
- /* 2470 */ { MAD_F(0x04136367) /* 0.254733470 */, 17 },
- /* 2471 */ { MAD_F(0x0413f399) /* 0.254870987 */, 17 },
- /* 2472 */ { MAD_F(0x041483d1) /* 0.255008523 */, 17 },
- /* 2473 */ { MAD_F(0x0415140d) /* 0.255146077 */, 17 },
- /* 2474 */ { MAD_F(0x0415a44f) /* 0.255283650 */, 17 },
- /* 2475 */ { MAD_F(0x04163495) /* 0.255421241 */, 17 },
- /* 2476 */ { MAD_F(0x0416c4e1) /* 0.255558851 */, 17 },
- /* 2477 */ { MAD_F(0x04175531) /* 0.255696480 */, 17 },
- /* 2478 */ { MAD_F(0x0417e586) /* 0.255834127 */, 17 },
- /* 2479 */ { MAD_F(0x041875e1) /* 0.255971792 */, 17 },
-
- /* 2480 */ { MAD_F(0x04190640) /* 0.256109476 */, 17 },
- /* 2481 */ { MAD_F(0x041996a4) /* 0.256247179 */, 17 },
- /* 2482 */ { MAD_F(0x041a270d) /* 0.256384900 */, 17 },
- /* 2483 */ { MAD_F(0x041ab77b) /* 0.256522639 */, 17 },
- /* 2484 */ { MAD_F(0x041b47ef) /* 0.256660397 */, 17 },
- /* 2485 */ { MAD_F(0x041bd867) /* 0.256798174 */, 17 },
- /* 2486 */ { MAD_F(0x041c68e4) /* 0.256935969 */, 17 },
- /* 2487 */ { MAD_F(0x041cf966) /* 0.257073782 */, 17 },
- /* 2488 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 17 },
- /* 2489 */ { MAD_F(0x041e1a79) /* 0.257349465 */, 17 },
- /* 2490 */ { MAD_F(0x041eab0a) /* 0.257487334 */, 17 },
- /* 2491 */ { MAD_F(0x041f3b9f) /* 0.257625221 */, 17 },
- /* 2492 */ { MAD_F(0x041fcc3a) /* 0.257763127 */, 17 },
- /* 2493 */ { MAD_F(0x04205cda) /* 0.257901051 */, 17 },
- /* 2494 */ { MAD_F(0x0420ed7f) /* 0.258038994 */, 17 },
- /* 2495 */ { MAD_F(0x04217e28) /* 0.258176955 */, 17 },
-
- /* 2496 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 17 },
- /* 2497 */ { MAD_F(0x04229f8a) /* 0.258452932 */, 17 },
- /* 2498 */ { MAD_F(0x04233043) /* 0.258590948 */, 17 },
- /* 2499 */ { MAD_F(0x0423c100) /* 0.258728983 */, 17 },
- /* 2500 */ { MAD_F(0x042451c3) /* 0.258867036 */, 17 },
- /* 2501 */ { MAD_F(0x0424e28a) /* 0.259005108 */, 17 },
- /* 2502 */ { MAD_F(0x04257356) /* 0.259143198 */, 17 },
- /* 2503 */ { MAD_F(0x04260428) /* 0.259281307 */, 17 },
- /* 2504 */ { MAD_F(0x042694fe) /* 0.259419433 */, 17 },
- /* 2505 */ { MAD_F(0x042725d9) /* 0.259557579 */, 17 },
- /* 2506 */ { MAD_F(0x0427b6b9) /* 0.259695742 */, 17 },
- /* 2507 */ { MAD_F(0x0428479e) /* 0.259833924 */, 17 },
- /* 2508 */ { MAD_F(0x0428d888) /* 0.259972124 */, 17 },
- /* 2509 */ { MAD_F(0x04296976) /* 0.260110343 */, 17 },
- /* 2510 */ { MAD_F(0x0429fa6a) /* 0.260248580 */, 17 },
- /* 2511 */ { MAD_F(0x042a8b63) /* 0.260386836 */, 17 },
-
- /* 2512 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 17 },
- /* 2513 */ { MAD_F(0x042bad63) /* 0.260663402 */, 17 },
- /* 2514 */ { MAD_F(0x042c3e6a) /* 0.260801712 */, 17 },
- /* 2515 */ { MAD_F(0x042ccf77) /* 0.260940041 */, 17 },
- /* 2516 */ { MAD_F(0x042d6088) /* 0.261078388 */, 17 },
- /* 2517 */ { MAD_F(0x042df19e) /* 0.261216754 */, 17 },
- /* 2518 */ { MAD_F(0x042e82b9) /* 0.261355137 */, 17 },
- /* 2519 */ { MAD_F(0x042f13d9) /* 0.261493540 */, 17 },
- /* 2520 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 17 },
- /* 2521 */ { MAD_F(0x04303628) /* 0.261770399 */, 17 },
- /* 2522 */ { MAD_F(0x0430c757) /* 0.261908856 */, 17 },
- /* 2523 */ { MAD_F(0x0431588b) /* 0.262047331 */, 17 },
- /* 2524 */ { MAD_F(0x0431e9c3) /* 0.262185825 */, 17 },
- /* 2525 */ { MAD_F(0x04327b01) /* 0.262324337 */, 17 },
- /* 2526 */ { MAD_F(0x04330c43) /* 0.262462867 */, 17 },
- /* 2527 */ { MAD_F(0x04339d8a) /* 0.262601416 */, 17 },
-
- /* 2528 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 17 },
- /* 2529 */ { MAD_F(0x0434c028) /* 0.262878568 */, 17 },
- /* 2530 */ { MAD_F(0x0435517e) /* 0.263017171 */, 17 },
- /* 2531 */ { MAD_F(0x0435e2d9) /* 0.263155792 */, 17 },
- /* 2532 */ { MAD_F(0x04367439) /* 0.263294432 */, 17 },
- /* 2533 */ { MAD_F(0x0437059e) /* 0.263433090 */, 17 },
- /* 2534 */ { MAD_F(0x04379707) /* 0.263571767 */, 17 },
- /* 2535 */ { MAD_F(0x04382876) /* 0.263710461 */, 17 },
- /* 2536 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 17 },
- /* 2537 */ { MAD_F(0x04394b61) /* 0.263987905 */, 17 },
- /* 2538 */ { MAD_F(0x0439dcdf) /* 0.264126655 */, 17 },
- /* 2539 */ { MAD_F(0x043a6e61) /* 0.264265422 */, 17 },
- /* 2540 */ { MAD_F(0x043affe8) /* 0.264404208 */, 17 },
- /* 2541 */ { MAD_F(0x043b9174) /* 0.264543012 */, 17 },
- /* 2542 */ { MAD_F(0x043c2305) /* 0.264681834 */, 17 },
- /* 2543 */ { MAD_F(0x043cb49a) /* 0.264820674 */, 17 },
-
- /* 2544 */ { MAD_F(0x043d4635) /* 0.264959533 */, 17 },
- /* 2545 */ { MAD_F(0x043dd7d4) /* 0.265098410 */, 17 },
- /* 2546 */ { MAD_F(0x043e6979) /* 0.265237305 */, 17 },
- /* 2547 */ { MAD_F(0x043efb22) /* 0.265376218 */, 17 },
- /* 2548 */ { MAD_F(0x043f8cd0) /* 0.265515149 */, 17 },
- /* 2549 */ { MAD_F(0x04401e83) /* 0.265654099 */, 17 },
- /* 2550 */ { MAD_F(0x0440b03b) /* 0.265793066 */, 17 },
- /* 2551 */ { MAD_F(0x044141f7) /* 0.265932052 */, 17 },
- /* 2552 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 17 },
- /* 2553 */ { MAD_F(0x04426580) /* 0.266210078 */, 17 },
- /* 2554 */ { MAD_F(0x0442f74b) /* 0.266349119 */, 17 },
- /* 2555 */ { MAD_F(0x0443891b) /* 0.266488177 */, 17 },
- /* 2556 */ { MAD_F(0x04441af0) /* 0.266627254 */, 17 },
- /* 2557 */ { MAD_F(0x0444acca) /* 0.266766349 */, 17 },
- /* 2558 */ { MAD_F(0x04453ea9) /* 0.266905462 */, 17 },
- /* 2559 */ { MAD_F(0x0445d08d) /* 0.267044593 */, 17 },
-
- /* 2560 */ { MAD_F(0x04466275) /* 0.267183742 */, 17 },
- /* 2561 */ { MAD_F(0x0446f463) /* 0.267322909 */, 17 },
- /* 2562 */ { MAD_F(0x04478655) /* 0.267462094 */, 17 },
- /* 2563 */ { MAD_F(0x0448184c) /* 0.267601298 */, 17 },
- /* 2564 */ { MAD_F(0x0448aa48) /* 0.267740519 */, 17 },
- /* 2565 */ { MAD_F(0x04493c49) /* 0.267879759 */, 17 },
- /* 2566 */ { MAD_F(0x0449ce4f) /* 0.268019017 */, 17 },
- /* 2567 */ { MAD_F(0x044a6059) /* 0.268158293 */, 17 },
- /* 2568 */ { MAD_F(0x044af269) /* 0.268297587 */, 17 },
- /* 2569 */ { MAD_F(0x044b847d) /* 0.268436899 */, 17 },
- /* 2570 */ { MAD_F(0x044c1696) /* 0.268576229 */, 17 },
- /* 2571 */ { MAD_F(0x044ca8b4) /* 0.268715577 */, 17 },
- /* 2572 */ { MAD_F(0x044d3ad7) /* 0.268854943 */, 17 },
- /* 2573 */ { MAD_F(0x044dccff) /* 0.268994328 */, 17 },
- /* 2574 */ { MAD_F(0x044e5f2b) /* 0.269133730 */, 17 },
- /* 2575 */ { MAD_F(0x044ef15d) /* 0.269273150 */, 17 },
-
- /* 2576 */ { MAD_F(0x044f8393) /* 0.269412589 */, 17 },
- /* 2577 */ { MAD_F(0x045015ce) /* 0.269552045 */, 17 },
- /* 2578 */ { MAD_F(0x0450a80e) /* 0.269691520 */, 17 },
- /* 2579 */ { MAD_F(0x04513a53) /* 0.269831013 */, 17 },
- /* 2580 */ { MAD_F(0x0451cc9c) /* 0.269970523 */, 17 },
- /* 2581 */ { MAD_F(0x04525eeb) /* 0.270110052 */, 17 },
- /* 2582 */ { MAD_F(0x0452f13e) /* 0.270249599 */, 17 },
- /* 2583 */ { MAD_F(0x04538396) /* 0.270389163 */, 17 },
- /* 2584 */ { MAD_F(0x045415f3) /* 0.270528746 */, 17 },
- /* 2585 */ { MAD_F(0x0454a855) /* 0.270668347 */, 17 },
- /* 2586 */ { MAD_F(0x04553abb) /* 0.270807965 */, 17 },
- /* 2587 */ { MAD_F(0x0455cd27) /* 0.270947602 */, 17 },
- /* 2588 */ { MAD_F(0x04565f97) /* 0.271087257 */, 17 },
- /* 2589 */ { MAD_F(0x0456f20c) /* 0.271226930 */, 17 },
- /* 2590 */ { MAD_F(0x04578486) /* 0.271366620 */, 17 },
- /* 2591 */ { MAD_F(0x04581705) /* 0.271506329 */, 17 },
-
- /* 2592 */ { MAD_F(0x0458a989) /* 0.271646056 */, 17 },
- /* 2593 */ { MAD_F(0x04593c11) /* 0.271785800 */, 17 },
- /* 2594 */ { MAD_F(0x0459ce9e) /* 0.271925563 */, 17 },
- /* 2595 */ { MAD_F(0x045a6130) /* 0.272065343 */, 17 },
- /* 2596 */ { MAD_F(0x045af3c7) /* 0.272205142 */, 17 },
- /* 2597 */ { MAD_F(0x045b8663) /* 0.272344958 */, 17 },
- /* 2598 */ { MAD_F(0x045c1903) /* 0.272484793 */, 17 },
- /* 2599 */ { MAD_F(0x045caba9) /* 0.272624645 */, 17 },
- /* 2600 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 17 },
- /* 2601 */ { MAD_F(0x045dd102) /* 0.272904403 */, 17 },
- /* 2602 */ { MAD_F(0x045e63b6) /* 0.273044310 */, 17 },
- /* 2603 */ { MAD_F(0x045ef66e) /* 0.273184234 */, 17 },
- /* 2604 */ { MAD_F(0x045f892b) /* 0.273324176 */, 17 },
- /* 2605 */ { MAD_F(0x04601bee) /* 0.273464136 */, 17 },
- /* 2606 */ { MAD_F(0x0460aeb5) /* 0.273604113 */, 17 },
- /* 2607 */ { MAD_F(0x04614180) /* 0.273744109 */, 17 },
-
- /* 2608 */ { MAD_F(0x0461d451) /* 0.273884123 */, 17 },
- /* 2609 */ { MAD_F(0x04626727) /* 0.274024154 */, 17 },
- /* 2610 */ { MAD_F(0x0462fa01) /* 0.274164204 */, 17 },
- /* 2611 */ { MAD_F(0x04638ce0) /* 0.274304271 */, 17 },
- /* 2612 */ { MAD_F(0x04641fc4) /* 0.274444356 */, 17 },
- /* 2613 */ { MAD_F(0x0464b2ac) /* 0.274584459 */, 17 },
- /* 2614 */ { MAD_F(0x0465459a) /* 0.274724580 */, 17 },
- /* 2615 */ { MAD_F(0x0465d88c) /* 0.274864719 */, 17 },
- /* 2616 */ { MAD_F(0x04666b83) /* 0.275004875 */, 17 },
- /* 2617 */ { MAD_F(0x0466fe7f) /* 0.275145050 */, 17 },
- /* 2618 */ { MAD_F(0x0467917f) /* 0.275285242 */, 17 },
- /* 2619 */ { MAD_F(0x04682485) /* 0.275425452 */, 17 },
- /* 2620 */ { MAD_F(0x0468b78f) /* 0.275565681 */, 17 },
- /* 2621 */ { MAD_F(0x04694a9e) /* 0.275705926 */, 17 },
- /* 2622 */ { MAD_F(0x0469ddb2) /* 0.275846190 */, 17 },
- /* 2623 */ { MAD_F(0x046a70ca) /* 0.275986472 */, 17 },
-
- /* 2624 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 17 },
- /* 2625 */ { MAD_F(0x046b970a) /* 0.276267088 */, 17 },
- /* 2626 */ { MAD_F(0x046c2a31) /* 0.276407423 */, 17 },
- /* 2627 */ { MAD_F(0x046cbd5c) /* 0.276547776 */, 17 },
- /* 2628 */ { MAD_F(0x046d508d) /* 0.276688147 */, 17 },
- /* 2629 */ { MAD_F(0x046de3c2) /* 0.276828535 */, 17 },
- /* 2630 */ { MAD_F(0x046e76fc) /* 0.276968942 */, 17 },
- /* 2631 */ { MAD_F(0x046f0a3b) /* 0.277109366 */, 17 },
- /* 2632 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 17 },
- /* 2633 */ { MAD_F(0x047030c7) /* 0.277390267 */, 17 },
- /* 2634 */ { MAD_F(0x0470c414) /* 0.277530745 */, 17 },
- /* 2635 */ { MAD_F(0x04715766) /* 0.277671240 */, 17 },
- /* 2636 */ { MAD_F(0x0471eabc) /* 0.277811753 */, 17 },
- /* 2637 */ { MAD_F(0x04727e18) /* 0.277952284 */, 17 },
- /* 2638 */ { MAD_F(0x04731178) /* 0.278092832 */, 17 },
- /* 2639 */ { MAD_F(0x0473a4dd) /* 0.278233399 */, 17 },
-
- /* 2640 */ { MAD_F(0x04743847) /* 0.278373983 */, 17 },
- /* 2641 */ { MAD_F(0x0474cbb5) /* 0.278514584 */, 17 },
- /* 2642 */ { MAD_F(0x04755f29) /* 0.278655204 */, 17 },
- /* 2643 */ { MAD_F(0x0475f2a1) /* 0.278795841 */, 17 },
- /* 2644 */ { MAD_F(0x0476861d) /* 0.278936496 */, 17 },
- /* 2645 */ { MAD_F(0x0477199f) /* 0.279077169 */, 17 },
- /* 2646 */ { MAD_F(0x0477ad25) /* 0.279217860 */, 17 },
- /* 2647 */ { MAD_F(0x047840b0) /* 0.279358568 */, 17 },
- /* 2648 */ { MAD_F(0x0478d440) /* 0.279499294 */, 17 },
- /* 2649 */ { MAD_F(0x047967d5) /* 0.279640037 */, 17 },
- /* 2650 */ { MAD_F(0x0479fb6e) /* 0.279780799 */, 17 },
- /* 2651 */ { MAD_F(0x047a8f0c) /* 0.279921578 */, 17 },
- /* 2652 */ { MAD_F(0x047b22af) /* 0.280062375 */, 17 },
- /* 2653 */ { MAD_F(0x047bb657) /* 0.280203189 */, 17 },
- /* 2654 */ { MAD_F(0x047c4a03) /* 0.280344021 */, 17 },
- /* 2655 */ { MAD_F(0x047cddb4) /* 0.280484871 */, 17 },
-
- /* 2656 */ { MAD_F(0x047d716a) /* 0.280625739 */, 17 },
- /* 2657 */ { MAD_F(0x047e0524) /* 0.280766624 */, 17 },
- /* 2658 */ { MAD_F(0x047e98e4) /* 0.280907527 */, 17 },
- /* 2659 */ { MAD_F(0x047f2ca8) /* 0.281048447 */, 17 },
- /* 2660 */ { MAD_F(0x047fc071) /* 0.281189385 */, 17 },
- /* 2661 */ { MAD_F(0x0480543e) /* 0.281330341 */, 17 },
- /* 2662 */ { MAD_F(0x0480e811) /* 0.281471315 */, 17 },
- /* 2663 */ { MAD_F(0x04817be8) /* 0.281612306 */, 17 },
- /* 2664 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 17 },
- /* 2665 */ { MAD_F(0x0482a3a4) /* 0.281894341 */, 17 },
- /* 2666 */ { MAD_F(0x04833789) /* 0.282035386 */, 17 },
- /* 2667 */ { MAD_F(0x0483cb73) /* 0.282176447 */, 17 },
- /* 2668 */ { MAD_F(0x04845f62) /* 0.282317527 */, 17 },
- /* 2669 */ { MAD_F(0x0484f355) /* 0.282458624 */, 17 },
- /* 2670 */ { MAD_F(0x0485874d) /* 0.282599738 */, 17 },
- /* 2671 */ { MAD_F(0x04861b4a) /* 0.282740871 */, 17 },
-
- /* 2672 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 17 },
- /* 2673 */ { MAD_F(0x04874352) /* 0.283023188 */, 17 },
- /* 2674 */ { MAD_F(0x0487d75d) /* 0.283164373 */, 17 },
- /* 2675 */ { MAD_F(0x04886b6d) /* 0.283305576 */, 17 },
- /* 2676 */ { MAD_F(0x0488ff82) /* 0.283446796 */, 17 },
- /* 2677 */ { MAD_F(0x0489939b) /* 0.283588034 */, 17 },
- /* 2678 */ { MAD_F(0x048a27b9) /* 0.283729290 */, 17 },
- /* 2679 */ { MAD_F(0x048abbdc) /* 0.283870563 */, 17 },
- /* 2680 */ { MAD_F(0x048b5003) /* 0.284011853 */, 17 },
- /* 2681 */ { MAD_F(0x048be42f) /* 0.284153161 */, 17 },
- /* 2682 */ { MAD_F(0x048c7860) /* 0.284294487 */, 17 },
- /* 2683 */ { MAD_F(0x048d0c96) /* 0.284435831 */, 17 },
- /* 2684 */ { MAD_F(0x048da0d0) /* 0.284577192 */, 17 },
- /* 2685 */ { MAD_F(0x048e350f) /* 0.284718570 */, 17 },
- /* 2686 */ { MAD_F(0x048ec953) /* 0.284859966 */, 17 },
- /* 2687 */ { MAD_F(0x048f5d9b) /* 0.285001380 */, 17 },
-
- /* 2688 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 17 },
- /* 2689 */ { MAD_F(0x0490863a) /* 0.285284259 */, 17 },
- /* 2690 */ { MAD_F(0x04911a91) /* 0.285425726 */, 17 },
- /* 2691 */ { MAD_F(0x0491aeec) /* 0.285567209 */, 17 },
- /* 2692 */ { MAD_F(0x0492434c) /* 0.285708711 */, 17 },
- /* 2693 */ { MAD_F(0x0492d7b0) /* 0.285850229 */, 17 },
- /* 2694 */ { MAD_F(0x04936c1a) /* 0.285991766 */, 17 },
- /* 2695 */ { MAD_F(0x04940088) /* 0.286133319 */, 17 },
- /* 2696 */ { MAD_F(0x049494fb) /* 0.286274891 */, 17 },
- /* 2697 */ { MAD_F(0x04952972) /* 0.286416480 */, 17 },
- /* 2698 */ { MAD_F(0x0495bdee) /* 0.286558086 */, 17 },
- /* 2699 */ { MAD_F(0x0496526f) /* 0.286699710 */, 17 },
- /* 2700 */ { MAD_F(0x0496e6f5) /* 0.286841351 */, 17 },
- /* 2701 */ { MAD_F(0x04977b7f) /* 0.286983010 */, 17 },
- /* 2702 */ { MAD_F(0x0498100e) /* 0.287124686 */, 17 },
- /* 2703 */ { MAD_F(0x0498a4a1) /* 0.287266380 */, 17 },
-
- /* 2704 */ { MAD_F(0x0499393a) /* 0.287408091 */, 17 },
- /* 2705 */ { MAD_F(0x0499cdd7) /* 0.287549820 */, 17 },
- /* 2706 */ { MAD_F(0x049a6278) /* 0.287691566 */, 17 },
- /* 2707 */ { MAD_F(0x049af71f) /* 0.287833330 */, 17 },
- /* 2708 */ { MAD_F(0x049b8bca) /* 0.287975111 */, 17 },
- /* 2709 */ { MAD_F(0x049c207a) /* 0.288116909 */, 17 },
- /* 2710 */ { MAD_F(0x049cb52e) /* 0.288258725 */, 17 },
- /* 2711 */ { MAD_F(0x049d49e7) /* 0.288400559 */, 17 },
- /* 2712 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 17 },
- /* 2713 */ { MAD_F(0x049e7367) /* 0.288684278 */, 17 },
- /* 2714 */ { MAD_F(0x049f082f) /* 0.288826163 */, 17 },
- /* 2715 */ { MAD_F(0x049f9cfa) /* 0.288968067 */, 17 },
- /* 2716 */ { MAD_F(0x04a031cb) /* 0.289109987 */, 17 },
- /* 2717 */ { MAD_F(0x04a0c6a0) /* 0.289251925 */, 17 },
- /* 2718 */ { MAD_F(0x04a15b7a) /* 0.289393881 */, 17 },
- /* 2719 */ { MAD_F(0x04a1f059) /* 0.289535854 */, 17 },
-
- /* 2720 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 17 },
- /* 2721 */ { MAD_F(0x04a31a24) /* 0.289819851 */, 17 },
- /* 2722 */ { MAD_F(0x04a3af10) /* 0.289961876 */, 17 },
- /* 2723 */ { MAD_F(0x04a44401) /* 0.290103919 */, 17 },
- /* 2724 */ { MAD_F(0x04a4d8f7) /* 0.290245979 */, 17 },
- /* 2725 */ { MAD_F(0x04a56df2) /* 0.290388056 */, 17 },
- /* 2726 */ { MAD_F(0x04a602f1) /* 0.290530150 */, 17 },
- /* 2727 */ { MAD_F(0x04a697f5) /* 0.290672262 */, 17 },
- /* 2728 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 17 },
- /* 2729 */ { MAD_F(0x04a7c20b) /* 0.290956538 */, 17 },
- /* 2730 */ { MAD_F(0x04a8571d) /* 0.291098703 */, 17 },
- /* 2731 */ { MAD_F(0x04a8ec33) /* 0.291240884 */, 17 },
- /* 2732 */ { MAD_F(0x04a9814e) /* 0.291383083 */, 17 },
- /* 2733 */ { MAD_F(0x04aa166e) /* 0.291525299 */, 17 },
- /* 2734 */ { MAD_F(0x04aaab93) /* 0.291667532 */, 17 },
- /* 2735 */ { MAD_F(0x04ab40bc) /* 0.291809783 */, 17 },
-
- /* 2736 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 17 },
- /* 2737 */ { MAD_F(0x04ac6b1c) /* 0.292094337 */, 17 },
- /* 2738 */ { MAD_F(0x04ad0053) /* 0.292236640 */, 17 },
- /* 2739 */ { MAD_F(0x04ad958f) /* 0.292378960 */, 17 },
- /* 2740 */ { MAD_F(0x04ae2ad0) /* 0.292521297 */, 17 },
- /* 2741 */ { MAD_F(0x04aec015) /* 0.292663652 */, 17 },
- /* 2742 */ { MAD_F(0x04af555e) /* 0.292806024 */, 17 },
- /* 2743 */ { MAD_F(0x04afeaad) /* 0.292948414 */, 17 },
- /* 2744 */ { MAD_F(0x04b08000) /* 0.293090820 */, 17 },
- /* 2745 */ { MAD_F(0x04b11557) /* 0.293233244 */, 17 },
- /* 2746 */ { MAD_F(0x04b1aab4) /* 0.293375686 */, 17 },
- /* 2747 */ { MAD_F(0x04b24015) /* 0.293518144 */, 17 },
- /* 2748 */ { MAD_F(0x04b2d57a) /* 0.293660620 */, 17 },
- /* 2749 */ { MAD_F(0x04b36ae4) /* 0.293803113 */, 17 },
- /* 2750 */ { MAD_F(0x04b40053) /* 0.293945624 */, 17 },
- /* 2751 */ { MAD_F(0x04b495c7) /* 0.294088151 */, 17 },
-
- /* 2752 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 17 },
- /* 2753 */ { MAD_F(0x04b5c0bc) /* 0.294373259 */, 17 },
- /* 2754 */ { MAD_F(0x04b6563d) /* 0.294515838 */, 17 },
- /* 2755 */ { MAD_F(0x04b6ebc3) /* 0.294658435 */, 17 },
- /* 2756 */ { MAD_F(0x04b7814e) /* 0.294801049 */, 17 },
- /* 2757 */ { MAD_F(0x04b816dd) /* 0.294943680 */, 17 },
- /* 2758 */ { MAD_F(0x04b8ac71) /* 0.295086329 */, 17 },
- /* 2759 */ { MAD_F(0x04b9420a) /* 0.295228995 */, 17 },
- /* 2760 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 17 },
- /* 2761 */ { MAD_F(0x04ba6d49) /* 0.295514378 */, 17 },
- /* 2762 */ { MAD_F(0x04bb02ef) /* 0.295657095 */, 17 },
- /* 2763 */ { MAD_F(0x04bb989a) /* 0.295799830 */, 17 },
- /* 2764 */ { MAD_F(0x04bc2e4a) /* 0.295942582 */, 17 },
- /* 2765 */ { MAD_F(0x04bcc3fe) /* 0.296085351 */, 17 },
- /* 2766 */ { MAD_F(0x04bd59b7) /* 0.296228138 */, 17 },
- /* 2767 */ { MAD_F(0x04bdef74) /* 0.296370941 */, 17 },
-
- /* 2768 */ { MAD_F(0x04be8537) /* 0.296513762 */, 17 },
- /* 2769 */ { MAD_F(0x04bf1afd) /* 0.296656600 */, 17 },
- /* 2770 */ { MAD_F(0x04bfb0c9) /* 0.296799455 */, 17 },
- /* 2771 */ { MAD_F(0x04c04699) /* 0.296942327 */, 17 },
- /* 2772 */ { MAD_F(0x04c0dc6d) /* 0.297085217 */, 17 },
- /* 2773 */ { MAD_F(0x04c17247) /* 0.297228124 */, 17 },
- /* 2774 */ { MAD_F(0x04c20824) /* 0.297371048 */, 17 },
- /* 2775 */ { MAD_F(0x04c29e07) /* 0.297513989 */, 17 },
- /* 2776 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 17 },
- /* 2777 */ { MAD_F(0x04c3c9da) /* 0.297799922 */, 17 },
- /* 2778 */ { MAD_F(0x04c45fca) /* 0.297942915 */, 17 },
- /* 2779 */ { MAD_F(0x04c4f5bf) /* 0.298085925 */, 17 },
- /* 2780 */ { MAD_F(0x04c58bb8) /* 0.298228951 */, 17 },
- /* 2781 */ { MAD_F(0x04c621b6) /* 0.298371996 */, 17 },
- /* 2782 */ { MAD_F(0x04c6b7b9) /* 0.298515057 */, 17 },
- /* 2783 */ { MAD_F(0x04c74dc0) /* 0.298658135 */, 17 },
-
- /* 2784 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 17 },
- /* 2785 */ { MAD_F(0x04c879dd) /* 0.298944343 */, 17 },
- /* 2786 */ { MAD_F(0x04c90ff2) /* 0.299087473 */, 17 },
- /* 2787 */ { MAD_F(0x04c9a60c) /* 0.299230620 */, 17 },
- /* 2788 */ { MAD_F(0x04ca3c2a) /* 0.299373784 */, 17 },
- /* 2789 */ { MAD_F(0x04cad24d) /* 0.299516965 */, 17 },
- /* 2790 */ { MAD_F(0x04cb6874) /* 0.299660163 */, 17 },
- /* 2791 */ { MAD_F(0x04cbfea0) /* 0.299803378 */, 17 },
- /* 2792 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 17 },
- /* 2793 */ { MAD_F(0x04cd2b06) /* 0.300089860 */, 17 },
- /* 2794 */ { MAD_F(0x04cdc140) /* 0.300233127 */, 17 },
- /* 2795 */ { MAD_F(0x04ce577f) /* 0.300376411 */, 17 },
- /* 2796 */ { MAD_F(0x04ceedc2) /* 0.300519711 */, 17 },
- /* 2797 */ { MAD_F(0x04cf8409) /* 0.300663029 */, 17 },
- /* 2798 */ { MAD_F(0x04d01a55) /* 0.300806364 */, 17 },
- /* 2799 */ { MAD_F(0x04d0b0a6) /* 0.300949716 */, 17 },
-
- /* 2800 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 17 },
- /* 2801 */ { MAD_F(0x04d1dd55) /* 0.301236472 */, 17 },
- /* 2802 */ { MAD_F(0x04d273b4) /* 0.301379875 */, 17 },
- /* 2803 */ { MAD_F(0x04d30a17) /* 0.301523295 */, 17 },
- /* 2804 */ { MAD_F(0x04d3a07f) /* 0.301666733 */, 17 },
- /* 2805 */ { MAD_F(0x04d436eb) /* 0.301810187 */, 17 },
- /* 2806 */ { MAD_F(0x04d4cd5c) /* 0.301953659 */, 17 },
- /* 2807 */ { MAD_F(0x04d563d1) /* 0.302097147 */, 17 },
- /* 2808 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 17 },
- /* 2809 */ { MAD_F(0x04d690ca) /* 0.302384175 */, 17 },
- /* 2810 */ { MAD_F(0x04d7274d) /* 0.302527715 */, 17 },
- /* 2811 */ { MAD_F(0x04d7bdd5) /* 0.302671271 */, 17 },
- /* 2812 */ { MAD_F(0x04d85461) /* 0.302814845 */, 17 },
- /* 2813 */ { MAD_F(0x04d8eaf2) /* 0.302958436 */, 17 },
- /* 2814 */ { MAD_F(0x04d98187) /* 0.303102044 */, 17 },
- /* 2815 */ { MAD_F(0x04da1821) /* 0.303245668 */, 17 },
-
- /* 2816 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 17 },
- /* 2817 */ { MAD_F(0x04db4563) /* 0.303532969 */, 17 },
- /* 2818 */ { MAD_F(0x04dbdc0a) /* 0.303676645 */, 17 },
- /* 2819 */ { MAD_F(0x04dc72b7) /* 0.303820337 */, 17 },
- /* 2820 */ { MAD_F(0x04dd0967) /* 0.303964047 */, 17 },
- /* 2821 */ { MAD_F(0x04dda01d) /* 0.304107774 */, 17 },
- /* 2822 */ { MAD_F(0x04de36d7) /* 0.304251517 */, 17 },
- /* 2823 */ { MAD_F(0x04decd95) /* 0.304395278 */, 17 },
- /* 2824 */ { MAD_F(0x04df6458) /* 0.304539056 */, 17 },
- /* 2825 */ { MAD_F(0x04dffb20) /* 0.304682850 */, 17 },
- /* 2826 */ { MAD_F(0x04e091ec) /* 0.304826662 */, 17 },
- /* 2827 */ { MAD_F(0x04e128bc) /* 0.304970491 */, 17 },
- /* 2828 */ { MAD_F(0x04e1bf92) /* 0.305114336 */, 17 },
- /* 2829 */ { MAD_F(0x04e2566b) /* 0.305258199 */, 17 },
- /* 2830 */ { MAD_F(0x04e2ed4a) /* 0.305402078 */, 17 },
- /* 2831 */ { MAD_F(0x04e3842d) /* 0.305545974 */, 17 },
-
- /* 2832 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 17 },
- /* 2833 */ { MAD_F(0x04e4b200) /* 0.305833818 */, 17 },
- /* 2834 */ { MAD_F(0x04e548f1) /* 0.305977765 */, 17 },
- /* 2835 */ { MAD_F(0x04e5dfe6) /* 0.306121729 */, 17 },
- /* 2836 */ { MAD_F(0x04e676df) /* 0.306265710 */, 17 },
- /* 2837 */ { MAD_F(0x04e70dde) /* 0.306409708 */, 17 },
- /* 2838 */ { MAD_F(0x04e7a4e0) /* 0.306553723 */, 17 },
- /* 2839 */ { MAD_F(0x04e83be7) /* 0.306697755 */, 17 },
- /* 2840 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 17 },
- /* 2841 */ { MAD_F(0x04e96a04) /* 0.306985869 */, 17 },
- /* 2842 */ { MAD_F(0x04ea0118) /* 0.307129952 */, 17 },
- /* 2843 */ { MAD_F(0x04ea9832) /* 0.307274051 */, 17 },
- /* 2844 */ { MAD_F(0x04eb2f50) /* 0.307418168 */, 17 },
- /* 2845 */ { MAD_F(0x04ebc672) /* 0.307562301 */, 17 },
- /* 2846 */ { MAD_F(0x04ec5d99) /* 0.307706451 */, 17 },
- /* 2847 */ { MAD_F(0x04ecf4c5) /* 0.307850618 */, 17 },
-
- /* 2848 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 17 },
- /* 2849 */ { MAD_F(0x04ee2329) /* 0.308139003 */, 17 },
- /* 2850 */ { MAD_F(0x04eeba63) /* 0.308283220 */, 17 },
- /* 2851 */ { MAD_F(0x04ef51a0) /* 0.308427455 */, 17 },
- /* 2852 */ { MAD_F(0x04efe8e2) /* 0.308571706 */, 17 },
- /* 2853 */ { MAD_F(0x04f08029) /* 0.308715974 */, 17 },
- /* 2854 */ { MAD_F(0x04f11774) /* 0.308860260 */, 17 },
- /* 2855 */ { MAD_F(0x04f1aec4) /* 0.309004561 */, 17 },
- /* 2856 */ { MAD_F(0x04f24618) /* 0.309148880 */, 17 },
- /* 2857 */ { MAD_F(0x04f2dd71) /* 0.309293216 */, 17 },
- /* 2858 */ { MAD_F(0x04f374cf) /* 0.309437568 */, 17 },
- /* 2859 */ { MAD_F(0x04f40c30) /* 0.309581938 */, 17 },
- /* 2860 */ { MAD_F(0x04f4a397) /* 0.309726324 */, 17 },
- /* 2861 */ { MAD_F(0x04f53b02) /* 0.309870727 */, 17 },
- /* 2862 */ { MAD_F(0x04f5d271) /* 0.310015147 */, 17 },
- /* 2863 */ { MAD_F(0x04f669e5) /* 0.310159583 */, 17 },
-
- /* 2864 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 17 },
- /* 2865 */ { MAD_F(0x04f798da) /* 0.310448507 */, 17 },
- /* 2866 */ { MAD_F(0x04f8305c) /* 0.310592994 */, 17 },
- /* 2867 */ { MAD_F(0x04f8c7e2) /* 0.310737498 */, 17 },
- /* 2868 */ { MAD_F(0x04f95f6c) /* 0.310882018 */, 17 },
- /* 2869 */ { MAD_F(0x04f9f6fb) /* 0.311026556 */, 17 },
- /* 2870 */ { MAD_F(0x04fa8e8f) /* 0.311171110 */, 17 },
- /* 2871 */ { MAD_F(0x04fb2627) /* 0.311315681 */, 17 },
- /* 2872 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 17 },
- /* 2873 */ { MAD_F(0x04fc5564) /* 0.311604874 */, 17 },
- /* 2874 */ { MAD_F(0x04fced0a) /* 0.311749495 */, 17 },
- /* 2875 */ { MAD_F(0x04fd84b4) /* 0.311894133 */, 17 },
- /* 2876 */ { MAD_F(0x04fe1c62) /* 0.312038788 */, 17 },
- /* 2877 */ { MAD_F(0x04feb415) /* 0.312183460 */, 17 },
- /* 2878 */ { MAD_F(0x04ff4bcd) /* 0.312328148 */, 17 },
- /* 2879 */ { MAD_F(0x04ffe389) /* 0.312472854 */, 17 },
-
- /* 2880 */ { MAD_F(0x05007b49) /* 0.312617576 */, 17 },
- /* 2881 */ { MAD_F(0x0501130e) /* 0.312762314 */, 17 },
- /* 2882 */ { MAD_F(0x0501aad8) /* 0.312907070 */, 17 },
- /* 2883 */ { MAD_F(0x050242a6) /* 0.313051842 */, 17 },
- /* 2884 */ { MAD_F(0x0502da78) /* 0.313196631 */, 17 },
- /* 2885 */ { MAD_F(0x0503724f) /* 0.313341437 */, 17 },
- /* 2886 */ { MAD_F(0x05040a2b) /* 0.313486259 */, 17 },
- /* 2887 */ { MAD_F(0x0504a20b) /* 0.313631098 */, 17 },
- /* 2888 */ { MAD_F(0x050539ef) /* 0.313775954 */, 17 },
- /* 2889 */ { MAD_F(0x0505d1d8) /* 0.313920827 */, 17 },
- /* 2890 */ { MAD_F(0x050669c5) /* 0.314065716 */, 17 },
- /* 2891 */ { MAD_F(0x050701b7) /* 0.314210622 */, 17 },
- /* 2892 */ { MAD_F(0x050799ae) /* 0.314355545 */, 17 },
- /* 2893 */ { MAD_F(0x050831a9) /* 0.314500484 */, 17 },
- /* 2894 */ { MAD_F(0x0508c9a8) /* 0.314645440 */, 17 },
- /* 2895 */ { MAD_F(0x050961ac) /* 0.314790413 */, 17 },
-
- /* 2896 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 17 },
- /* 2897 */ { MAD_F(0x050a91c1) /* 0.315080409 */, 17 },
- /* 2898 */ { MAD_F(0x050b29d2) /* 0.315225432 */, 17 },
- /* 2899 */ { MAD_F(0x050bc1e8) /* 0.315370472 */, 17 },
- /* 2900 */ { MAD_F(0x050c5a02) /* 0.315515528 */, 17 },
- /* 2901 */ { MAD_F(0x050cf221) /* 0.315660601 */, 17 },
- /* 2902 */ { MAD_F(0x050d8a44) /* 0.315805690 */, 17 },
- /* 2903 */ { MAD_F(0x050e226c) /* 0.315950797 */, 17 },
- /* 2904 */ { MAD_F(0x050eba98) /* 0.316095920 */, 17 },
- /* 2905 */ { MAD_F(0x050f52c9) /* 0.316241059 */, 17 },
- /* 2906 */ { MAD_F(0x050feafe) /* 0.316386216 */, 17 },
- /* 2907 */ { MAD_F(0x05108337) /* 0.316531388 */, 17 },
- /* 2908 */ { MAD_F(0x05111b75) /* 0.316676578 */, 17 },
- /* 2909 */ { MAD_F(0x0511b3b8) /* 0.316821784 */, 17 },
- /* 2910 */ { MAD_F(0x05124bff) /* 0.316967007 */, 17 },
- /* 2911 */ { MAD_F(0x0512e44a) /* 0.317112247 */, 17 },
-
- /* 2912 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 17 },
- /* 2913 */ { MAD_F(0x051414ee) /* 0.317402775 */, 17 },
- /* 2914 */ { MAD_F(0x0514ad47) /* 0.317548065 */, 17 },
- /* 2915 */ { MAD_F(0x051545a5) /* 0.317693371 */, 17 },
- /* 2916 */ { MAD_F(0x0515de06) /* 0.317838693 */, 17 },
- /* 2917 */ { MAD_F(0x0516766d) /* 0.317984033 */, 17 },
- /* 2918 */ { MAD_F(0x05170ed7) /* 0.318129388 */, 17 },
- /* 2919 */ { MAD_F(0x0517a746) /* 0.318274761 */, 17 },
- /* 2920 */ { MAD_F(0x05183fba) /* 0.318420150 */, 17 },
- /* 2921 */ { MAD_F(0x0518d832) /* 0.318565555 */, 17 },
- /* 2922 */ { MAD_F(0x051970ae) /* 0.318710978 */, 17 },
- /* 2923 */ { MAD_F(0x051a092f) /* 0.318856416 */, 17 },
- /* 2924 */ { MAD_F(0x051aa1b5) /* 0.319001872 */, 17 },
- /* 2925 */ { MAD_F(0x051b3a3f) /* 0.319147344 */, 17 },
- /* 2926 */ { MAD_F(0x051bd2cd) /* 0.319292832 */, 17 },
- /* 2927 */ { MAD_F(0x051c6b60) /* 0.319438338 */, 17 },
-
- /* 2928 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 17 },
- /* 2929 */ { MAD_F(0x051d9c92) /* 0.319729398 */, 17 },
- /* 2930 */ { MAD_F(0x051e3532) /* 0.319874952 */, 17 },
- /* 2931 */ { MAD_F(0x051ecdd7) /* 0.320020524 */, 17 },
- /* 2932 */ { MAD_F(0x051f6680) /* 0.320166112 */, 17 },
- /* 2933 */ { MAD_F(0x051fff2d) /* 0.320311716 */, 17 },
- /* 2934 */ { MAD_F(0x052097df) /* 0.320457337 */, 17 },
- /* 2935 */ { MAD_F(0x05213095) /* 0.320602975 */, 17 },
- /* 2936 */ { MAD_F(0x0521c950) /* 0.320748629 */, 17 },
- /* 2937 */ { MAD_F(0x0522620f) /* 0.320894300 */, 17 },
- /* 2938 */ { MAD_F(0x0522fad3) /* 0.321039987 */, 17 },
- /* 2939 */ { MAD_F(0x0523939b) /* 0.321185691 */, 17 },
- /* 2940 */ { MAD_F(0x05242c68) /* 0.321331411 */, 17 },
- /* 2941 */ { MAD_F(0x0524c538) /* 0.321477148 */, 17 },
- /* 2942 */ { MAD_F(0x05255e0e) /* 0.321622901 */, 17 },
- /* 2943 */ { MAD_F(0x0525f6e8) /* 0.321768671 */, 17 },
-
- /* 2944 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 17 },
- /* 2945 */ { MAD_F(0x052728a9) /* 0.322060260 */, 17 },
- /* 2946 */ { MAD_F(0x0527c190) /* 0.322206079 */, 17 },
- /* 2947 */ { MAD_F(0x05285a7b) /* 0.322351915 */, 17 },
- /* 2948 */ { MAD_F(0x0528f36b) /* 0.322497768 */, 17 },
- /* 2949 */ { MAD_F(0x05298c5f) /* 0.322643636 */, 17 },
- /* 2950 */ { MAD_F(0x052a2558) /* 0.322789522 */, 17 },
- /* 2951 */ { MAD_F(0x052abe55) /* 0.322935424 */, 17 },
- /* 2952 */ { MAD_F(0x052b5757) /* 0.323081342 */, 17 },
- /* 2953 */ { MAD_F(0x052bf05d) /* 0.323227277 */, 17 },
- /* 2954 */ { MAD_F(0x052c8968) /* 0.323373228 */, 17 },
- /* 2955 */ { MAD_F(0x052d2277) /* 0.323519196 */, 17 },
- /* 2956 */ { MAD_F(0x052dbb8a) /* 0.323665180 */, 17 },
- /* 2957 */ { MAD_F(0x052e54a2) /* 0.323811180 */, 17 },
- /* 2958 */ { MAD_F(0x052eedbe) /* 0.323957197 */, 17 },
- /* 2959 */ { MAD_F(0x052f86de) /* 0.324103231 */, 17 },
-
- /* 2960 */ { MAD_F(0x05302003) /* 0.324249281 */, 17 },
- /* 2961 */ { MAD_F(0x0530b92d) /* 0.324395347 */, 17 },
- /* 2962 */ { MAD_F(0x0531525b) /* 0.324541430 */, 17 },
- /* 2963 */ { MAD_F(0x0531eb8d) /* 0.324687530 */, 17 },
- /* 2964 */ { MAD_F(0x053284c4) /* 0.324833646 */, 17 },
- /* 2965 */ { MAD_F(0x05331dff) /* 0.324979778 */, 17 },
- /* 2966 */ { MAD_F(0x0533b73e) /* 0.325125926 */, 17 },
- /* 2967 */ { MAD_F(0x05345082) /* 0.325272091 */, 17 },
- /* 2968 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 17 },
- /* 2969 */ { MAD_F(0x05358317) /* 0.325564471 */, 17 },
- /* 2970 */ { MAD_F(0x05361c68) /* 0.325710685 */, 17 },
- /* 2971 */ { MAD_F(0x0536b5be) /* 0.325856916 */, 17 },
- /* 2972 */ { MAD_F(0x05374f17) /* 0.326003163 */, 17 },
- /* 2973 */ { MAD_F(0x0537e876) /* 0.326149427 */, 17 },
- /* 2974 */ { MAD_F(0x053881d9) /* 0.326295707 */, 17 },
- /* 2975 */ { MAD_F(0x05391b40) /* 0.326442003 */, 17 },
-
- /* 2976 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 17 },
- /* 2977 */ { MAD_F(0x053a4e1b) /* 0.326734645 */, 17 },
- /* 2978 */ { MAD_F(0x053ae78f) /* 0.326880990 */, 17 },
- /* 2979 */ { MAD_F(0x053b8108) /* 0.327027352 */, 17 },
- /* 2980 */ { MAD_F(0x053c1a85) /* 0.327173730 */, 17 },
- /* 2981 */ { MAD_F(0x053cb407) /* 0.327320125 */, 17 },
- /* 2982 */ { MAD_F(0x053d4d8d) /* 0.327466536 */, 17 },
- /* 2983 */ { MAD_F(0x053de717) /* 0.327612963 */, 17 },
- /* 2984 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 17 },
- /* 2985 */ { MAD_F(0x053f1a39) /* 0.327905867 */, 17 },
- /* 2986 */ { MAD_F(0x053fb3d0) /* 0.328052344 */, 17 },
- /* 2987 */ { MAD_F(0x05404d6c) /* 0.328198837 */, 17 },
- /* 2988 */ { MAD_F(0x0540e70c) /* 0.328345346 */, 17 },
- /* 2989 */ { MAD_F(0x054180b1) /* 0.328491871 */, 17 },
- /* 2990 */ { MAD_F(0x05421a5a) /* 0.328638413 */, 17 },
- /* 2991 */ { MAD_F(0x0542b407) /* 0.328784971 */, 17 },
-
- /* 2992 */ { MAD_F(0x05434db9) /* 0.328931546 */, 17 },
- /* 2993 */ { MAD_F(0x0543e76f) /* 0.329078137 */, 17 },
- /* 2994 */ { MAD_F(0x0544812a) /* 0.329224744 */, 17 },
- /* 2995 */ { MAD_F(0x05451ae9) /* 0.329371367 */, 17 },
- /* 2996 */ { MAD_F(0x0545b4ac) /* 0.329518007 */, 17 },
- /* 2997 */ { MAD_F(0x05464e74) /* 0.329664663 */, 17 },
- /* 2998 */ { MAD_F(0x0546e840) /* 0.329811336 */, 17 },
- /* 2999 */ { MAD_F(0x05478211) /* 0.329958024 */, 17 },
- /* 3000 */ { MAD_F(0x05481be5) /* 0.330104730 */, 17 },
- /* 3001 */ { MAD_F(0x0548b5bf) /* 0.330251451 */, 17 },
- /* 3002 */ { MAD_F(0x05494f9c) /* 0.330398189 */, 17 },
- /* 3003 */ { MAD_F(0x0549e97e) /* 0.330544943 */, 17 },
- /* 3004 */ { MAD_F(0x054a8364) /* 0.330691713 */, 17 },
- /* 3005 */ { MAD_F(0x054b1d4f) /* 0.330838499 */, 17 },
- /* 3006 */ { MAD_F(0x054bb73e) /* 0.330985302 */, 17 },
- /* 3007 */ { MAD_F(0x054c5132) /* 0.331132121 */, 17 },
-
- /* 3008 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 17 },
- /* 3009 */ { MAD_F(0x054d8526) /* 0.331425808 */, 17 },
- /* 3010 */ { MAD_F(0x054e1f26) /* 0.331572676 */, 17 },
- /* 3011 */ { MAD_F(0x054eb92b) /* 0.331719560 */, 17 },
- /* 3012 */ { MAD_F(0x054f5334) /* 0.331866461 */, 17 },
- /* 3013 */ { MAD_F(0x054fed42) /* 0.332013377 */, 17 },
- /* 3014 */ { MAD_F(0x05508754) /* 0.332160310 */, 17 },
- /* 3015 */ { MAD_F(0x0551216b) /* 0.332307260 */, 17 },
- /* 3016 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 17 },
- /* 3017 */ { MAD_F(0x055255a4) /* 0.332601207 */, 17 },
- /* 3018 */ { MAD_F(0x0552efc8) /* 0.332748205 */, 17 },
- /* 3019 */ { MAD_F(0x055389f0) /* 0.332895219 */, 17 },
- /* 3020 */ { MAD_F(0x0554241c) /* 0.333042249 */, 17 },
- /* 3021 */ { MAD_F(0x0554be4c) /* 0.333189296 */, 17 },
- /* 3022 */ { MAD_F(0x05555881) /* 0.333336359 */, 17 },
- /* 3023 */ { MAD_F(0x0555f2ba) /* 0.333483438 */, 17 },
-
- /* 3024 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 17 },
- /* 3025 */ { MAD_F(0x0557273a) /* 0.333777645 */, 17 },
- /* 3026 */ { MAD_F(0x0557c180) /* 0.333924772 */, 17 },
- /* 3027 */ { MAD_F(0x05585bcb) /* 0.334071916 */, 17 },
- /* 3028 */ { MAD_F(0x0558f61a) /* 0.334219076 */, 17 },
- /* 3029 */ { MAD_F(0x0559906d) /* 0.334366253 */, 17 },
- /* 3030 */ { MAD_F(0x055a2ac5) /* 0.334513445 */, 17 },
- /* 3031 */ { MAD_F(0x055ac521) /* 0.334660654 */, 17 },
- /* 3032 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 17 },
- /* 3033 */ { MAD_F(0x055bf9e6) /* 0.334955120 */, 17 },
- /* 3034 */ { MAD_F(0x055c944f) /* 0.335102377 */, 17 },
- /* 3035 */ { MAD_F(0x055d2ebd) /* 0.335249651 */, 17 },
- /* 3036 */ { MAD_F(0x055dc92e) /* 0.335396941 */, 17 },
- /* 3037 */ { MAD_F(0x055e63a5) /* 0.335544246 */, 17 },
- /* 3038 */ { MAD_F(0x055efe1f) /* 0.335691568 */, 17 },
- /* 3039 */ { MAD_F(0x055f989e) /* 0.335838906 */, 17 },
-
- /* 3040 */ { MAD_F(0x05603321) /* 0.335986261 */, 17 },
- /* 3041 */ { MAD_F(0x0560cda8) /* 0.336133631 */, 17 },
- /* 3042 */ { MAD_F(0x05616834) /* 0.336281018 */, 17 },
- /* 3043 */ { MAD_F(0x056202c4) /* 0.336428421 */, 17 },
- /* 3044 */ { MAD_F(0x05629d59) /* 0.336575840 */, 17 },
- /* 3045 */ { MAD_F(0x056337f2) /* 0.336723275 */, 17 },
- /* 3046 */ { MAD_F(0x0563d28f) /* 0.336870726 */, 17 },
- /* 3047 */ { MAD_F(0x05646d30) /* 0.337018193 */, 17 },
- /* 3048 */ { MAD_F(0x056507d6) /* 0.337165677 */, 17 },
- /* 3049 */ { MAD_F(0x0565a280) /* 0.337313176 */, 17 },
- /* 3050 */ { MAD_F(0x05663d2f) /* 0.337460692 */, 17 },
- /* 3051 */ { MAD_F(0x0566d7e1) /* 0.337608224 */, 17 },
- /* 3052 */ { MAD_F(0x05677298) /* 0.337755772 */, 17 },
- /* 3053 */ { MAD_F(0x05680d54) /* 0.337903336 */, 17 },
- /* 3054 */ { MAD_F(0x0568a814) /* 0.338050916 */, 17 },
- /* 3055 */ { MAD_F(0x056942d8) /* 0.338198513 */, 17 },
-
- /* 3056 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 17 },
- /* 3057 */ { MAD_F(0x056a786d) /* 0.338493753 */, 17 },
- /* 3058 */ { MAD_F(0x056b133e) /* 0.338641398 */, 17 },
- /* 3059 */ { MAD_F(0x056bae13) /* 0.338789059 */, 17 },
- /* 3060 */ { MAD_F(0x056c48ed) /* 0.338936736 */, 17 },
- /* 3061 */ { MAD_F(0x056ce3cb) /* 0.339084429 */, 17 },
- /* 3062 */ { MAD_F(0x056d7ead) /* 0.339232138 */, 17 },
- /* 3063 */ { MAD_F(0x056e1994) /* 0.339379863 */, 17 },
- /* 3064 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 17 },
- /* 3065 */ { MAD_F(0x056f4f6e) /* 0.339675361 */, 17 },
- /* 3066 */ { MAD_F(0x056fea62) /* 0.339823134 */, 17 },
- /* 3067 */ { MAD_F(0x0570855a) /* 0.339970924 */, 17 },
- /* 3068 */ { MAD_F(0x05712056) /* 0.340118729 */, 17 },
- /* 3069 */ { MAD_F(0x0571bb56) /* 0.340266550 */, 17 },
- /* 3070 */ { MAD_F(0x0572565b) /* 0.340414388 */, 17 },
- /* 3071 */ { MAD_F(0x0572f164) /* 0.340562242 */, 17 },
-
- /* 3072 */ { MAD_F(0x05738c72) /* 0.340710111 */, 17 },
- /* 3073 */ { MAD_F(0x05742784) /* 0.340857997 */, 17 },
- /* 3074 */ { MAD_F(0x0574c29a) /* 0.341005899 */, 17 },
- /* 3075 */ { MAD_F(0x05755db4) /* 0.341153816 */, 17 },
- /* 3076 */ { MAD_F(0x0575f8d3) /* 0.341301750 */, 17 },
- /* 3077 */ { MAD_F(0x057693f6) /* 0.341449700 */, 17 },
- /* 3078 */ { MAD_F(0x05772f1d) /* 0.341597666 */, 17 },
- /* 3079 */ { MAD_F(0x0577ca49) /* 0.341745648 */, 17 },
- /* 3080 */ { MAD_F(0x05786578) /* 0.341893646 */, 17 },
- /* 3081 */ { MAD_F(0x057900ad) /* 0.342041659 */, 17 },
- /* 3082 */ { MAD_F(0x05799be5) /* 0.342189689 */, 17 },
- /* 3083 */ { MAD_F(0x057a3722) /* 0.342337735 */, 17 },
- /* 3084 */ { MAD_F(0x057ad263) /* 0.342485797 */, 17 },
- /* 3085 */ { MAD_F(0x057b6da8) /* 0.342633875 */, 17 },
- /* 3086 */ { MAD_F(0x057c08f2) /* 0.342781969 */, 17 },
- /* 3087 */ { MAD_F(0x057ca440) /* 0.342930079 */, 17 },
-
- /* 3088 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 17 },
- /* 3089 */ { MAD_F(0x057ddae9) /* 0.343226347 */, 17 },
- /* 3090 */ { MAD_F(0x057e7644) /* 0.343374505 */, 17 },
- /* 3091 */ { MAD_F(0x057f11a3) /* 0.343522679 */, 17 },
- /* 3092 */ { MAD_F(0x057fad06) /* 0.343670869 */, 17 },
- /* 3093 */ { MAD_F(0x0580486e) /* 0.343819075 */, 17 },
- /* 3094 */ { MAD_F(0x0580e3da) /* 0.343967296 */, 17 },
- /* 3095 */ { MAD_F(0x05817f4a) /* 0.344115534 */, 17 },
- /* 3096 */ { MAD_F(0x05821abf) /* 0.344263788 */, 17 },
- /* 3097 */ { MAD_F(0x0582b638) /* 0.344412058 */, 17 },
- /* 3098 */ { MAD_F(0x058351b5) /* 0.344560343 */, 17 },
- /* 3099 */ { MAD_F(0x0583ed36) /* 0.344708645 */, 17 },
- /* 3100 */ { MAD_F(0x058488bc) /* 0.344856963 */, 17 },
- /* 3101 */ { MAD_F(0x05852446) /* 0.345005296 */, 17 },
- /* 3102 */ { MAD_F(0x0585bfd4) /* 0.345153646 */, 17 },
- /* 3103 */ { MAD_F(0x05865b67) /* 0.345302011 */, 17 },
-
- /* 3104 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 17 },
- /* 3105 */ { MAD_F(0x05879298) /* 0.345598790 */, 17 },
- /* 3106 */ { MAD_F(0x05882e38) /* 0.345747203 */, 17 },
- /* 3107 */ { MAD_F(0x0588c9dc) /* 0.345895632 */, 17 },
- /* 3108 */ { MAD_F(0x05896583) /* 0.346044077 */, 17 },
- /* 3109 */ { MAD_F(0x058a0130) /* 0.346192538 */, 17 },
- /* 3110 */ { MAD_F(0x058a9ce0) /* 0.346341015 */, 17 },
- /* 3111 */ { MAD_F(0x058b3895) /* 0.346489508 */, 17 },
- /* 3112 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 17 },
- /* 3113 */ { MAD_F(0x058c700b) /* 0.346786542 */, 17 },
- /* 3114 */ { MAD_F(0x058d0bcd) /* 0.346935082 */, 17 },
- /* 3115 */ { MAD_F(0x058da793) /* 0.347083639 */, 17 },
- /* 3116 */ { MAD_F(0x058e435d) /* 0.347232211 */, 17 },
- /* 3117 */ { MAD_F(0x058edf2b) /* 0.347380799 */, 17 },
- /* 3118 */ { MAD_F(0x058f7afe) /* 0.347529403 */, 17 },
- /* 3119 */ { MAD_F(0x059016d5) /* 0.347678023 */, 17 },
-
- /* 3120 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 17 },
- /* 3121 */ { MAD_F(0x05914e8f) /* 0.347975311 */, 17 },
- /* 3122 */ { MAD_F(0x0591ea73) /* 0.348123979 */, 17 },
- /* 3123 */ { MAD_F(0x0592865b) /* 0.348272662 */, 17 },
- /* 3124 */ { MAD_F(0x05932247) /* 0.348421362 */, 17 },
- /* 3125 */ { MAD_F(0x0593be37) /* 0.348570077 */, 17 },
- /* 3126 */ { MAD_F(0x05945a2c) /* 0.348718808 */, 17 },
- /* 3127 */ { MAD_F(0x0594f625) /* 0.348867555 */, 17 },
- /* 3128 */ { MAD_F(0x05959222) /* 0.349016318 */, 17 },
- /* 3129 */ { MAD_F(0x05962e24) /* 0.349165097 */, 17 },
- /* 3130 */ { MAD_F(0x0596ca2a) /* 0.349313892 */, 17 },
- /* 3131 */ { MAD_F(0x05976634) /* 0.349462702 */, 17 },
- /* 3132 */ { MAD_F(0x05980242) /* 0.349611528 */, 17 },
- /* 3133 */ { MAD_F(0x05989e54) /* 0.349760370 */, 17 },
- /* 3134 */ { MAD_F(0x05993a6b) /* 0.349909228 */, 17 },
- /* 3135 */ { MAD_F(0x0599d686) /* 0.350058102 */, 17 },
-
- /* 3136 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 17 },
- /* 3137 */ { MAD_F(0x059b0ec9) /* 0.350355897 */, 17 },
- /* 3138 */ { MAD_F(0x059baaf1) /* 0.350504818 */, 17 },
- /* 3139 */ { MAD_F(0x059c471d) /* 0.350653756 */, 17 },
- /* 3140 */ { MAD_F(0x059ce34d) /* 0.350802708 */, 17 },
- /* 3141 */ { MAD_F(0x059d7f81) /* 0.350951677 */, 17 },
- /* 3142 */ { MAD_F(0x059e1bba) /* 0.351100662 */, 17 },
- /* 3143 */ { MAD_F(0x059eb7f7) /* 0.351249662 */, 17 },
- /* 3144 */ { MAD_F(0x059f5438) /* 0.351398678 */, 17 },
- /* 3145 */ { MAD_F(0x059ff07e) /* 0.351547710 */, 17 },
- /* 3146 */ { MAD_F(0x05a08cc7) /* 0.351696758 */, 17 },
- /* 3147 */ { MAD_F(0x05a12915) /* 0.351845821 */, 17 },
- /* 3148 */ { MAD_F(0x05a1c567) /* 0.351994901 */, 17 },
- /* 3149 */ { MAD_F(0x05a261be) /* 0.352143996 */, 17 },
- /* 3150 */ { MAD_F(0x05a2fe18) /* 0.352293107 */, 17 },
- /* 3151 */ { MAD_F(0x05a39a77) /* 0.352442233 */, 17 },
-
- /* 3152 */ { MAD_F(0x05a436da) /* 0.352591376 */, 17 },
- /* 3153 */ { MAD_F(0x05a4d342) /* 0.352740534 */, 17 },
- /* 3154 */ { MAD_F(0x05a56fad) /* 0.352889708 */, 17 },
- /* 3155 */ { MAD_F(0x05a60c1d) /* 0.353038898 */, 17 },
- /* 3156 */ { MAD_F(0x05a6a891) /* 0.353188103 */, 17 },
- /* 3157 */ { MAD_F(0x05a7450a) /* 0.353337325 */, 17 },
- /* 3158 */ { MAD_F(0x05a7e186) /* 0.353486562 */, 17 },
- /* 3159 */ { MAD_F(0x05a87e07) /* 0.353635814 */, 17 },
- /* 3160 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 17 },
- /* 3161 */ { MAD_F(0x05a9b715) /* 0.353934367 */, 17 },
- /* 3162 */ { MAD_F(0x05aa53a2) /* 0.354083667 */, 17 },
- /* 3163 */ { MAD_F(0x05aaf034) /* 0.354232983 */, 17 },
- /* 3164 */ { MAD_F(0x05ab8cca) /* 0.354382314 */, 17 },
- /* 3165 */ { MAD_F(0x05ac2964) /* 0.354531662 */, 17 },
- /* 3166 */ { MAD_F(0x05acc602) /* 0.354681025 */, 17 },
- /* 3167 */ { MAD_F(0x05ad62a5) /* 0.354830403 */, 17 },
-
- /* 3168 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 17 },
- /* 3169 */ { MAD_F(0x05ae9bf7) /* 0.355129208 */, 17 },
- /* 3170 */ { MAD_F(0x05af38a6) /* 0.355278634 */, 17 },
- /* 3171 */ { MAD_F(0x05afd559) /* 0.355428075 */, 17 },
- /* 3172 */ { MAD_F(0x05b07211) /* 0.355577533 */, 17 },
- /* 3173 */ { MAD_F(0x05b10ecd) /* 0.355727006 */, 17 },
- /* 3174 */ { MAD_F(0x05b1ab8d) /* 0.355876494 */, 17 },
- /* 3175 */ { MAD_F(0x05b24851) /* 0.356025999 */, 17 },
- /* 3176 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 17 },
- /* 3177 */ { MAD_F(0x05b381e6) /* 0.356325054 */, 17 },
- /* 3178 */ { MAD_F(0x05b41eb7) /* 0.356474606 */, 17 },
- /* 3179 */ { MAD_F(0x05b4bb8c) /* 0.356624173 */, 17 },
- /* 3180 */ { MAD_F(0x05b55866) /* 0.356773756 */, 17 },
- /* 3181 */ { MAD_F(0x05b5f543) /* 0.356923354 */, 17 },
- /* 3182 */ { MAD_F(0x05b69225) /* 0.357072969 */, 17 },
- /* 3183 */ { MAD_F(0x05b72f0b) /* 0.357222598 */, 17 },
-
- /* 3184 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 17 },
- /* 3185 */ { MAD_F(0x05b868e3) /* 0.357521905 */, 17 },
- /* 3186 */ { MAD_F(0x05b905d6) /* 0.357671582 */, 17 },
- /* 3187 */ { MAD_F(0x05b9a2cd) /* 0.357821275 */, 17 },
- /* 3188 */ { MAD_F(0x05ba3fc8) /* 0.357970983 */, 17 },
- /* 3189 */ { MAD_F(0x05badcc7) /* 0.358120707 */, 17 },
- /* 3190 */ { MAD_F(0x05bb79ca) /* 0.358270446 */, 17 },
- /* 3191 */ { MAD_F(0x05bc16d2) /* 0.358420201 */, 17 },
- /* 3192 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 17 },
- /* 3193 */ { MAD_F(0x05bd50ee) /* 0.358719758 */, 17 },
- /* 3194 */ { MAD_F(0x05bdee02) /* 0.358869560 */, 17 },
- /* 3195 */ { MAD_F(0x05be8b1a) /* 0.359019378 */, 17 },
- /* 3196 */ { MAD_F(0x05bf2837) /* 0.359169211 */, 17 },
- /* 3197 */ { MAD_F(0x05bfc558) /* 0.359319060 */, 17 },
- /* 3198 */ { MAD_F(0x05c0627d) /* 0.359468925 */, 17 },
- /* 3199 */ { MAD_F(0x05c0ffa6) /* 0.359618805 */, 17 },
-
- /* 3200 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 17 },
- /* 3201 */ { MAD_F(0x05c23a05) /* 0.359918612 */, 17 },
- /* 3202 */ { MAD_F(0x05c2d73a) /* 0.360068540 */, 17 },
- /* 3203 */ { MAD_F(0x05c37474) /* 0.360218482 */, 17 },
- /* 3204 */ { MAD_F(0x05c411b2) /* 0.360368440 */, 17 },
- /* 3205 */ { MAD_F(0x05c4aef5) /* 0.360518414 */, 17 },
- /* 3206 */ { MAD_F(0x05c54c3b) /* 0.360668404 */, 17 },
- /* 3207 */ { MAD_F(0x05c5e986) /* 0.360818409 */, 17 },
- /* 3208 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 17 },
- /* 3209 */ { MAD_F(0x05c72428) /* 0.361118466 */, 17 },
- /* 3210 */ { MAD_F(0x05c7c17f) /* 0.361268517 */, 17 },
- /* 3211 */ { MAD_F(0x05c85eda) /* 0.361418585 */, 17 },
- /* 3212 */ { MAD_F(0x05c8fc3a) /* 0.361568668 */, 17 },
- /* 3213 */ { MAD_F(0x05c9999e) /* 0.361718766 */, 17 },
- /* 3214 */ { MAD_F(0x05ca3706) /* 0.361868881 */, 17 },
- /* 3215 */ { MAD_F(0x05cad472) /* 0.362019010 */, 17 },
-
- /* 3216 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 17 },
- /* 3217 */ { MAD_F(0x05cc0f57) /* 0.362319316 */, 17 },
- /* 3218 */ { MAD_F(0x05ccaccf) /* 0.362469493 */, 17 },
- /* 3219 */ { MAD_F(0x05cd4a4c) /* 0.362619685 */, 17 },
- /* 3220 */ { MAD_F(0x05cde7cd) /* 0.362769892 */, 17 },
- /* 3221 */ { MAD_F(0x05ce8552) /* 0.362920115 */, 17 },
- /* 3222 */ { MAD_F(0x05cf22dc) /* 0.363070354 */, 17 },
- /* 3223 */ { MAD_F(0x05cfc069) /* 0.363220608 */, 17 },
- /* 3224 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 17 },
- /* 3225 */ { MAD_F(0x05d0fb91) /* 0.363521163 */, 17 },
- /* 3226 */ { MAD_F(0x05d1992b) /* 0.363671464 */, 17 },
- /* 3227 */ { MAD_F(0x05d236c9) /* 0.363821780 */, 17 },
- /* 3228 */ { MAD_F(0x05d2d46c) /* 0.363972112 */, 17 },
- /* 3229 */ { MAD_F(0x05d37212) /* 0.364122459 */, 17 },
- /* 3230 */ { MAD_F(0x05d40fbd) /* 0.364272822 */, 17 },
- /* 3231 */ { MAD_F(0x05d4ad6c) /* 0.364423200 */, 17 },
-
- /* 3232 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 17 },
- /* 3233 */ { MAD_F(0x05d5e8d6) /* 0.364724004 */, 17 },
- /* 3234 */ { MAD_F(0x05d68691) /* 0.364874429 */, 17 },
- /* 3235 */ { MAD_F(0x05d72451) /* 0.365024869 */, 17 },
- /* 3236 */ { MAD_F(0x05d7c215) /* 0.365175325 */, 17 },
- /* 3237 */ { MAD_F(0x05d85fdc) /* 0.365325796 */, 17 },
- /* 3238 */ { MAD_F(0x05d8fda8) /* 0.365476283 */, 17 },
- /* 3239 */ { MAD_F(0x05d99b79) /* 0.365626786 */, 17 },
- /* 3240 */ { MAD_F(0x05da394d) /* 0.365777304 */, 17 },
- /* 3241 */ { MAD_F(0x05dad726) /* 0.365927837 */, 17 },
- /* 3242 */ { MAD_F(0x05db7502) /* 0.366078386 */, 17 },
- /* 3243 */ { MAD_F(0x05dc12e3) /* 0.366228950 */, 17 },
- /* 3244 */ { MAD_F(0x05dcb0c8) /* 0.366379530 */, 17 },
- /* 3245 */ { MAD_F(0x05dd4eb1) /* 0.366530125 */, 17 },
- /* 3246 */ { MAD_F(0x05ddec9e) /* 0.366680736 */, 17 },
- /* 3247 */ { MAD_F(0x05de8a90) /* 0.366831362 */, 17 },
-
- /* 3248 */ { MAD_F(0x05df2885) /* 0.366982004 */, 17 },
- /* 3249 */ { MAD_F(0x05dfc67f) /* 0.367132661 */, 17 },
- /* 3250 */ { MAD_F(0x05e0647d) /* 0.367283334 */, 17 },
- /* 3251 */ { MAD_F(0x05e1027f) /* 0.367434022 */, 17 },
- /* 3252 */ { MAD_F(0x05e1a085) /* 0.367584725 */, 17 },
- /* 3253 */ { MAD_F(0x05e23e8f) /* 0.367735444 */, 17 },
- /* 3254 */ { MAD_F(0x05e2dc9e) /* 0.367886179 */, 17 },
- /* 3255 */ { MAD_F(0x05e37ab0) /* 0.368036929 */, 17 },
- /* 3256 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 17 },
- /* 3257 */ { MAD_F(0x05e4b6e2) /* 0.368338475 */, 17 },
- /* 3258 */ { MAD_F(0x05e55501) /* 0.368489271 */, 17 },
- /* 3259 */ { MAD_F(0x05e5f324) /* 0.368640082 */, 17 },
- /* 3260 */ { MAD_F(0x05e6914c) /* 0.368790909 */, 17 },
- /* 3261 */ { MAD_F(0x05e72f77) /* 0.368941752 */, 17 },
- /* 3262 */ { MAD_F(0x05e7cda7) /* 0.369092610 */, 17 },
- /* 3263 */ { MAD_F(0x05e86bda) /* 0.369243483 */, 17 },
-
- /* 3264 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 17 },
- /* 3265 */ { MAD_F(0x05e9a84e) /* 0.369545276 */, 17 },
- /* 3266 */ { MAD_F(0x05ea468e) /* 0.369696195 */, 17 },
- /* 3267 */ { MAD_F(0x05eae4d3) /* 0.369847130 */, 17 },
- /* 3268 */ { MAD_F(0x05eb831b) /* 0.369998080 */, 17 },
- /* 3269 */ { MAD_F(0x05ec2168) /* 0.370149046 */, 17 },
- /* 3270 */ { MAD_F(0x05ecbfb8) /* 0.370300027 */, 17 },
- /* 3271 */ { MAD_F(0x05ed5e0d) /* 0.370451024 */, 17 },
- /* 3272 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 17 },
- /* 3273 */ { MAD_F(0x05ee9ac3) /* 0.370753063 */, 17 },
- /* 3274 */ { MAD_F(0x05ef3924) /* 0.370904105 */, 17 },
- /* 3275 */ { MAD_F(0x05efd78a) /* 0.371055163 */, 17 },
- /* 3276 */ { MAD_F(0x05f075f3) /* 0.371206237 */, 17 },
- /* 3277 */ { MAD_F(0x05f11461) /* 0.371357326 */, 17 },
- /* 3278 */ { MAD_F(0x05f1b2d3) /* 0.371508430 */, 17 },
- /* 3279 */ { MAD_F(0x05f25148) /* 0.371659549 */, 17 },
-
- /* 3280 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 17 },
- /* 3281 */ { MAD_F(0x05f38e40) /* 0.371961834 */, 17 },
- /* 3282 */ { MAD_F(0x05f42cc3) /* 0.372113000 */, 17 },
- /* 3283 */ { MAD_F(0x05f4cb49) /* 0.372264181 */, 17 },
- /* 3284 */ { MAD_F(0x05f569d3) /* 0.372415377 */, 17 },
- /* 3285 */ { MAD_F(0x05f60862) /* 0.372566589 */, 17 },
- /* 3286 */ { MAD_F(0x05f6a6f5) /* 0.372717816 */, 17 },
- /* 3287 */ { MAD_F(0x05f7458b) /* 0.372869058 */, 17 },
- /* 3288 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 17 },
- /* 3289 */ { MAD_F(0x05f882c5) /* 0.373171589 */, 17 },
- /* 3290 */ { MAD_F(0x05f92169) /* 0.373322877 */, 17 },
- /* 3291 */ { MAD_F(0x05f9c010) /* 0.373474181 */, 17 },
- /* 3292 */ { MAD_F(0x05fa5ebb) /* 0.373625500 */, 17 },
- /* 3293 */ { MAD_F(0x05fafd6b) /* 0.373776834 */, 17 },
- /* 3294 */ { MAD_F(0x05fb9c1e) /* 0.373928184 */, 17 },
- /* 3295 */ { MAD_F(0x05fc3ad6) /* 0.374079549 */, 17 },
-
- /* 3296 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 17 },
- /* 3297 */ { MAD_F(0x05fd7852) /* 0.374382325 */, 17 },
- /* 3298 */ { MAD_F(0x05fe1716) /* 0.374533735 */, 17 },
- /* 3299 */ { MAD_F(0x05feb5de) /* 0.374685162 */, 17 },
- /* 3300 */ { MAD_F(0x05ff54aa) /* 0.374836603 */, 17 },
- /* 3301 */ { MAD_F(0x05fff37b) /* 0.374988060 */, 17 },
- /* 3302 */ { MAD_F(0x0600924f) /* 0.375139532 */, 17 },
- /* 3303 */ { MAD_F(0x06013128) /* 0.375291019 */, 17 },
- /* 3304 */ { MAD_F(0x0601d004) /* 0.375442522 */, 17 },
- /* 3305 */ { MAD_F(0x06026ee5) /* 0.375594040 */, 17 },
- /* 3306 */ { MAD_F(0x06030dca) /* 0.375745573 */, 17 },
- /* 3307 */ { MAD_F(0x0603acb3) /* 0.375897122 */, 17 },
- /* 3308 */ { MAD_F(0x06044ba0) /* 0.376048685 */, 17 },
- /* 3309 */ { MAD_F(0x0604ea91) /* 0.376200265 */, 17 },
- /* 3310 */ { MAD_F(0x06058987) /* 0.376351859 */, 17 },
- /* 3311 */ { MAD_F(0x06062880) /* 0.376503468 */, 17 },
-
- /* 3312 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 17 },
- /* 3313 */ { MAD_F(0x0607667f) /* 0.376806733 */, 17 },
- /* 3314 */ { MAD_F(0x06080585) /* 0.376958389 */, 17 },
- /* 3315 */ { MAD_F(0x0608a48f) /* 0.377110059 */, 17 },
- /* 3316 */ { MAD_F(0x0609439c) /* 0.377261745 */, 17 },
- /* 3317 */ { MAD_F(0x0609e2ae) /* 0.377413446 */, 17 },
- /* 3318 */ { MAD_F(0x060a81c4) /* 0.377565163 */, 17 },
- /* 3319 */ { MAD_F(0x060b20df) /* 0.377716894 */, 17 },
- /* 3320 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 17 },
- /* 3321 */ { MAD_F(0x060c5f1f) /* 0.378020403 */, 17 },
- /* 3322 */ { MAD_F(0x060cfe46) /* 0.378172181 */, 17 },
- /* 3323 */ { MAD_F(0x060d9d70) /* 0.378323973 */, 17 },
- /* 3324 */ { MAD_F(0x060e3c9f) /* 0.378475781 */, 17 },
- /* 3325 */ { MAD_F(0x060edbd1) /* 0.378627604 */, 17 },
- /* 3326 */ { MAD_F(0x060f7b08) /* 0.378779442 */, 17 },
- /* 3327 */ { MAD_F(0x06101a43) /* 0.378931296 */, 17 },
-
- /* 3328 */ { MAD_F(0x0610b982) /* 0.379083164 */, 17 },
- /* 3329 */ { MAD_F(0x061158c5) /* 0.379235048 */, 17 },
- /* 3330 */ { MAD_F(0x0611f80c) /* 0.379386947 */, 17 },
- /* 3331 */ { MAD_F(0x06129757) /* 0.379538862 */, 17 },
- /* 3332 */ { MAD_F(0x061336a6) /* 0.379690791 */, 17 },
- /* 3333 */ { MAD_F(0x0613d5fa) /* 0.379842736 */, 17 },
- /* 3334 */ { MAD_F(0x06147551) /* 0.379994696 */, 17 },
- /* 3335 */ { MAD_F(0x061514ad) /* 0.380146671 */, 17 },
- /* 3336 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 17 },
- /* 3337 */ { MAD_F(0x06165370) /* 0.380450666 */, 17 },
- /* 3338 */ { MAD_F(0x0616f2d8) /* 0.380602687 */, 17 },
- /* 3339 */ { MAD_F(0x06179243) /* 0.380754723 */, 17 },
- /* 3340 */ { MAD_F(0x061831b3) /* 0.380906774 */, 17 },
- /* 3341 */ { MAD_F(0x0618d127) /* 0.381058840 */, 17 },
- /* 3342 */ { MAD_F(0x0619709f) /* 0.381210921 */, 17 },
- /* 3343 */ { MAD_F(0x061a101b) /* 0.381363018 */, 17 },
-
- /* 3344 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 17 },
- /* 3345 */ { MAD_F(0x061b4f20) /* 0.381667257 */, 17 },
- /* 3346 */ { MAD_F(0x061beea8) /* 0.381819399 */, 17 },
- /* 3347 */ { MAD_F(0x061c8e34) /* 0.381971556 */, 17 },
- /* 3348 */ { MAD_F(0x061d2dc5) /* 0.382123728 */, 17 },
- /* 3349 */ { MAD_F(0x061dcd59) /* 0.382275916 */, 17 },
- /* 3350 */ { MAD_F(0x061e6cf2) /* 0.382428118 */, 17 },
- /* 3351 */ { MAD_F(0x061f0c8f) /* 0.382580336 */, 17 },
- /* 3352 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 17 },
- /* 3353 */ { MAD_F(0x06204bd4) /* 0.382884817 */, 17 },
- /* 3354 */ { MAD_F(0x0620eb7d) /* 0.383037080 */, 17 },
- /* 3355 */ { MAD_F(0x06218b2a) /* 0.383189358 */, 17 },
- /* 3356 */ { MAD_F(0x06222adb) /* 0.383341652 */, 17 },
- /* 3357 */ { MAD_F(0x0622ca90) /* 0.383493960 */, 17 },
- /* 3358 */ { MAD_F(0x06236a49) /* 0.383646284 */, 17 },
- /* 3359 */ { MAD_F(0x06240a06) /* 0.383798623 */, 17 },
-
- /* 3360 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 17 },
- /* 3361 */ { MAD_F(0x0625498d) /* 0.384103346 */, 17 },
- /* 3362 */ { MAD_F(0x0625e956) /* 0.384255730 */, 17 },
- /* 3363 */ { MAD_F(0x06268923) /* 0.384408129 */, 17 },
- /* 3364 */ { MAD_F(0x062728f5) /* 0.384560544 */, 17 },
- /* 3365 */ { MAD_F(0x0627c8ca) /* 0.384712973 */, 17 },
- /* 3366 */ { MAD_F(0x062868a4) /* 0.384865418 */, 17 },
- /* 3367 */ { MAD_F(0x06290881) /* 0.385017878 */, 17 },
- /* 3368 */ { MAD_F(0x0629a863) /* 0.385170352 */, 17 },
- /* 3369 */ { MAD_F(0x062a4849) /* 0.385322842 */, 17 },
- /* 3370 */ { MAD_F(0x062ae832) /* 0.385475347 */, 17 },
- /* 3371 */ { MAD_F(0x062b8820) /* 0.385627867 */, 17 },
- /* 3372 */ { MAD_F(0x062c2812) /* 0.385780402 */, 17 },
- /* 3373 */ { MAD_F(0x062cc808) /* 0.385932953 */, 17 },
- /* 3374 */ { MAD_F(0x062d6802) /* 0.386085518 */, 17 },
- /* 3375 */ { MAD_F(0x062e0800) /* 0.386238098 */, 17 },
-
- /* 3376 */ { MAD_F(0x062ea802) /* 0.386390694 */, 17 },
- /* 3377 */ { MAD_F(0x062f4808) /* 0.386543304 */, 17 },
- /* 3378 */ { MAD_F(0x062fe812) /* 0.386695930 */, 17 },
- /* 3379 */ { MAD_F(0x06308820) /* 0.386848570 */, 17 },
- /* 3380 */ { MAD_F(0x06312832) /* 0.387001226 */, 17 },
- /* 3381 */ { MAD_F(0x0631c849) /* 0.387153897 */, 17 },
- /* 3382 */ { MAD_F(0x06326863) /* 0.387306582 */, 17 },
- /* 3383 */ { MAD_F(0x06330881) /* 0.387459283 */, 17 },
- /* 3384 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 17 },
- /* 3385 */ { MAD_F(0x063448ca) /* 0.387764730 */, 17 },
- /* 3386 */ { MAD_F(0x0634e8f4) /* 0.387917476 */, 17 },
- /* 3387 */ { MAD_F(0x06358923) /* 0.388070237 */, 17 },
- /* 3388 */ { MAD_F(0x06362955) /* 0.388223013 */, 17 },
- /* 3389 */ { MAD_F(0x0636c98c) /* 0.388375804 */, 17 },
- /* 3390 */ { MAD_F(0x063769c6) /* 0.388528610 */, 17 },
- /* 3391 */ { MAD_F(0x06380a05) /* 0.388681431 */, 17 },
-
- /* 3392 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 17 },
- /* 3393 */ { MAD_F(0x06394a8e) /* 0.388987119 */, 17 },
- /* 3394 */ { MAD_F(0x0639ead9) /* 0.389139985 */, 17 },
- /* 3395 */ { MAD_F(0x063a8b28) /* 0.389292866 */, 17 },
- /* 3396 */ { MAD_F(0x063b2b7b) /* 0.389445762 */, 17 },
- /* 3397 */ { MAD_F(0x063bcbd1) /* 0.389598674 */, 17 },
- /* 3398 */ { MAD_F(0x063c6c2c) /* 0.389751600 */, 17 },
- /* 3399 */ { MAD_F(0x063d0c8b) /* 0.389904541 */, 17 },
- /* 3400 */ { MAD_F(0x063dacee) /* 0.390057497 */, 17 },
- /* 3401 */ { MAD_F(0x063e4d55) /* 0.390210468 */, 17 },
- /* 3402 */ { MAD_F(0x063eedc0) /* 0.390363455 */, 17 },
- /* 3403 */ { MAD_F(0x063f8e2f) /* 0.390516456 */, 17 },
- /* 3404 */ { MAD_F(0x06402ea2) /* 0.390669472 */, 17 },
- /* 3405 */ { MAD_F(0x0640cf19) /* 0.390822503 */, 17 },
- /* 3406 */ { MAD_F(0x06416f94) /* 0.390975549 */, 17 },
- /* 3407 */ { MAD_F(0x06421013) /* 0.391128611 */, 17 },
-
- /* 3408 */ { MAD_F(0x0642b096) /* 0.391281687 */, 17 },
- /* 3409 */ { MAD_F(0x0643511d) /* 0.391434778 */, 17 },
- /* 3410 */ { MAD_F(0x0643f1a8) /* 0.391587884 */, 17 },
- /* 3411 */ { MAD_F(0x06449237) /* 0.391741005 */, 17 },
- /* 3412 */ { MAD_F(0x064532ca) /* 0.391894141 */, 17 },
- /* 3413 */ { MAD_F(0x0645d361) /* 0.392047292 */, 17 },
- /* 3414 */ { MAD_F(0x064673fc) /* 0.392200458 */, 17 },
- /* 3415 */ { MAD_F(0x0647149c) /* 0.392353638 */, 17 },
- /* 3416 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 17 },
- /* 3417 */ { MAD_F(0x064855e6) /* 0.392660045 */, 17 },
- /* 3418 */ { MAD_F(0x0648f691) /* 0.392813271 */, 17 },
- /* 3419 */ { MAD_F(0x06499740) /* 0.392966511 */, 17 },
- /* 3420 */ { MAD_F(0x064a37f4) /* 0.393119767 */, 17 },
- /* 3421 */ { MAD_F(0x064ad8ab) /* 0.393273038 */, 17 },
- /* 3422 */ { MAD_F(0x064b7966) /* 0.393426323 */, 17 },
- /* 3423 */ { MAD_F(0x064c1a25) /* 0.393579623 */, 17 },
-
- /* 3424 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 17 },
- /* 3425 */ { MAD_F(0x064d5bb0) /* 0.393886269 */, 17 },
- /* 3426 */ { MAD_F(0x064dfc7b) /* 0.394039614 */, 17 },
- /* 3427 */ { MAD_F(0x064e9d4b) /* 0.394192974 */, 17 },
- /* 3428 */ { MAD_F(0x064f3e1e) /* 0.394346349 */, 17 },
- /* 3429 */ { MAD_F(0x064fdef5) /* 0.394499739 */, 17 },
- /* 3430 */ { MAD_F(0x06507fd0) /* 0.394653144 */, 17 },
- /* 3431 */ { MAD_F(0x065120b0) /* 0.394806564 */, 17 },
- /* 3432 */ { MAD_F(0x0651c193) /* 0.394959999 */, 17 },
- /* 3433 */ { MAD_F(0x0652627a) /* 0.395113448 */, 17 },
- /* 3434 */ { MAD_F(0x06530366) /* 0.395266913 */, 17 },
- /* 3435 */ { MAD_F(0x0653a455) /* 0.395420392 */, 17 },
- /* 3436 */ { MAD_F(0x06544548) /* 0.395573886 */, 17 },
- /* 3437 */ { MAD_F(0x0654e640) /* 0.395727395 */, 17 },
- /* 3438 */ { MAD_F(0x0655873b) /* 0.395880919 */, 17 },
- /* 3439 */ { MAD_F(0x0656283a) /* 0.396034458 */, 17 },
-
- /* 3440 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 17 },
- /* 3441 */ { MAD_F(0x06576a45) /* 0.396341581 */, 17 },
- /* 3442 */ { MAD_F(0x06580b50) /* 0.396495164 */, 17 },
- /* 3443 */ { MAD_F(0x0658ac5f) /* 0.396648763 */, 17 },
- /* 3444 */ { MAD_F(0x06594d73) /* 0.396802376 */, 17 },
- /* 3445 */ { MAD_F(0x0659ee8a) /* 0.396956004 */, 17 },
- /* 3446 */ { MAD_F(0x065a8fa5) /* 0.397109647 */, 17 },
- /* 3447 */ { MAD_F(0x065b30c4) /* 0.397263305 */, 17 },
- /* 3448 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 17 },
- /* 3449 */ { MAD_F(0x065c730f) /* 0.397570666 */, 17 },
- /* 3450 */ { MAD_F(0x065d143a) /* 0.397724368 */, 17 },
- /* 3451 */ { MAD_F(0x065db569) /* 0.397878085 */, 17 },
- /* 3452 */ { MAD_F(0x065e569c) /* 0.398031818 */, 17 },
- /* 3453 */ { MAD_F(0x065ef7d3) /* 0.398185565 */, 17 },
- /* 3454 */ { MAD_F(0x065f990e) /* 0.398339326 */, 17 },
- /* 3455 */ { MAD_F(0x06603a4e) /* 0.398493103 */, 17 },
-
- /* 3456 */ { MAD_F(0x0660db91) /* 0.398646895 */, 17 },
- /* 3457 */ { MAD_F(0x06617cd8) /* 0.398800701 */, 17 },
- /* 3458 */ { MAD_F(0x06621e23) /* 0.398954522 */, 17 },
- /* 3459 */ { MAD_F(0x0662bf72) /* 0.399108358 */, 17 },
- /* 3460 */ { MAD_F(0x066360c5) /* 0.399262209 */, 17 },
- /* 3461 */ { MAD_F(0x0664021c) /* 0.399416075 */, 17 },
- /* 3462 */ { MAD_F(0x0664a377) /* 0.399569955 */, 17 },
- /* 3463 */ { MAD_F(0x066544d6) /* 0.399723851 */, 17 },
- /* 3464 */ { MAD_F(0x0665e639) /* 0.399877761 */, 17 },
- /* 3465 */ { MAD_F(0x066687a0) /* 0.400031686 */, 17 },
- /* 3466 */ { MAD_F(0x0667290b) /* 0.400185625 */, 17 },
- /* 3467 */ { MAD_F(0x0667ca79) /* 0.400339580 */, 17 },
- /* 3468 */ { MAD_F(0x06686bec) /* 0.400493549 */, 17 },
- /* 3469 */ { MAD_F(0x06690d63) /* 0.400647534 */, 17 },
- /* 3470 */ { MAD_F(0x0669aede) /* 0.400801533 */, 17 },
- /* 3471 */ { MAD_F(0x066a505d) /* 0.400955546 */, 17 },
-
- /* 3472 */ { MAD_F(0x066af1df) /* 0.401109575 */, 17 },
- /* 3473 */ { MAD_F(0x066b9366) /* 0.401263618 */, 17 },
- /* 3474 */ { MAD_F(0x066c34f1) /* 0.401417676 */, 17 },
- /* 3475 */ { MAD_F(0x066cd67f) /* 0.401571749 */, 17 },
- /* 3476 */ { MAD_F(0x066d7812) /* 0.401725837 */, 17 },
- /* 3477 */ { MAD_F(0x066e19a9) /* 0.401879939 */, 17 },
- /* 3478 */ { MAD_F(0x066ebb43) /* 0.402034056 */, 17 },
- /* 3479 */ { MAD_F(0x066f5ce2) /* 0.402188188 */, 17 },
- /* 3480 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 17 },
- /* 3481 */ { MAD_F(0x0670a02a) /* 0.402496497 */, 17 },
- /* 3482 */ { MAD_F(0x067141d5) /* 0.402650673 */, 17 },
- /* 3483 */ { MAD_F(0x0671e383) /* 0.402804864 */, 17 },
- /* 3484 */ { MAD_F(0x06728535) /* 0.402959070 */, 17 },
- /* 3485 */ { MAD_F(0x067326ec) /* 0.403113291 */, 17 },
- /* 3486 */ { MAD_F(0x0673c8a6) /* 0.403267526 */, 17 },
- /* 3487 */ { MAD_F(0x06746a64) /* 0.403421776 */, 17 },
-
- /* 3488 */ { MAD_F(0x06750c26) /* 0.403576041 */, 17 },
- /* 3489 */ { MAD_F(0x0675adec) /* 0.403730320 */, 17 },
- /* 3490 */ { MAD_F(0x06764fb6) /* 0.403884615 */, 17 },
- /* 3491 */ { MAD_F(0x0676f184) /* 0.404038924 */, 17 },
- /* 3492 */ { MAD_F(0x06779356) /* 0.404193247 */, 17 },
- /* 3493 */ { MAD_F(0x0678352c) /* 0.404347586 */, 17 },
- /* 3494 */ { MAD_F(0x0678d706) /* 0.404501939 */, 17 },
- /* 3495 */ { MAD_F(0x067978e4) /* 0.404656307 */, 17 },
- /* 3496 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 17 },
- /* 3497 */ { MAD_F(0x067abcac) /* 0.404965087 */, 17 },
- /* 3498 */ { MAD_F(0x067b5e95) /* 0.405119499 */, 17 },
- /* 3499 */ { MAD_F(0x067c0083) /* 0.405273926 */, 17 },
- /* 3500 */ { MAD_F(0x067ca275) /* 0.405428368 */, 17 },
- /* 3501 */ { MAD_F(0x067d446a) /* 0.405582824 */, 17 },
- /* 3502 */ { MAD_F(0x067de664) /* 0.405737295 */, 17 },
- /* 3503 */ { MAD_F(0x067e8861) /* 0.405891781 */, 17 },
-
- /* 3504 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 17 },
- /* 3505 */ { MAD_F(0x067fcc68) /* 0.406200796 */, 17 },
- /* 3506 */ { MAD_F(0x06806e71) /* 0.406355326 */, 17 },
- /* 3507 */ { MAD_F(0x0681107e) /* 0.406509870 */, 17 },
- /* 3508 */ { MAD_F(0x0681b28f) /* 0.406664429 */, 17 },
- /* 3509 */ { MAD_F(0x068254a4) /* 0.406819003 */, 17 },
- /* 3510 */ { MAD_F(0x0682f6bd) /* 0.406973592 */, 17 },
- /* 3511 */ { MAD_F(0x068398da) /* 0.407128195 */, 17 },
- /* 3512 */ { MAD_F(0x06843afb) /* 0.407282813 */, 17 },
- /* 3513 */ { MAD_F(0x0684dd20) /* 0.407437445 */, 17 },
- /* 3514 */ { MAD_F(0x06857f49) /* 0.407592093 */, 17 },
- /* 3515 */ { MAD_F(0x06862176) /* 0.407746754 */, 17 },
- /* 3516 */ { MAD_F(0x0686c3a6) /* 0.407901431 */, 17 },
- /* 3517 */ { MAD_F(0x068765db) /* 0.408056122 */, 17 },
- /* 3518 */ { MAD_F(0x06880814) /* 0.408210828 */, 17 },
- /* 3519 */ { MAD_F(0x0688aa50) /* 0.408365549 */, 17 },
-
- /* 3520 */ { MAD_F(0x06894c90) /* 0.408520284 */, 17 },
- /* 3521 */ { MAD_F(0x0689eed5) /* 0.408675034 */, 17 },
- /* 3522 */ { MAD_F(0x068a911d) /* 0.408829798 */, 17 },
- /* 3523 */ { MAD_F(0x068b3369) /* 0.408984577 */, 17 },
- /* 3524 */ { MAD_F(0x068bd5b9) /* 0.409139371 */, 17 },
- /* 3525 */ { MAD_F(0x068c780e) /* 0.409294180 */, 17 },
- /* 3526 */ { MAD_F(0x068d1a66) /* 0.409449003 */, 17 },
- /* 3527 */ { MAD_F(0x068dbcc1) /* 0.409603840 */, 17 },
- /* 3528 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 17 },
- /* 3529 */ { MAD_F(0x068f0185) /* 0.409913560 */, 17 },
- /* 3530 */ { MAD_F(0x068fa3ed) /* 0.410068441 */, 17 },
- /* 3531 */ { MAD_F(0x06904658) /* 0.410223338 */, 17 },
- /* 3532 */ { MAD_F(0x0690e8c8) /* 0.410378249 */, 17 },
- /* 3533 */ { MAD_F(0x06918b3c) /* 0.410533174 */, 17 },
- /* 3534 */ { MAD_F(0x06922db3) /* 0.410688114 */, 17 },
- /* 3535 */ { MAD_F(0x0692d02e) /* 0.410843069 */, 17 },
-
- /* 3536 */ { MAD_F(0x069372ae) /* 0.410998038 */, 17 },
- /* 3537 */ { MAD_F(0x06941531) /* 0.411153022 */, 17 },
- /* 3538 */ { MAD_F(0x0694b7b8) /* 0.411308021 */, 17 },
- /* 3539 */ { MAD_F(0x06955a43) /* 0.411463034 */, 17 },
- /* 3540 */ { MAD_F(0x0695fcd2) /* 0.411618062 */, 17 },
- /* 3541 */ { MAD_F(0x06969f65) /* 0.411773104 */, 17 },
- /* 3542 */ { MAD_F(0x069741fb) /* 0.411928161 */, 17 },
- /* 3543 */ { MAD_F(0x0697e496) /* 0.412083232 */, 17 },
- /* 3544 */ { MAD_F(0x06988735) /* 0.412238319 */, 17 },
- /* 3545 */ { MAD_F(0x069929d7) /* 0.412393419 */, 17 },
- /* 3546 */ { MAD_F(0x0699cc7e) /* 0.412548535 */, 17 },
- /* 3547 */ { MAD_F(0x069a6f28) /* 0.412703664 */, 17 },
- /* 3548 */ { MAD_F(0x069b11d6) /* 0.412858809 */, 17 },
- /* 3549 */ { MAD_F(0x069bb489) /* 0.413013968 */, 17 },
- /* 3550 */ { MAD_F(0x069c573f) /* 0.413169142 */, 17 },
- /* 3551 */ { MAD_F(0x069cf9f9) /* 0.413324330 */, 17 },
-
- /* 3552 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 17 },
- /* 3553 */ { MAD_F(0x069e3f78) /* 0.413634750 */, 17 },
- /* 3554 */ { MAD_F(0x069ee23e) /* 0.413789982 */, 17 },
- /* 3555 */ { MAD_F(0x069f8508) /* 0.413945228 */, 17 },
- /* 3556 */ { MAD_F(0x06a027d5) /* 0.414100489 */, 17 },
- /* 3557 */ { MAD_F(0x06a0caa7) /* 0.414255765 */, 17 },
- /* 3558 */ { MAD_F(0x06a16d7c) /* 0.414411055 */, 17 },
- /* 3559 */ { MAD_F(0x06a21055) /* 0.414566359 */, 17 },
- /* 3560 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 17 },
- /* 3561 */ { MAD_F(0x06a35614) /* 0.414877012 */, 17 },
- /* 3562 */ { MAD_F(0x06a3f8f9) /* 0.415032361 */, 17 },
- /* 3563 */ { MAD_F(0x06a49be2) /* 0.415187723 */, 17 },
- /* 3564 */ { MAD_F(0x06a53ece) /* 0.415343101 */, 17 },
- /* 3565 */ { MAD_F(0x06a5e1bf) /* 0.415498493 */, 17 },
- /* 3566 */ { MAD_F(0x06a684b4) /* 0.415653899 */, 17 },
- /* 3567 */ { MAD_F(0x06a727ac) /* 0.415809320 */, 17 },
-
- /* 3568 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 17 },
- /* 3569 */ { MAD_F(0x06a86da9) /* 0.416120206 */, 17 },
- /* 3570 */ { MAD_F(0x06a910ad) /* 0.416275670 */, 17 },
- /* 3571 */ { MAD_F(0x06a9b3b5) /* 0.416431149 */, 17 },
- /* 3572 */ { MAD_F(0x06aa56c1) /* 0.416586643 */, 17 },
- /* 3573 */ { MAD_F(0x06aaf9d1) /* 0.416742151 */, 17 },
- /* 3574 */ { MAD_F(0x06ab9ce5) /* 0.416897673 */, 17 },
- /* 3575 */ { MAD_F(0x06ac3ffc) /* 0.417053210 */, 17 },
- /* 3576 */ { MAD_F(0x06ace318) /* 0.417208762 */, 17 },
- /* 3577 */ { MAD_F(0x06ad8637) /* 0.417364328 */, 17 },
- /* 3578 */ { MAD_F(0x06ae295b) /* 0.417519909 */, 17 },
- /* 3579 */ { MAD_F(0x06aecc82) /* 0.417675504 */, 17 },
- /* 3580 */ { MAD_F(0x06af6fad) /* 0.417831113 */, 17 },
- /* 3581 */ { MAD_F(0x06b012dc) /* 0.417986737 */, 17 },
- /* 3582 */ { MAD_F(0x06b0b60f) /* 0.418142376 */, 17 },
- /* 3583 */ { MAD_F(0x06b15946) /* 0.418298029 */, 17 },
-
- /* 3584 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 17 },
- /* 3585 */ { MAD_F(0x06b29fbf) /* 0.418609378 */, 17 },
- /* 3586 */ { MAD_F(0x06b34302) /* 0.418765075 */, 17 },
- /* 3587 */ { MAD_F(0x06b3e648) /* 0.418920786 */, 17 },
- /* 3588 */ { MAD_F(0x06b48992) /* 0.419076511 */, 17 },
- /* 3589 */ { MAD_F(0x06b52ce0) /* 0.419232251 */, 17 },
- /* 3590 */ { MAD_F(0x06b5d032) /* 0.419388005 */, 17 },
- /* 3591 */ { MAD_F(0x06b67388) /* 0.419543774 */, 17 },
- /* 3592 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 17 },
- /* 3593 */ { MAD_F(0x06b7ba3f) /* 0.419855355 */, 17 },
- /* 3594 */ { MAD_F(0x06b85da1) /* 0.420011167 */, 17 },
- /* 3595 */ { MAD_F(0x06b90106) /* 0.420166994 */, 17 },
- /* 3596 */ { MAD_F(0x06b9a470) /* 0.420322835 */, 17 },
- /* 3597 */ { MAD_F(0x06ba47dd) /* 0.420478690 */, 17 },
- /* 3598 */ { MAD_F(0x06baeb4e) /* 0.420634560 */, 17 },
- /* 3599 */ { MAD_F(0x06bb8ec3) /* 0.420790445 */, 17 },
-
- /* 3600 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 17 },
- /* 3601 */ { MAD_F(0x06bcd5b8) /* 0.421102257 */, 17 },
- /* 3602 */ { MAD_F(0x06bd7939) /* 0.421258184 */, 17 },
- /* 3603 */ { MAD_F(0x06be1cbd) /* 0.421414127 */, 17 },
- /* 3604 */ { MAD_F(0x06bec045) /* 0.421570083 */, 17 },
- /* 3605 */ { MAD_F(0x06bf63d1) /* 0.421726054 */, 17 },
- /* 3606 */ { MAD_F(0x06c00761) /* 0.421882040 */, 17 },
- /* 3607 */ { MAD_F(0x06c0aaf5) /* 0.422038039 */, 17 },
- /* 3608 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 17 },
- /* 3609 */ { MAD_F(0x06c1f229) /* 0.422350082 */, 17 },
- /* 3610 */ { MAD_F(0x06c295c8) /* 0.422506125 */, 17 },
- /* 3611 */ { MAD_F(0x06c3396c) /* 0.422662183 */, 17 },
- /* 3612 */ { MAD_F(0x06c3dd13) /* 0.422818255 */, 17 },
- /* 3613 */ { MAD_F(0x06c480be) /* 0.422974341 */, 17 },
- /* 3614 */ { MAD_F(0x06c5246d) /* 0.423130442 */, 17 },
- /* 3615 */ { MAD_F(0x06c5c820) /* 0.423286557 */, 17 },
-
- /* 3616 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 17 },
- /* 3617 */ { MAD_F(0x06c70f91) /* 0.423598830 */, 17 },
- /* 3618 */ { MAD_F(0x06c7b34f) /* 0.423754988 */, 17 },
- /* 3619 */ { MAD_F(0x06c85712) /* 0.423911161 */, 17 },
- /* 3620 */ { MAD_F(0x06c8fad8) /* 0.424067348 */, 17 },
- /* 3621 */ { MAD_F(0x06c99ea2) /* 0.424223550 */, 17 },
- /* 3622 */ { MAD_F(0x06ca4270) /* 0.424379765 */, 17 },
- /* 3623 */ { MAD_F(0x06cae641) /* 0.424535996 */, 17 },
- /* 3624 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 17 },
- /* 3625 */ { MAD_F(0x06cc2df0) /* 0.424848499 */, 17 },
- /* 3626 */ { MAD_F(0x06ccd1ce) /* 0.425004772 */, 17 },
- /* 3627 */ { MAD_F(0x06cd75af) /* 0.425161060 */, 17 },
- /* 3628 */ { MAD_F(0x06ce1994) /* 0.425317362 */, 17 },
- /* 3629 */ { MAD_F(0x06cebd7d) /* 0.425473678 */, 17 },
- /* 3630 */ { MAD_F(0x06cf6169) /* 0.425630009 */, 17 },
- /* 3631 */ { MAD_F(0x06d0055a) /* 0.425786354 */, 17 },
-
- /* 3632 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 17 },
- /* 3633 */ { MAD_F(0x06d14d47) /* 0.426099088 */, 17 },
- /* 3634 */ { MAD_F(0x06d1f143) /* 0.426255476 */, 17 },
- /* 3635 */ { MAD_F(0x06d29543) /* 0.426411878 */, 17 },
- /* 3636 */ { MAD_F(0x06d33947) /* 0.426568295 */, 17 },
- /* 3637 */ { MAD_F(0x06d3dd4e) /* 0.426724726 */, 17 },
- /* 3638 */ { MAD_F(0x06d4815a) /* 0.426881172 */, 17 },
- /* 3639 */ { MAD_F(0x06d52569) /* 0.427037632 */, 17 },
- /* 3640 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 17 },
- /* 3641 */ { MAD_F(0x06d66d93) /* 0.427350594 */, 17 },
- /* 3642 */ { MAD_F(0x06d711ae) /* 0.427507097 */, 17 },
- /* 3643 */ { MAD_F(0x06d7b5cd) /* 0.427663614 */, 17 },
- /* 3644 */ { MAD_F(0x06d859f0) /* 0.427820146 */, 17 },
- /* 3645 */ { MAD_F(0x06d8fe16) /* 0.427976692 */, 17 },
- /* 3646 */ { MAD_F(0x06d9a240) /* 0.428133252 */, 17 },
- /* 3647 */ { MAD_F(0x06da466f) /* 0.428289826 */, 17 },
-
- /* 3648 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 17 },
- /* 3649 */ { MAD_F(0x06db8ed6) /* 0.428603018 */, 17 },
- /* 3650 */ { MAD_F(0x06dc3310) /* 0.428759635 */, 17 },
- /* 3651 */ { MAD_F(0x06dcd74d) /* 0.428916267 */, 17 },
- /* 3652 */ { MAD_F(0x06dd7b8f) /* 0.429072913 */, 17 },
- /* 3653 */ { MAD_F(0x06de1fd4) /* 0.429229573 */, 17 },
- /* 3654 */ { MAD_F(0x06dec41d) /* 0.429386248 */, 17 },
- /* 3655 */ { MAD_F(0x06df686a) /* 0.429542937 */, 17 },
- /* 3656 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 17 },
- /* 3657 */ { MAD_F(0x06e0b10f) /* 0.429856357 */, 17 },
- /* 3658 */ { MAD_F(0x06e15567) /* 0.430013089 */, 17 },
- /* 3659 */ { MAD_F(0x06e1f9c4) /* 0.430169835 */, 17 },
- /* 3660 */ { MAD_F(0x06e29e24) /* 0.430326595 */, 17 },
- /* 3661 */ { MAD_F(0x06e34287) /* 0.430483370 */, 17 },
- /* 3662 */ { MAD_F(0x06e3e6ef) /* 0.430640159 */, 17 },
- /* 3663 */ { MAD_F(0x06e48b5b) /* 0.430796962 */, 17 },
-
- /* 3664 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 17 },
- /* 3665 */ { MAD_F(0x06e5d43d) /* 0.431110611 */, 17 },
- /* 3666 */ { MAD_F(0x06e678b4) /* 0.431267457 */, 17 },
- /* 3667 */ { MAD_F(0x06e71d2f) /* 0.431424317 */, 17 },
- /* 3668 */ { MAD_F(0x06e7c1ae) /* 0.431581192 */, 17 },
- /* 3669 */ { MAD_F(0x06e86630) /* 0.431738080 */, 17 },
- /* 3670 */ { MAD_F(0x06e90ab7) /* 0.431894983 */, 17 },
- /* 3671 */ { MAD_F(0x06e9af41) /* 0.432051900 */, 17 },
- /* 3672 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 17 },
- /* 3673 */ { MAD_F(0x06eaf860) /* 0.432365778 */, 17 },
- /* 3674 */ { MAD_F(0x06eb9cf6) /* 0.432522737 */, 17 },
- /* 3675 */ { MAD_F(0x06ec418f) /* 0.432679712 */, 17 },
- /* 3676 */ { MAD_F(0x06ece62d) /* 0.432836700 */, 17 },
- /* 3677 */ { MAD_F(0x06ed8ace) /* 0.432993703 */, 17 },
- /* 3678 */ { MAD_F(0x06ee2f73) /* 0.433150720 */, 17 },
- /* 3679 */ { MAD_F(0x06eed41b) /* 0.433307751 */, 17 },
-
- /* 3680 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 17 },
- /* 3681 */ { MAD_F(0x06f01d78) /* 0.433621856 */, 17 },
- /* 3682 */ { MAD_F(0x06f0c22c) /* 0.433778929 */, 17 },
- /* 3683 */ { MAD_F(0x06f166e4) /* 0.433936017 */, 17 },
- /* 3684 */ { MAD_F(0x06f20ba0) /* 0.434093120 */, 17 },
- /* 3685 */ { MAD_F(0x06f2b060) /* 0.434250236 */, 17 },
- /* 3686 */ { MAD_F(0x06f35523) /* 0.434407367 */, 17 },
- /* 3687 */ { MAD_F(0x06f3f9eb) /* 0.434564512 */, 17 },
- /* 3688 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 17 },
- /* 3689 */ { MAD_F(0x06f54385) /* 0.434878844 */, 17 },
- /* 3690 */ { MAD_F(0x06f5e857) /* 0.435036032 */, 17 },
- /* 3691 */ { MAD_F(0x06f68d2e) /* 0.435193233 */, 17 },
- /* 3692 */ { MAD_F(0x06f73208) /* 0.435350449 */, 17 },
- /* 3693 */ { MAD_F(0x06f7d6e6) /* 0.435507679 */, 17 },
- /* 3694 */ { MAD_F(0x06f87bc8) /* 0.435664924 */, 17 },
- /* 3695 */ { MAD_F(0x06f920ae) /* 0.435822182 */, 17 },
-
- /* 3696 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 17 },
- /* 3697 */ { MAD_F(0x06fa6a85) /* 0.436136741 */, 17 },
- /* 3698 */ { MAD_F(0x06fb0f76) /* 0.436294042 */, 17 },
- /* 3699 */ { MAD_F(0x06fbb46b) /* 0.436451358 */, 17 },
- /* 3700 */ { MAD_F(0x06fc5964) /* 0.436608687 */, 17 },
- /* 3701 */ { MAD_F(0x06fcfe60) /* 0.436766031 */, 17 },
- /* 3702 */ { MAD_F(0x06fda361) /* 0.436923388 */, 17 },
- /* 3703 */ { MAD_F(0x06fe4865) /* 0.437080760 */, 17 },
- /* 3704 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 17 },
- /* 3705 */ { MAD_F(0x06ff9279) /* 0.437395547 */, 17 },
- /* 3706 */ { MAD_F(0x07003788) /* 0.437552961 */, 17 },
- /* 3707 */ { MAD_F(0x0700dc9c) /* 0.437710389 */, 17 },
- /* 3708 */ { MAD_F(0x070181b3) /* 0.437867832 */, 17 },
- /* 3709 */ { MAD_F(0x070226ce) /* 0.438025289 */, 17 },
- /* 3710 */ { MAD_F(0x0702cbed) /* 0.438182760 */, 17 },
- /* 3711 */ { MAD_F(0x0703710f) /* 0.438340245 */, 17 },
-
- /* 3712 */ { MAD_F(0x07041636) /* 0.438497744 */, 17 },
- /* 3713 */ { MAD_F(0x0704bb60) /* 0.438655258 */, 17 },
- /* 3714 */ { MAD_F(0x0705608e) /* 0.438812785 */, 17 },
- /* 3715 */ { MAD_F(0x070605c0) /* 0.438970327 */, 17 },
- /* 3716 */ { MAD_F(0x0706aaf5) /* 0.439127883 */, 17 },
- /* 3717 */ { MAD_F(0x0707502f) /* 0.439285453 */, 17 },
- /* 3718 */ { MAD_F(0x0707f56c) /* 0.439443037 */, 17 },
- /* 3719 */ { MAD_F(0x07089aad) /* 0.439600635 */, 17 },
- /* 3720 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 17 },
- /* 3721 */ { MAD_F(0x0709e53a) /* 0.439915874 */, 17 },
- /* 3722 */ { MAD_F(0x070a8a86) /* 0.440073515 */, 17 },
- /* 3723 */ { MAD_F(0x070b2fd7) /* 0.440231170 */, 17 },
- /* 3724 */ { MAD_F(0x070bd52a) /* 0.440388839 */, 17 },
- /* 3725 */ { MAD_F(0x070c7a82) /* 0.440546522 */, 17 },
- /* 3726 */ { MAD_F(0x070d1fde) /* 0.440704219 */, 17 },
- /* 3727 */ { MAD_F(0x070dc53d) /* 0.440861930 */, 17 },
-
- /* 3728 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 17 },
- /* 3729 */ { MAD_F(0x070f1007) /* 0.441177395 */, 17 },
- /* 3730 */ { MAD_F(0x070fb571) /* 0.441335148 */, 17 },
- /* 3731 */ { MAD_F(0x07105ae0) /* 0.441492916 */, 17 },
- /* 3732 */ { MAD_F(0x07110052) /* 0.441650697 */, 17 },
- /* 3733 */ { MAD_F(0x0711a5c8) /* 0.441808493 */, 17 },
- /* 3734 */ { MAD_F(0x07124b42) /* 0.441966303 */, 17 },
- /* 3735 */ { MAD_F(0x0712f0bf) /* 0.442124127 */, 17 },
- /* 3736 */ { MAD_F(0x07139641) /* 0.442281965 */, 17 },
- /* 3737 */ { MAD_F(0x07143bc6) /* 0.442439817 */, 17 },
- /* 3738 */ { MAD_F(0x0714e14f) /* 0.442597683 */, 17 },
- /* 3739 */ { MAD_F(0x071586db) /* 0.442755564 */, 17 },
- /* 3740 */ { MAD_F(0x07162c6c) /* 0.442913458 */, 17 },
- /* 3741 */ { MAD_F(0x0716d200) /* 0.443071366 */, 17 },
- /* 3742 */ { MAD_F(0x07177798) /* 0.443229289 */, 17 },
- /* 3743 */ { MAD_F(0x07181d34) /* 0.443387226 */, 17 },
-
- /* 3744 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 17 },
- /* 3745 */ { MAD_F(0x07196877) /* 0.443703141 */, 17 },
- /* 3746 */ { MAD_F(0x071a0e1e) /* 0.443861120 */, 17 },
- /* 3747 */ { MAD_F(0x071ab3c9) /* 0.444019113 */, 17 },
- /* 3748 */ { MAD_F(0x071b5977) /* 0.444177119 */, 17 },
- /* 3749 */ { MAD_F(0x071bff2a) /* 0.444335140 */, 17 },
- /* 3750 */ { MAD_F(0x071ca4e0) /* 0.444493175 */, 17 },
- /* 3751 */ { MAD_F(0x071d4a9a) /* 0.444651224 */, 17 },
- /* 3752 */ { MAD_F(0x071df058) /* 0.444809288 */, 17 },
- /* 3753 */ { MAD_F(0x071e9619) /* 0.444967365 */, 17 },
- /* 3754 */ { MAD_F(0x071f3bde) /* 0.445125456 */, 17 },
- /* 3755 */ { MAD_F(0x071fe1a8) /* 0.445283561 */, 17 },
- /* 3756 */ { MAD_F(0x07208774) /* 0.445441680 */, 17 },
- /* 3757 */ { MAD_F(0x07212d45) /* 0.445599814 */, 17 },
- /* 3758 */ { MAD_F(0x0721d319) /* 0.445757961 */, 17 },
- /* 3759 */ { MAD_F(0x072278f1) /* 0.445916122 */, 17 },
-
- /* 3760 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 17 },
- /* 3761 */ { MAD_F(0x0723c4ad) /* 0.446232487 */, 17 },
- /* 3762 */ { MAD_F(0x07246a90) /* 0.446390690 */, 17 },
- /* 3763 */ { MAD_F(0x07251077) /* 0.446548908 */, 17 },
- /* 3764 */ { MAD_F(0x0725b662) /* 0.446707139 */, 17 },
- /* 3765 */ { MAD_F(0x07265c51) /* 0.446865385 */, 17 },
- /* 3766 */ { MAD_F(0x07270244) /* 0.447023644 */, 17 },
- /* 3767 */ { MAD_F(0x0727a83a) /* 0.447181918 */, 17 },
- /* 3768 */ { MAD_F(0x07284e34) /* 0.447340205 */, 17 },
- /* 3769 */ { MAD_F(0x0728f431) /* 0.447498507 */, 17 },
- /* 3770 */ { MAD_F(0x07299a33) /* 0.447656822 */, 17 },
- /* 3771 */ { MAD_F(0x072a4038) /* 0.447815152 */, 17 },
- /* 3772 */ { MAD_F(0x072ae641) /* 0.447973495 */, 17 },
- /* 3773 */ { MAD_F(0x072b8c4e) /* 0.448131853 */, 17 },
- /* 3774 */ { MAD_F(0x072c325e) /* 0.448290224 */, 17 },
- /* 3775 */ { MAD_F(0x072cd873) /* 0.448448609 */, 17 },
-
- /* 3776 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 17 },
- /* 3777 */ { MAD_F(0x072e24a7) /* 0.448765422 */, 17 },
- /* 3778 */ { MAD_F(0x072ecac6) /* 0.448923850 */, 17 },
- /* 3779 */ { MAD_F(0x072f70e9) /* 0.449082291 */, 17 },
- /* 3780 */ { MAD_F(0x07301710) /* 0.449240746 */, 17 },
- /* 3781 */ { MAD_F(0x0730bd3b) /* 0.449399216 */, 17 },
- /* 3782 */ { MAD_F(0x0731636a) /* 0.449557699 */, 17 },
- /* 3783 */ { MAD_F(0x0732099c) /* 0.449716196 */, 17 },
- /* 3784 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 17 },
- /* 3785 */ { MAD_F(0x0733560c) /* 0.450033233 */, 17 },
- /* 3786 */ { MAD_F(0x0733fc49) /* 0.450191772 */, 17 },
- /* 3787 */ { MAD_F(0x0734a28b) /* 0.450350325 */, 17 },
- /* 3788 */ { MAD_F(0x073548d0) /* 0.450508892 */, 17 },
- /* 3789 */ { MAD_F(0x0735ef18) /* 0.450667473 */, 17 },
- /* 3790 */ { MAD_F(0x07369565) /* 0.450826068 */, 17 },
- /* 3791 */ { MAD_F(0x07373bb5) /* 0.450984677 */, 17 },
-
- /* 3792 */ { MAD_F(0x0737e209) /* 0.451143300 */, 17 },
- /* 3793 */ { MAD_F(0x07388861) /* 0.451301937 */, 17 },
- /* 3794 */ { MAD_F(0x07392ebc) /* 0.451460588 */, 17 },
- /* 3795 */ { MAD_F(0x0739d51c) /* 0.451619252 */, 17 },
- /* 3796 */ { MAD_F(0x073a7b7f) /* 0.451777931 */, 17 },
- /* 3797 */ { MAD_F(0x073b21e5) /* 0.451936623 */, 17 },
- /* 3798 */ { MAD_F(0x073bc850) /* 0.452095330 */, 17 },
- /* 3799 */ { MAD_F(0x073c6ebe) /* 0.452254050 */, 17 },
- /* 3800 */ { MAD_F(0x073d1530) /* 0.452412785 */, 17 },
- /* 3801 */ { MAD_F(0x073dbba6) /* 0.452571533 */, 17 },
- /* 3802 */ { MAD_F(0x073e621f) /* 0.452730295 */, 17 },
- /* 3803 */ { MAD_F(0x073f089c) /* 0.452889071 */, 17 },
- /* 3804 */ { MAD_F(0x073faf1d) /* 0.453047861 */, 17 },
- /* 3805 */ { MAD_F(0x074055a2) /* 0.453206665 */, 17 },
- /* 3806 */ { MAD_F(0x0740fc2a) /* 0.453365483 */, 17 },
- /* 3807 */ { MAD_F(0x0741a2b6) /* 0.453524315 */, 17 },
-
- /* 3808 */ { MAD_F(0x07424946) /* 0.453683161 */, 17 },
- /* 3809 */ { MAD_F(0x0742efd9) /* 0.453842020 */, 17 },
- /* 3810 */ { MAD_F(0x07439671) /* 0.454000894 */, 17 },
- /* 3811 */ { MAD_F(0x07443d0c) /* 0.454159781 */, 17 },
- /* 3812 */ { MAD_F(0x0744e3aa) /* 0.454318683 */, 17 },
- /* 3813 */ { MAD_F(0x07458a4d) /* 0.454477598 */, 17 },
- /* 3814 */ { MAD_F(0x074630f3) /* 0.454636527 */, 17 },
- /* 3815 */ { MAD_F(0x0746d79d) /* 0.454795470 */, 17 },
- /* 3816 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 17 },
- /* 3817 */ { MAD_F(0x074824fc) /* 0.455113397 */, 17 },
- /* 3818 */ { MAD_F(0x0748cbb1) /* 0.455272382 */, 17 },
- /* 3819 */ { MAD_F(0x0749726a) /* 0.455431381 */, 17 },
- /* 3820 */ { MAD_F(0x074a1927) /* 0.455590393 */, 17 },
- /* 3821 */ { MAD_F(0x074abfe7) /* 0.455749419 */, 17 },
- /* 3822 */ { MAD_F(0x074b66ab) /* 0.455908459 */, 17 },
- /* 3823 */ { MAD_F(0x074c0d73) /* 0.456067513 */, 17 },
-
- /* 3824 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 17 },
- /* 3825 */ { MAD_F(0x074d5b0d) /* 0.456385663 */, 17 },
- /* 3826 */ { MAD_F(0x074e01e0) /* 0.456544759 */, 17 },
- /* 3827 */ { MAD_F(0x074ea8b7) /* 0.456703868 */, 17 },
- /* 3828 */ { MAD_F(0x074f4f91) /* 0.456862992 */, 17 },
- /* 3829 */ { MAD_F(0x074ff66f) /* 0.457022129 */, 17 },
- /* 3830 */ { MAD_F(0x07509d51) /* 0.457181280 */, 17 },
- /* 3831 */ { MAD_F(0x07514437) /* 0.457340445 */, 17 },
- /* 3832 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 17 },
- /* 3833 */ { MAD_F(0x0752920d) /* 0.457658816 */, 17 },
- /* 3834 */ { MAD_F(0x075338fd) /* 0.457818022 */, 17 },
- /* 3835 */ { MAD_F(0x0753dff2) /* 0.457977243 */, 17 },
- /* 3836 */ { MAD_F(0x075486ea) /* 0.458136477 */, 17 },
- /* 3837 */ { MAD_F(0x07552de6) /* 0.458295725 */, 17 },
- /* 3838 */ { MAD_F(0x0755d4e5) /* 0.458454987 */, 17 },
- /* 3839 */ { MAD_F(0x07567be8) /* 0.458614262 */, 17 },
-
- /* 3840 */ { MAD_F(0x075722ef) /* 0.458773552 */, 17 },
- /* 3841 */ { MAD_F(0x0757c9fa) /* 0.458932855 */, 17 },
- /* 3842 */ { MAD_F(0x07587108) /* 0.459092172 */, 17 },
- /* 3843 */ { MAD_F(0x0759181a) /* 0.459251503 */, 17 },
- /* 3844 */ { MAD_F(0x0759bf30) /* 0.459410848 */, 17 },
- /* 3845 */ { MAD_F(0x075a664a) /* 0.459570206 */, 17 },
- /* 3846 */ { MAD_F(0x075b0d67) /* 0.459729579 */, 17 },
- /* 3847 */ { MAD_F(0x075bb488) /* 0.459888965 */, 17 },
- /* 3848 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 17 },
- /* 3849 */ { MAD_F(0x075d02d5) /* 0.460207779 */, 17 },
- /* 3850 */ { MAD_F(0x075daa01) /* 0.460367206 */, 17 },
- /* 3851 */ { MAD_F(0x075e5130) /* 0.460526648 */, 17 },
- /* 3852 */ { MAD_F(0x075ef864) /* 0.460686103 */, 17 },
- /* 3853 */ { MAD_F(0x075f9f9b) /* 0.460845572 */, 17 },
- /* 3854 */ { MAD_F(0x076046d6) /* 0.461005055 */, 17 },
- /* 3855 */ { MAD_F(0x0760ee14) /* 0.461164552 */, 17 },
-
- /* 3856 */ { MAD_F(0x07619557) /* 0.461324062 */, 17 },
- /* 3857 */ { MAD_F(0x07623c9d) /* 0.461483586 */, 17 },
- /* 3858 */ { MAD_F(0x0762e3e6) /* 0.461643124 */, 17 },
- /* 3859 */ { MAD_F(0x07638b34) /* 0.461802676 */, 17 },
- /* 3860 */ { MAD_F(0x07643285) /* 0.461962242 */, 17 },
- /* 3861 */ { MAD_F(0x0764d9d9) /* 0.462121821 */, 17 },
- /* 3862 */ { MAD_F(0x07658132) /* 0.462281414 */, 17 },
- /* 3863 */ { MAD_F(0x0766288e) /* 0.462441021 */, 17 },
- /* 3864 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 17 },
- /* 3865 */ { MAD_F(0x07677751) /* 0.462760276 */, 17 },
- /* 3866 */ { MAD_F(0x07681eb9) /* 0.462919924 */, 17 },
- /* 3867 */ { MAD_F(0x0768c624) /* 0.463079586 */, 17 },
- /* 3868 */ { MAD_F(0x07696d92) /* 0.463239262 */, 17 },
- /* 3869 */ { MAD_F(0x076a1505) /* 0.463398951 */, 17 },
- /* 3870 */ { MAD_F(0x076abc7b) /* 0.463558655 */, 17 },
- /* 3871 */ { MAD_F(0x076b63f4) /* 0.463718372 */, 17 },
-
- /* 3872 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 17 },
- /* 3873 */ { MAD_F(0x076cb2f3) /* 0.464037847 */, 17 },
- /* 3874 */ { MAD_F(0x076d5a78) /* 0.464197605 */, 17 },
- /* 3875 */ { MAD_F(0x076e0200) /* 0.464357377 */, 17 },
- /* 3876 */ { MAD_F(0x076ea98c) /* 0.464517163 */, 17 },
- /* 3877 */ { MAD_F(0x076f511c) /* 0.464676962 */, 17 },
- /* 3878 */ { MAD_F(0x076ff8b0) /* 0.464836776 */, 17 },
- /* 3879 */ { MAD_F(0x0770a047) /* 0.464996603 */, 17 },
- /* 3880 */ { MAD_F(0x077147e2) /* 0.465156443 */, 17 },
- /* 3881 */ { MAD_F(0x0771ef80) /* 0.465316298 */, 17 },
- /* 3882 */ { MAD_F(0x07729723) /* 0.465476166 */, 17 },
- /* 3883 */ { MAD_F(0x07733ec9) /* 0.465636048 */, 17 },
- /* 3884 */ { MAD_F(0x0773e672) /* 0.465795943 */, 17 },
- /* 3885 */ { MAD_F(0x07748e20) /* 0.465955853 */, 17 },
- /* 3886 */ { MAD_F(0x077535d1) /* 0.466115776 */, 17 },
- /* 3887 */ { MAD_F(0x0775dd85) /* 0.466275713 */, 17 },
-
- /* 3888 */ { MAD_F(0x0776853e) /* 0.466435663 */, 17 },
- /* 3889 */ { MAD_F(0x07772cfa) /* 0.466595627 */, 17 },
- /* 3890 */ { MAD_F(0x0777d4ba) /* 0.466755605 */, 17 },
- /* 3891 */ { MAD_F(0x07787c7d) /* 0.466915597 */, 17 },
- /* 3892 */ { MAD_F(0x07792444) /* 0.467075602 */, 17 },
- /* 3893 */ { MAD_F(0x0779cc0f) /* 0.467235621 */, 17 },
- /* 3894 */ { MAD_F(0x077a73dd) /* 0.467395654 */, 17 },
- /* 3895 */ { MAD_F(0x077b1baf) /* 0.467555701 */, 17 },
- /* 3896 */ { MAD_F(0x077bc385) /* 0.467715761 */, 17 },
- /* 3897 */ { MAD_F(0x077c6b5f) /* 0.467875835 */, 17 },
- /* 3898 */ { MAD_F(0x077d133c) /* 0.468035922 */, 17 },
- /* 3899 */ { MAD_F(0x077dbb1d) /* 0.468196023 */, 17 },
- /* 3900 */ { MAD_F(0x077e6301) /* 0.468356138 */, 17 },
- /* 3901 */ { MAD_F(0x077f0ae9) /* 0.468516267 */, 17 },
- /* 3902 */ { MAD_F(0x077fb2d5) /* 0.468676409 */, 17 },
- /* 3903 */ { MAD_F(0x07805ac5) /* 0.468836565 */, 17 },
-
- /* 3904 */ { MAD_F(0x078102b8) /* 0.468996735 */, 17 },
- /* 3905 */ { MAD_F(0x0781aaaf) /* 0.469156918 */, 17 },
- /* 3906 */ { MAD_F(0x078252aa) /* 0.469317115 */, 17 },
- /* 3907 */ { MAD_F(0x0782faa8) /* 0.469477326 */, 17 },
- /* 3908 */ { MAD_F(0x0783a2aa) /* 0.469637550 */, 17 },
- /* 3909 */ { MAD_F(0x07844aaf) /* 0.469797788 */, 17 },
- /* 3910 */ { MAD_F(0x0784f2b8) /* 0.469958040 */, 17 },
- /* 3911 */ { MAD_F(0x07859ac5) /* 0.470118305 */, 17 },
- /* 3912 */ { MAD_F(0x078642d6) /* 0.470278584 */, 17 },
- /* 3913 */ { MAD_F(0x0786eaea) /* 0.470438877 */, 17 },
- /* 3914 */ { MAD_F(0x07879302) /* 0.470599183 */, 17 },
- /* 3915 */ { MAD_F(0x07883b1e) /* 0.470759503 */, 17 },
- /* 3916 */ { MAD_F(0x0788e33d) /* 0.470919836 */, 17 },
- /* 3917 */ { MAD_F(0x07898b60) /* 0.471080184 */, 17 },
- /* 3918 */ { MAD_F(0x078a3386) /* 0.471240545 */, 17 },
- /* 3919 */ { MAD_F(0x078adbb0) /* 0.471400919 */, 17 },
-
- /* 3920 */ { MAD_F(0x078b83de) /* 0.471561307 */, 17 },
- /* 3921 */ { MAD_F(0x078c2c10) /* 0.471721709 */, 17 },
- /* 3922 */ { MAD_F(0x078cd445) /* 0.471882125 */, 17 },
- /* 3923 */ { MAD_F(0x078d7c7e) /* 0.472042554 */, 17 },
- /* 3924 */ { MAD_F(0x078e24ba) /* 0.472202996 */, 17 },
- /* 3925 */ { MAD_F(0x078eccfb) /* 0.472363453 */, 17 },
- /* 3926 */ { MAD_F(0x078f753e) /* 0.472523923 */, 17 },
- /* 3927 */ { MAD_F(0x07901d86) /* 0.472684406 */, 17 },
- /* 3928 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 17 },
- /* 3929 */ { MAD_F(0x07916e20) /* 0.473005414 */, 17 },
- /* 3930 */ { MAD_F(0x07921672) /* 0.473165939 */, 17 },
- /* 3931 */ { MAD_F(0x0792bec8) /* 0.473326477 */, 17 },
- /* 3932 */ { MAD_F(0x07936722) /* 0.473487029 */, 17 },
- /* 3933 */ { MAD_F(0x07940f80) /* 0.473647594 */, 17 },
- /* 3934 */ { MAD_F(0x0794b7e1) /* 0.473808173 */, 17 },
- /* 3935 */ { MAD_F(0x07956045) /* 0.473968765 */, 17 },
-
- /* 3936 */ { MAD_F(0x079608ae) /* 0.474129372 */, 17 },
- /* 3937 */ { MAD_F(0x0796b11a) /* 0.474289991 */, 17 },
- /* 3938 */ { MAD_F(0x0797598a) /* 0.474450625 */, 17 },
- /* 3939 */ { MAD_F(0x079801fd) /* 0.474611272 */, 17 },
- /* 3940 */ { MAD_F(0x0798aa74) /* 0.474771932 */, 17 },
- /* 3941 */ { MAD_F(0x079952ee) /* 0.474932606 */, 17 },
- /* 3942 */ { MAD_F(0x0799fb6d) /* 0.475093294 */, 17 },
- /* 3943 */ { MAD_F(0x079aa3ef) /* 0.475253995 */, 17 },
- /* 3944 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 17 },
- /* 3945 */ { MAD_F(0x079bf4fd) /* 0.475575439 */, 17 },
- /* 3946 */ { MAD_F(0x079c9d8a) /* 0.475736181 */, 17 },
- /* 3947 */ { MAD_F(0x079d461b) /* 0.475896936 */, 17 },
- /* 3948 */ { MAD_F(0x079deeaf) /* 0.476057705 */, 17 },
- /* 3949 */ { MAD_F(0x079e9747) /* 0.476218488 */, 17 },
- /* 3950 */ { MAD_F(0x079f3fe2) /* 0.476379285 */, 17 },
- /* 3951 */ { MAD_F(0x079fe881) /* 0.476540095 */, 17 },
-
- /* 3952 */ { MAD_F(0x07a09124) /* 0.476700918 */, 17 },
- /* 3953 */ { MAD_F(0x07a139ca) /* 0.476861755 */, 17 },
- /* 3954 */ { MAD_F(0x07a1e274) /* 0.477022606 */, 17 },
- /* 3955 */ { MAD_F(0x07a28b22) /* 0.477183470 */, 17 },
- /* 3956 */ { MAD_F(0x07a333d3) /* 0.477344348 */, 17 },
- /* 3957 */ { MAD_F(0x07a3dc88) /* 0.477505239 */, 17 },
- /* 3958 */ { MAD_F(0x07a48541) /* 0.477666144 */, 17 },
- /* 3959 */ { MAD_F(0x07a52dfd) /* 0.477827062 */, 17 },
- /* 3960 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 17 },
- /* 3961 */ { MAD_F(0x07a67f80) /* 0.478148940 */, 17 },
- /* 3962 */ { MAD_F(0x07a72847) /* 0.478309899 */, 17 },
- /* 3963 */ { MAD_F(0x07a7d112) /* 0.478470871 */, 17 },
- /* 3964 */ { MAD_F(0x07a879e1) /* 0.478631857 */, 17 },
- /* 3965 */ { MAD_F(0x07a922b3) /* 0.478792857 */, 17 },
- /* 3966 */ { MAD_F(0x07a9cb88) /* 0.478953870 */, 17 },
- /* 3967 */ { MAD_F(0x07aa7462) /* 0.479114897 */, 17 },
-
- /* 3968 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 17 },
- /* 3969 */ { MAD_F(0x07abc61f) /* 0.479436991 */, 17 },
- /* 3970 */ { MAD_F(0x07ac6f03) /* 0.479598058 */, 17 },
- /* 3971 */ { MAD_F(0x07ad17eb) /* 0.479759139 */, 17 },
- /* 3972 */ { MAD_F(0x07adc0d6) /* 0.479920233 */, 17 },
- /* 3973 */ { MAD_F(0x07ae69c6) /* 0.480081341 */, 17 },
- /* 3974 */ { MAD_F(0x07af12b8) /* 0.480242463 */, 17 },
- /* 3975 */ { MAD_F(0x07afbbaf) /* 0.480403598 */, 17 },
- /* 3976 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 17 },
- /* 3977 */ { MAD_F(0x07b10da6) /* 0.480725908 */, 17 },
- /* 3978 */ { MAD_F(0x07b1b6a7) /* 0.480887083 */, 17 },
- /* 3979 */ { MAD_F(0x07b25fac) /* 0.481048272 */, 17 },
- /* 3980 */ { MAD_F(0x07b308b5) /* 0.481209475 */, 17 },
- /* 3981 */ { MAD_F(0x07b3b1c1) /* 0.481370691 */, 17 },
- /* 3982 */ { MAD_F(0x07b45ad0) /* 0.481531920 */, 17 },
- /* 3983 */ { MAD_F(0x07b503e4) /* 0.481693163 */, 17 },
-
- /* 3984 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 17 },
- /* 3985 */ { MAD_F(0x07b65615) /* 0.482015690 */, 17 },
- /* 3986 */ { MAD_F(0x07b6ff33) /* 0.482176973 */, 17 },
- /* 3987 */ { MAD_F(0x07b7a855) /* 0.482338270 */, 17 },
- /* 3988 */ { MAD_F(0x07b8517b) /* 0.482499580 */, 17 },
- /* 3989 */ { MAD_F(0x07b8faa4) /* 0.482660904 */, 17 },
- /* 3990 */ { MAD_F(0x07b9a3d0) /* 0.482822242 */, 17 },
- /* 3991 */ { MAD_F(0x07ba4d01) /* 0.482983592 */, 17 },
- /* 3992 */ { MAD_F(0x07baf635) /* 0.483144957 */, 17 },
- /* 3993 */ { MAD_F(0x07bb9f6c) /* 0.483306335 */, 17 },
- /* 3994 */ { MAD_F(0x07bc48a7) /* 0.483467726 */, 17 },
- /* 3995 */ { MAD_F(0x07bcf1e6) /* 0.483629131 */, 17 },
- /* 3996 */ { MAD_F(0x07bd9b28) /* 0.483790549 */, 17 },
- /* 3997 */ { MAD_F(0x07be446e) /* 0.483951980 */, 17 },
- /* 3998 */ { MAD_F(0x07beedb8) /* 0.484113426 */, 17 },
- /* 3999 */ { MAD_F(0x07bf9705) /* 0.484274884 */, 17 },
-
- /* 4000 */ { MAD_F(0x07c04056) /* 0.484436356 */, 17 },
- /* 4001 */ { MAD_F(0x07c0e9aa) /* 0.484597842 */, 17 },
- /* 4002 */ { MAD_F(0x07c19302) /* 0.484759341 */, 17 },
- /* 4003 */ { MAD_F(0x07c23c5e) /* 0.484920853 */, 17 },
- /* 4004 */ { MAD_F(0x07c2e5bd) /* 0.485082379 */, 17 },
- /* 4005 */ { MAD_F(0x07c38f20) /* 0.485243918 */, 17 },
- /* 4006 */ { MAD_F(0x07c43887) /* 0.485405471 */, 17 },
- /* 4007 */ { MAD_F(0x07c4e1f1) /* 0.485567037 */, 17 },
- /* 4008 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 17 },
- /* 4009 */ { MAD_F(0x07c634d0) /* 0.485890210 */, 17 },
- /* 4010 */ { MAD_F(0x07c6de45) /* 0.486051817 */, 17 },
- /* 4011 */ { MAD_F(0x07c787bd) /* 0.486213436 */, 17 },
- /* 4012 */ { MAD_F(0x07c83139) /* 0.486375070 */, 17 },
- /* 4013 */ { MAD_F(0x07c8dab9) /* 0.486536717 */, 17 },
- /* 4014 */ { MAD_F(0x07c9843c) /* 0.486698377 */, 17 },
- /* 4015 */ { MAD_F(0x07ca2dc3) /* 0.486860051 */, 17 },
-
- /* 4016 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 17 },
- /* 4017 */ { MAD_F(0x07cb80dc) /* 0.487183438 */, 17 },
- /* 4018 */ { MAD_F(0x07cc2a6e) /* 0.487345152 */, 17 },
- /* 4019 */ { MAD_F(0x07ccd403) /* 0.487506879 */, 17 },
- /* 4020 */ { MAD_F(0x07cd7d9c) /* 0.487668620 */, 17 },
- /* 4021 */ { MAD_F(0x07ce2739) /* 0.487830374 */, 17 },
- /* 4022 */ { MAD_F(0x07ced0d9) /* 0.487992142 */, 17 },
- /* 4023 */ { MAD_F(0x07cf7a7d) /* 0.488153923 */, 17 },
- /* 4024 */ { MAD_F(0x07d02424) /* 0.488315717 */, 17 },
- /* 4025 */ { MAD_F(0x07d0cdcf) /* 0.488477525 */, 17 },
- /* 4026 */ { MAD_F(0x07d1777e) /* 0.488639346 */, 17 },
- /* 4027 */ { MAD_F(0x07d22130) /* 0.488801181 */, 17 },
- /* 4028 */ { MAD_F(0x07d2cae5) /* 0.488963029 */, 17 },
- /* 4029 */ { MAD_F(0x07d3749f) /* 0.489124890 */, 17 },
- /* 4030 */ { MAD_F(0x07d41e5c) /* 0.489286765 */, 17 },
- /* 4031 */ { MAD_F(0x07d4c81c) /* 0.489448653 */, 17 },
-
- /* 4032 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 17 },
- /* 4033 */ { MAD_F(0x07d61ba8) /* 0.489772470 */, 17 },
- /* 4034 */ { MAD_F(0x07d6c573) /* 0.489934398 */, 17 },
- /* 4035 */ { MAD_F(0x07d76f42) /* 0.490096340 */, 17 },
- /* 4036 */ { MAD_F(0x07d81915) /* 0.490258295 */, 17 },
- /* 4037 */ { MAD_F(0x07d8c2eb) /* 0.490420263 */, 17 },
- /* 4038 */ { MAD_F(0x07d96cc4) /* 0.490582245 */, 17 },
- /* 4039 */ { MAD_F(0x07da16a2) /* 0.490744240 */, 17 },
- /* 4040 */ { MAD_F(0x07dac083) /* 0.490906249 */, 17 },
- /* 4041 */ { MAD_F(0x07db6a67) /* 0.491068271 */, 17 },
- /* 4042 */ { MAD_F(0x07dc144f) /* 0.491230306 */, 17 },
- /* 4043 */ { MAD_F(0x07dcbe3b) /* 0.491392355 */, 17 },
- /* 4044 */ { MAD_F(0x07dd682a) /* 0.491554417 */, 17 },
- /* 4045 */ { MAD_F(0x07de121d) /* 0.491716492 */, 17 },
- /* 4046 */ { MAD_F(0x07debc13) /* 0.491878581 */, 17 },
- /* 4047 */ { MAD_F(0x07df660d) /* 0.492040683 */, 17 },
-
- /* 4048 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 17 },
- /* 4049 */ { MAD_F(0x07e0ba0c) /* 0.492364928 */, 17 },
- /* 4050 */ { MAD_F(0x07e16410) /* 0.492527070 */, 17 },
- /* 4051 */ { MAD_F(0x07e20e19) /* 0.492689225 */, 17 },
- /* 4052 */ { MAD_F(0x07e2b824) /* 0.492851394 */, 17 },
- /* 4053 */ { MAD_F(0x07e36234) /* 0.493013576 */, 17 },
- /* 4054 */ { MAD_F(0x07e40c47) /* 0.493175772 */, 17 },
- /* 4055 */ { MAD_F(0x07e4b65e) /* 0.493337981 */, 17 },
- /* 4056 */ { MAD_F(0x07e56078) /* 0.493500203 */, 17 },
- /* 4057 */ { MAD_F(0x07e60a95) /* 0.493662438 */, 17 },
- /* 4058 */ { MAD_F(0x07e6b4b7) /* 0.493824687 */, 17 },
- /* 4059 */ { MAD_F(0x07e75edc) /* 0.493986949 */, 17 },
- /* 4060 */ { MAD_F(0x07e80904) /* 0.494149225 */, 17 },
- /* 4061 */ { MAD_F(0x07e8b330) /* 0.494311514 */, 17 },
- /* 4062 */ { MAD_F(0x07e95d60) /* 0.494473816 */, 17 },
- /* 4063 */ { MAD_F(0x07ea0793) /* 0.494636131 */, 17 },
-
- /* 4064 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 17 },
- /* 4065 */ { MAD_F(0x07eb5c04) /* 0.494960802 */, 17 },
- /* 4066 */ { MAD_F(0x07ec0642) /* 0.495123158 */, 17 },
- /* 4067 */ { MAD_F(0x07ecb084) /* 0.495285526 */, 17 },
- /* 4068 */ { MAD_F(0x07ed5ac9) /* 0.495447908 */, 17 },
- /* 4069 */ { MAD_F(0x07ee0512) /* 0.495610304 */, 17 },
- /* 4070 */ { MAD_F(0x07eeaf5e) /* 0.495772712 */, 17 },
- /* 4071 */ { MAD_F(0x07ef59ae) /* 0.495935134 */, 17 },
- /* 4072 */ { MAD_F(0x07f00401) /* 0.496097570 */, 17 },
- /* 4073 */ { MAD_F(0x07f0ae58) /* 0.496260018 */, 17 },
- /* 4074 */ { MAD_F(0x07f158b3) /* 0.496422480 */, 17 },
- /* 4075 */ { MAD_F(0x07f20311) /* 0.496584955 */, 17 },
- /* 4076 */ { MAD_F(0x07f2ad72) /* 0.496747444 */, 17 },
- /* 4077 */ { MAD_F(0x07f357d8) /* 0.496909945 */, 17 },
- /* 4078 */ { MAD_F(0x07f40240) /* 0.497072460 */, 17 },
- /* 4079 */ { MAD_F(0x07f4acad) /* 0.497234989 */, 17 },
-
- /* 4080 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 17 },
- /* 4081 */ { MAD_F(0x07f60190) /* 0.497560085 */, 17 },
- /* 4082 */ { MAD_F(0x07f6ac07) /* 0.497722653 */, 17 },
- /* 4083 */ { MAD_F(0x07f75682) /* 0.497885235 */, 17 },
- /* 4084 */ { MAD_F(0x07f80100) /* 0.498047829 */, 17 },
- /* 4085 */ { MAD_F(0x07f8ab82) /* 0.498210437 */, 17 },
- /* 4086 */ { MAD_F(0x07f95607) /* 0.498373058 */, 17 },
- /* 4087 */ { MAD_F(0x07fa0090) /* 0.498535693 */, 17 },
- /* 4088 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 17 },
- /* 4089 */ { MAD_F(0x07fb55ac) /* 0.498861002 */, 17 },
- /* 4090 */ { MAD_F(0x07fc0040) /* 0.499023676 */, 17 },
- /* 4091 */ { MAD_F(0x07fcaad7) /* 0.499186364 */, 17 },
- /* 4092 */ { MAD_F(0x07fd5572) /* 0.499349064 */, 17 },
- /* 4093 */ { MAD_F(0x07fe0010) /* 0.499511778 */, 17 },
- /* 4094 */ { MAD_F(0x07feaab2) /* 0.499674506 */, 17 },
- /* 4095 */ { MAD_F(0x07ff5557) /* 0.499837246 */, 17 },
-
- /* 4096 */ { MAD_F(0x04000000) /* 0.250000000 */, 18 },
- /* 4097 */ { MAD_F(0x04005556) /* 0.250081384 */, 18 },
- /* 4098 */ { MAD_F(0x0400aaae) /* 0.250162774 */, 18 },
- /* 4099 */ { MAD_F(0x04010008) /* 0.250244170 */, 18 },
- /* 4100 */ { MAD_F(0x04015563) /* 0.250325574 */, 18 },
- /* 4101 */ { MAD_F(0x0401aac1) /* 0.250406984 */, 18 },
- /* 4102 */ { MAD_F(0x04020020) /* 0.250488400 */, 18 },
- /* 4103 */ { MAD_F(0x04025581) /* 0.250569824 */, 18 },
- /* 4104 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 18 },
- /* 4105 */ { MAD_F(0x04030048) /* 0.250732690 */, 18 },
- /* 4106 */ { MAD_F(0x040355ae) /* 0.250814133 */, 18 },
- /* 4107 */ { MAD_F(0x0403ab16) /* 0.250895583 */, 18 },
- /* 4108 */ { MAD_F(0x04040080) /* 0.250977039 */, 18 },
- /* 4109 */ { MAD_F(0x040455eb) /* 0.251058502 */, 18 },
- /* 4110 */ { MAD_F(0x0404ab59) /* 0.251139971 */, 18 },
- /* 4111 */ { MAD_F(0x040500c8) /* 0.251221448 */, 18 },
-
- /* 4112 */ { MAD_F(0x04055638) /* 0.251302930 */, 18 },
- /* 4113 */ { MAD_F(0x0405abab) /* 0.251384420 */, 18 },
- /* 4114 */ { MAD_F(0x0406011f) /* 0.251465916 */, 18 },
- /* 4115 */ { MAD_F(0x04065696) /* 0.251547418 */, 18 },
- /* 4116 */ { MAD_F(0x0406ac0e) /* 0.251628927 */, 18 },
- /* 4117 */ { MAD_F(0x04070187) /* 0.251710443 */, 18 },
- /* 4118 */ { MAD_F(0x04075703) /* 0.251791965 */, 18 },
- /* 4119 */ { MAD_F(0x0407ac80) /* 0.251873494 */, 18 },
- /* 4120 */ { MAD_F(0x040801ff) /* 0.251955030 */, 18 },
- /* 4121 */ { MAD_F(0x04085780) /* 0.252036572 */, 18 },
- /* 4122 */ { MAD_F(0x0408ad02) /* 0.252118121 */, 18 },
- /* 4123 */ { MAD_F(0x04090287) /* 0.252199676 */, 18 },
- /* 4124 */ { MAD_F(0x0409580d) /* 0.252281238 */, 18 },
- /* 4125 */ { MAD_F(0x0409ad95) /* 0.252362807 */, 18 },
- /* 4126 */ { MAD_F(0x040a031e) /* 0.252444382 */, 18 },
- /* 4127 */ { MAD_F(0x040a58aa) /* 0.252525963 */, 18 },
-
- /* 4128 */ { MAD_F(0x040aae37) /* 0.252607552 */, 18 },
- /* 4129 */ { MAD_F(0x040b03c6) /* 0.252689147 */, 18 },
- /* 4130 */ { MAD_F(0x040b5957) /* 0.252770748 */, 18 },
- /* 4131 */ { MAD_F(0x040baee9) /* 0.252852356 */, 18 },
- /* 4132 */ { MAD_F(0x040c047e) /* 0.252933971 */, 18 },
- /* 4133 */ { MAD_F(0x040c5a14) /* 0.253015592 */, 18 },
- /* 4134 */ { MAD_F(0x040cafab) /* 0.253097220 */, 18 },
- /* 4135 */ { MAD_F(0x040d0545) /* 0.253178854 */, 18 },
- /* 4136 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 18 },
- /* 4137 */ { MAD_F(0x040db07d) /* 0.253342143 */, 18 },
- /* 4138 */ { MAD_F(0x040e061c) /* 0.253423797 */, 18 },
- /* 4139 */ { MAD_F(0x040e5bbd) /* 0.253505457 */, 18 },
- /* 4140 */ { MAD_F(0x040eb15f) /* 0.253587125 */, 18 },
- /* 4141 */ { MAD_F(0x040f0703) /* 0.253668799 */, 18 },
- /* 4142 */ { MAD_F(0x040f5ca9) /* 0.253750479 */, 18 },
- /* 4143 */ { MAD_F(0x040fb251) /* 0.253832166 */, 18 },
-
- /* 4144 */ { MAD_F(0x041007fa) /* 0.253913860 */, 18 },
- /* 4145 */ { MAD_F(0x04105da6) /* 0.253995560 */, 18 },
- /* 4146 */ { MAD_F(0x0410b353) /* 0.254077266 */, 18 },
- /* 4147 */ { MAD_F(0x04110901) /* 0.254158980 */, 18 },
- /* 4148 */ { MAD_F(0x04115eb2) /* 0.254240700 */, 18 },
- /* 4149 */ { MAD_F(0x0411b464) /* 0.254322426 */, 18 },
- /* 4150 */ { MAD_F(0x04120a18) /* 0.254404159 */, 18 },
- /* 4151 */ { MAD_F(0x04125fce) /* 0.254485899 */, 18 },
- /* 4152 */ { MAD_F(0x0412b586) /* 0.254567645 */, 18 },
- /* 4153 */ { MAD_F(0x04130b3f) /* 0.254649397 */, 18 },
- /* 4154 */ { MAD_F(0x041360fa) /* 0.254731157 */, 18 },
- /* 4155 */ { MAD_F(0x0413b6b7) /* 0.254812922 */, 18 },
- /* 4156 */ { MAD_F(0x04140c75) /* 0.254894695 */, 18 },
- /* 4157 */ { MAD_F(0x04146236) /* 0.254976474 */, 18 },
- /* 4158 */ { MAD_F(0x0414b7f8) /* 0.255058259 */, 18 },
- /* 4159 */ { MAD_F(0x04150dbc) /* 0.255140051 */, 18 },
-
- /* 4160 */ { MAD_F(0x04156381) /* 0.255221850 */, 18 },
- /* 4161 */ { MAD_F(0x0415b949) /* 0.255303655 */, 18 },
- /* 4162 */ { MAD_F(0x04160f12) /* 0.255385467 */, 18 },
- /* 4163 */ { MAD_F(0x041664dd) /* 0.255467285 */, 18 },
- /* 4164 */ { MAD_F(0x0416baaa) /* 0.255549110 */, 18 },
- /* 4165 */ { MAD_F(0x04171078) /* 0.255630941 */, 18 },
- /* 4166 */ { MAD_F(0x04176648) /* 0.255712779 */, 18 },
- /* 4167 */ { MAD_F(0x0417bc1a) /* 0.255794624 */, 18 },
- /* 4168 */ { MAD_F(0x041811ee) /* 0.255876475 */, 18 },
- /* 4169 */ { MAD_F(0x041867c3) /* 0.255958332 */, 18 },
- /* 4170 */ { MAD_F(0x0418bd9b) /* 0.256040196 */, 18 },
- /* 4171 */ { MAD_F(0x04191374) /* 0.256122067 */, 18 },
- /* 4172 */ { MAD_F(0x0419694e) /* 0.256203944 */, 18 },
- /* 4173 */ { MAD_F(0x0419bf2b) /* 0.256285828 */, 18 },
- /* 4174 */ { MAD_F(0x041a1509) /* 0.256367718 */, 18 },
- /* 4175 */ { MAD_F(0x041a6ae9) /* 0.256449615 */, 18 },
-
- /* 4176 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 18 },
- /* 4177 */ { MAD_F(0x041b16ae) /* 0.256613428 */, 18 },
- /* 4178 */ { MAD_F(0x041b6c94) /* 0.256695344 */, 18 },
- /* 4179 */ { MAD_F(0x041bc27b) /* 0.256777267 */, 18 },
- /* 4180 */ { MAD_F(0x041c1863) /* 0.256859197 */, 18 },
- /* 4181 */ { MAD_F(0x041c6e4e) /* 0.256941133 */, 18 },
- /* 4182 */ { MAD_F(0x041cc43a) /* 0.257023076 */, 18 },
- /* 4183 */ { MAD_F(0x041d1a28) /* 0.257105025 */, 18 },
- /* 4184 */ { MAD_F(0x041d7018) /* 0.257186980 */, 18 },
- /* 4185 */ { MAD_F(0x041dc60a) /* 0.257268942 */, 18 },
- /* 4186 */ { MAD_F(0x041e1bfd) /* 0.257350911 */, 18 },
- /* 4187 */ { MAD_F(0x041e71f2) /* 0.257432886 */, 18 },
- /* 4188 */ { MAD_F(0x041ec7e9) /* 0.257514868 */, 18 },
- /* 4189 */ { MAD_F(0x041f1de1) /* 0.257596856 */, 18 },
- /* 4190 */ { MAD_F(0x041f73dc) /* 0.257678851 */, 18 },
- /* 4191 */ { MAD_F(0x041fc9d8) /* 0.257760852 */, 18 },
-
- /* 4192 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 18 },
- /* 4193 */ { MAD_F(0x042075d5) /* 0.257924875 */, 18 },
- /* 4194 */ { MAD_F(0x0420cbd6) /* 0.258006895 */, 18 },
- /* 4195 */ { MAD_F(0x042121d9) /* 0.258088923 */, 18 },
- /* 4196 */ { MAD_F(0x042177de) /* 0.258170957 */, 18 },
- /* 4197 */ { MAD_F(0x0421cde5) /* 0.258252997 */, 18 },
- /* 4198 */ { MAD_F(0x042223ed) /* 0.258335044 */, 18 },
- /* 4199 */ { MAD_F(0x042279f7) /* 0.258417097 */, 18 },
- /* 4200 */ { MAD_F(0x0422d003) /* 0.258499157 */, 18 },
- /* 4201 */ { MAD_F(0x04232611) /* 0.258581224 */, 18 },
- /* 4202 */ { MAD_F(0x04237c20) /* 0.258663297 */, 18 },
- /* 4203 */ { MAD_F(0x0423d231) /* 0.258745376 */, 18 },
- /* 4204 */ { MAD_F(0x04242844) /* 0.258827462 */, 18 },
- /* 4205 */ { MAD_F(0x04247e58) /* 0.258909555 */, 18 },
- /* 4206 */ { MAD_F(0x0424d46e) /* 0.258991654 */, 18 },
- /* 4207 */ { MAD_F(0x04252a87) /* 0.259073760 */, 18 },
-
- /* 4208 */ { MAD_F(0x042580a0) /* 0.259155872 */, 18 },
- /* 4209 */ { MAD_F(0x0425d6bc) /* 0.259237990 */, 18 },
- /* 4210 */ { MAD_F(0x04262cd9) /* 0.259320115 */, 18 },
- /* 4211 */ { MAD_F(0x042682f8) /* 0.259402247 */, 18 },
- /* 4212 */ { MAD_F(0x0426d919) /* 0.259484385 */, 18 },
- /* 4213 */ { MAD_F(0x04272f3b) /* 0.259566529 */, 18 },
- /* 4214 */ { MAD_F(0x04278560) /* 0.259648680 */, 18 },
- /* 4215 */ { MAD_F(0x0427db86) /* 0.259730838 */, 18 },
- /* 4216 */ { MAD_F(0x042831ad) /* 0.259813002 */, 18 },
- /* 4217 */ { MAD_F(0x042887d7) /* 0.259895173 */, 18 },
- /* 4218 */ { MAD_F(0x0428de02) /* 0.259977350 */, 18 },
- /* 4219 */ { MAD_F(0x0429342f) /* 0.260059533 */, 18 },
- /* 4220 */ { MAD_F(0x04298a5e) /* 0.260141723 */, 18 },
- /* 4221 */ { MAD_F(0x0429e08e) /* 0.260223920 */, 18 },
- /* 4222 */ { MAD_F(0x042a36c0) /* 0.260306123 */, 18 },
- /* 4223 */ { MAD_F(0x042a8cf4) /* 0.260388332 */, 18 },
-
- /* 4224 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 18 },
- /* 4225 */ { MAD_F(0x042b3962) /* 0.260552771 */, 18 },
- /* 4226 */ { MAD_F(0x042b8f9b) /* 0.260635000 */, 18 },
- /* 4227 */ { MAD_F(0x042be5d6) /* 0.260717235 */, 18 },
- /* 4228 */ { MAD_F(0x042c3c12) /* 0.260799477 */, 18 },
- /* 4229 */ { MAD_F(0x042c9251) /* 0.260881725 */, 18 },
- /* 4230 */ { MAD_F(0x042ce891) /* 0.260963980 */, 18 },
- /* 4231 */ { MAD_F(0x042d3ed3) /* 0.261046242 */, 18 },
- /* 4232 */ { MAD_F(0x042d9516) /* 0.261128510 */, 18 },
- /* 4233 */ { MAD_F(0x042deb5c) /* 0.261210784 */, 18 },
- /* 4234 */ { MAD_F(0x042e41a3) /* 0.261293065 */, 18 },
- /* 4235 */ { MAD_F(0x042e97ec) /* 0.261375352 */, 18 },
- /* 4236 */ { MAD_F(0x042eee36) /* 0.261457646 */, 18 },
- /* 4237 */ { MAD_F(0x042f4482) /* 0.261539946 */, 18 },
- /* 4238 */ { MAD_F(0x042f9ad1) /* 0.261622253 */, 18 },
- /* 4239 */ { MAD_F(0x042ff120) /* 0.261704566 */, 18 },
-
- /* 4240 */ { MAD_F(0x04304772) /* 0.261786886 */, 18 },
- /* 4241 */ { MAD_F(0x04309dc5) /* 0.261869212 */, 18 },
- /* 4242 */ { MAD_F(0x0430f41a) /* 0.261951545 */, 18 },
- /* 4243 */ { MAD_F(0x04314a71) /* 0.262033884 */, 18 },
- /* 4244 */ { MAD_F(0x0431a0c9) /* 0.262116229 */, 18 },
- /* 4245 */ { MAD_F(0x0431f723) /* 0.262198581 */, 18 },
- /* 4246 */ { MAD_F(0x04324d7f) /* 0.262280940 */, 18 },
- /* 4247 */ { MAD_F(0x0432a3dd) /* 0.262363305 */, 18 },
- /* 4248 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 18 },
- /* 4249 */ { MAD_F(0x0433509e) /* 0.262528054 */, 18 },
- /* 4250 */ { MAD_F(0x0433a701) /* 0.262610438 */, 18 },
- /* 4251 */ { MAD_F(0x0433fd65) /* 0.262692829 */, 18 },
- /* 4252 */ { MAD_F(0x043453cc) /* 0.262775227 */, 18 },
- /* 4253 */ { MAD_F(0x0434aa34) /* 0.262857630 */, 18 },
- /* 4254 */ { MAD_F(0x0435009d) /* 0.262940040 */, 18 },
- /* 4255 */ { MAD_F(0x04355709) /* 0.263022457 */, 18 },
-
- /* 4256 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 18 },
- /* 4257 */ { MAD_F(0x043603e5) /* 0.263187310 */, 18 },
- /* 4258 */ { MAD_F(0x04365a56) /* 0.263269746 */, 18 },
- /* 4259 */ { MAD_F(0x0436b0c9) /* 0.263352188 */, 18 },
- /* 4260 */ { MAD_F(0x0437073d) /* 0.263434637 */, 18 },
- /* 4261 */ { MAD_F(0x04375db3) /* 0.263517093 */, 18 },
- /* 4262 */ { MAD_F(0x0437b42a) /* 0.263599554 */, 18 },
- /* 4263 */ { MAD_F(0x04380aa4) /* 0.263682023 */, 18 },
- /* 4264 */ { MAD_F(0x0438611f) /* 0.263764497 */, 18 },
- /* 4265 */ { MAD_F(0x0438b79c) /* 0.263846979 */, 18 },
- /* 4266 */ { MAD_F(0x04390e1a) /* 0.263929466 */, 18 },
- /* 4267 */ { MAD_F(0x0439649b) /* 0.264011960 */, 18 },
- /* 4268 */ { MAD_F(0x0439bb1d) /* 0.264094461 */, 18 },
- /* 4269 */ { MAD_F(0x043a11a1) /* 0.264176968 */, 18 },
- /* 4270 */ { MAD_F(0x043a6826) /* 0.264259481 */, 18 },
- /* 4271 */ { MAD_F(0x043abead) /* 0.264342001 */, 18 },
-
- /* 4272 */ { MAD_F(0x043b1536) /* 0.264424527 */, 18 },
- /* 4273 */ { MAD_F(0x043b6bc1) /* 0.264507060 */, 18 },
- /* 4274 */ { MAD_F(0x043bc24d) /* 0.264589599 */, 18 },
- /* 4275 */ { MAD_F(0x043c18dc) /* 0.264672145 */, 18 },
- /* 4276 */ { MAD_F(0x043c6f6c) /* 0.264754697 */, 18 },
- /* 4277 */ { MAD_F(0x043cc5fd) /* 0.264837255 */, 18 },
- /* 4278 */ { MAD_F(0x043d1c91) /* 0.264919820 */, 18 },
- /* 4279 */ { MAD_F(0x043d7326) /* 0.265002392 */, 18 },
- /* 4280 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 18 },
- /* 4281 */ { MAD_F(0x043e2055) /* 0.265167554 */, 18 },
- /* 4282 */ { MAD_F(0x043e76ef) /* 0.265250144 */, 18 },
- /* 4283 */ { MAD_F(0x043ecd8b) /* 0.265332741 */, 18 },
- /* 4284 */ { MAD_F(0x043f2429) /* 0.265415345 */, 18 },
- /* 4285 */ { MAD_F(0x043f7ac8) /* 0.265497955 */, 18 },
- /* 4286 */ { MAD_F(0x043fd169) /* 0.265580571 */, 18 },
- /* 4287 */ { MAD_F(0x0440280c) /* 0.265663194 */, 18 },
-
- /* 4288 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 18 },
- /* 4289 */ { MAD_F(0x0440d557) /* 0.265828459 */, 18 },
- /* 4290 */ { MAD_F(0x04412bff) /* 0.265911101 */, 18 },
- /* 4291 */ { MAD_F(0x044182a9) /* 0.265993749 */, 18 },
- /* 4292 */ { MAD_F(0x0441d955) /* 0.266076404 */, 18 },
- /* 4293 */ { MAD_F(0x04423002) /* 0.266159065 */, 18 },
- /* 4294 */ { MAD_F(0x044286b1) /* 0.266241733 */, 18 },
- /* 4295 */ { MAD_F(0x0442dd61) /* 0.266324407 */, 18 },
- /* 4296 */ { MAD_F(0x04433414) /* 0.266407088 */, 18 },
- /* 4297 */ { MAD_F(0x04438ac8) /* 0.266489775 */, 18 },
- /* 4298 */ { MAD_F(0x0443e17e) /* 0.266572468 */, 18 },
- /* 4299 */ { MAD_F(0x04443835) /* 0.266655168 */, 18 },
- /* 4300 */ { MAD_F(0x04448eef) /* 0.266737874 */, 18 },
- /* 4301 */ { MAD_F(0x0444e5aa) /* 0.266820587 */, 18 },
- /* 4302 */ { MAD_F(0x04453c66) /* 0.266903306 */, 18 },
- /* 4303 */ { MAD_F(0x04459325) /* 0.266986031 */, 18 },
-
- /* 4304 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 18 },
- /* 4305 */ { MAD_F(0x044640a7) /* 0.267151501 */, 18 },
- /* 4306 */ { MAD_F(0x0446976a) /* 0.267234246 */, 18 },
- /* 4307 */ { MAD_F(0x0446ee30) /* 0.267316997 */, 18 },
- /* 4308 */ { MAD_F(0x044744f7) /* 0.267399755 */, 18 },
- /* 4309 */ { MAD_F(0x04479bc0) /* 0.267482518 */, 18 },
- /* 4310 */ { MAD_F(0x0447f28a) /* 0.267565289 */, 18 },
- /* 4311 */ { MAD_F(0x04484956) /* 0.267648065 */, 18 },
- /* 4312 */ { MAD_F(0x0448a024) /* 0.267730848 */, 18 },
- /* 4313 */ { MAD_F(0x0448f6f4) /* 0.267813638 */, 18 },
- /* 4314 */ { MAD_F(0x04494dc5) /* 0.267896434 */, 18 },
- /* 4315 */ { MAD_F(0x0449a498) /* 0.267979236 */, 18 },
- /* 4316 */ { MAD_F(0x0449fb6d) /* 0.268062045 */, 18 },
- /* 4317 */ { MAD_F(0x044a5243) /* 0.268144860 */, 18 },
- /* 4318 */ { MAD_F(0x044aa91c) /* 0.268227681 */, 18 },
- /* 4319 */ { MAD_F(0x044afff6) /* 0.268310509 */, 18 },
-
- /* 4320 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 18 },
- /* 4321 */ { MAD_F(0x044badaf) /* 0.268476184 */, 18 },
- /* 4322 */ { MAD_F(0x044c048e) /* 0.268559031 */, 18 },
- /* 4323 */ { MAD_F(0x044c5b6f) /* 0.268641885 */, 18 },
- /* 4324 */ { MAD_F(0x044cb251) /* 0.268724744 */, 18 },
- /* 4325 */ { MAD_F(0x044d0935) /* 0.268807611 */, 18 },
- /* 4326 */ { MAD_F(0x044d601b) /* 0.268890483 */, 18 },
- /* 4327 */ { MAD_F(0x044db703) /* 0.268973362 */, 18 },
- /* 4328 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 18 },
- /* 4329 */ { MAD_F(0x044e64d7) /* 0.269139139 */, 18 },
- /* 4330 */ { MAD_F(0x044ebbc4) /* 0.269222037 */, 18 },
- /* 4331 */ { MAD_F(0x044f12b3) /* 0.269304942 */, 18 },
- /* 4332 */ { MAD_F(0x044f69a3) /* 0.269387853 */, 18 },
- /* 4333 */ { MAD_F(0x044fc095) /* 0.269470770 */, 18 },
- /* 4334 */ { MAD_F(0x04501788) /* 0.269553694 */, 18 },
- /* 4335 */ { MAD_F(0x04506e7e) /* 0.269636624 */, 18 },
-
- /* 4336 */ { MAD_F(0x0450c575) /* 0.269719560 */, 18 },
- /* 4337 */ { MAD_F(0x04511c6e) /* 0.269802503 */, 18 },
- /* 4338 */ { MAD_F(0x04517368) /* 0.269885452 */, 18 },
- /* 4339 */ { MAD_F(0x0451ca64) /* 0.269968408 */, 18 },
- /* 4340 */ { MAD_F(0x04522162) /* 0.270051370 */, 18 },
- /* 4341 */ { MAD_F(0x04527862) /* 0.270134338 */, 18 },
- /* 4342 */ { MAD_F(0x0452cf63) /* 0.270217312 */, 18 },
- /* 4343 */ { MAD_F(0x04532666) /* 0.270300293 */, 18 },
- /* 4344 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 18 },
- /* 4345 */ { MAD_F(0x0453d472) /* 0.270466275 */, 18 },
- /* 4346 */ { MAD_F(0x04542b7a) /* 0.270549275 */, 18 },
- /* 4347 */ { MAD_F(0x04548284) /* 0.270632281 */, 18 },
- /* 4348 */ { MAD_F(0x0454d98f) /* 0.270715294 */, 18 },
- /* 4349 */ { MAD_F(0x0455309c) /* 0.270798313 */, 18 },
- /* 4350 */ { MAD_F(0x045587ab) /* 0.270881339 */, 18 },
- /* 4351 */ { MAD_F(0x0455debc) /* 0.270964371 */, 18 },
-
- /* 4352 */ { MAD_F(0x045635cf) /* 0.271047409 */, 18 },
- /* 4353 */ { MAD_F(0x04568ce3) /* 0.271130454 */, 18 },
- /* 4354 */ { MAD_F(0x0456e3f9) /* 0.271213505 */, 18 },
- /* 4355 */ { MAD_F(0x04573b10) /* 0.271296562 */, 18 },
- /* 4356 */ { MAD_F(0x04579229) /* 0.271379626 */, 18 },
- /* 4357 */ { MAD_F(0x0457e944) /* 0.271462696 */, 18 },
- /* 4358 */ { MAD_F(0x04584061) /* 0.271545772 */, 18 },
- /* 4359 */ { MAD_F(0x0458977f) /* 0.271628855 */, 18 },
- /* 4360 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 18 },
- /* 4361 */ { MAD_F(0x045945c1) /* 0.271795040 */, 18 },
- /* 4362 */ { MAD_F(0x04599ce5) /* 0.271878142 */, 18 },
- /* 4363 */ { MAD_F(0x0459f40a) /* 0.271961250 */, 18 },
- /* 4364 */ { MAD_F(0x045a4b31) /* 0.272044365 */, 18 },
- /* 4365 */ { MAD_F(0x045aa259) /* 0.272127486 */, 18 },
- /* 4366 */ { MAD_F(0x045af984) /* 0.272210613 */, 18 },
- /* 4367 */ { MAD_F(0x045b50b0) /* 0.272293746 */, 18 },
-
- /* 4368 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 18 },
- /* 4369 */ { MAD_F(0x045bff0d) /* 0.272460033 */, 18 },
- /* 4370 */ { MAD_F(0x045c563e) /* 0.272543185 */, 18 },
- /* 4371 */ { MAD_F(0x045cad71) /* 0.272626344 */, 18 },
- /* 4372 */ { MAD_F(0x045d04a5) /* 0.272709510 */, 18 },
- /* 4373 */ { MAD_F(0x045d5bdc) /* 0.272792681 */, 18 },
- /* 4374 */ { MAD_F(0x045db313) /* 0.272875859 */, 18 },
- /* 4375 */ { MAD_F(0x045e0a4d) /* 0.272959044 */, 18 },
- /* 4376 */ { MAD_F(0x045e6188) /* 0.273042234 */, 18 },
- /* 4377 */ { MAD_F(0x045eb8c5) /* 0.273125431 */, 18 },
- /* 4378 */ { MAD_F(0x045f1004) /* 0.273208635 */, 18 },
- /* 4379 */ { MAD_F(0x045f6745) /* 0.273291844 */, 18 },
- /* 4380 */ { MAD_F(0x045fbe87) /* 0.273375060 */, 18 },
- /* 4381 */ { MAD_F(0x046015cb) /* 0.273458283 */, 18 },
- /* 4382 */ { MAD_F(0x04606d10) /* 0.273541511 */, 18 },
- /* 4383 */ { MAD_F(0x0460c457) /* 0.273624747 */, 18 },
-
- /* 4384 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 18 },
- /* 4385 */ { MAD_F(0x046172eb) /* 0.273791236 */, 18 },
- /* 4386 */ { MAD_F(0x0461ca37) /* 0.273874490 */, 18 },
- /* 4387 */ { MAD_F(0x04622185) /* 0.273957750 */, 18 },
- /* 4388 */ { MAD_F(0x046278d5) /* 0.274041017 */, 18 },
- /* 4389 */ { MAD_F(0x0462d026) /* 0.274124290 */, 18 },
- /* 4390 */ { MAD_F(0x0463277a) /* 0.274207569 */, 18 },
- /* 4391 */ { MAD_F(0x04637ece) /* 0.274290855 */, 18 },
- /* 4392 */ { MAD_F(0x0463d625) /* 0.274374147 */, 18 },
- /* 4393 */ { MAD_F(0x04642d7d) /* 0.274457445 */, 18 },
- /* 4394 */ { MAD_F(0x046484d7) /* 0.274540749 */, 18 },
- /* 4395 */ { MAD_F(0x0464dc33) /* 0.274624060 */, 18 },
- /* 4396 */ { MAD_F(0x04653390) /* 0.274707378 */, 18 },
- /* 4397 */ { MAD_F(0x04658aef) /* 0.274790701 */, 18 },
- /* 4398 */ { MAD_F(0x0465e250) /* 0.274874031 */, 18 },
- /* 4399 */ { MAD_F(0x046639b2) /* 0.274957367 */, 18 },
-
- /* 4400 */ { MAD_F(0x04669116) /* 0.275040710 */, 18 },
- /* 4401 */ { MAD_F(0x0466e87c) /* 0.275124059 */, 18 },
- /* 4402 */ { MAD_F(0x04673fe3) /* 0.275207414 */, 18 },
- /* 4403 */ { MAD_F(0x0467974d) /* 0.275290775 */, 18 },
- /* 4404 */ { MAD_F(0x0467eeb7) /* 0.275374143 */, 18 },
- /* 4405 */ { MAD_F(0x04684624) /* 0.275457517 */, 18 },
- /* 4406 */ { MAD_F(0x04689d92) /* 0.275540897 */, 18 },
- /* 4407 */ { MAD_F(0x0468f502) /* 0.275624284 */, 18 },
- /* 4408 */ { MAD_F(0x04694c74) /* 0.275707677 */, 18 },
- /* 4409 */ { MAD_F(0x0469a3e7) /* 0.275791076 */, 18 },
- /* 4410 */ { MAD_F(0x0469fb5c) /* 0.275874482 */, 18 },
- /* 4411 */ { MAD_F(0x046a52d3) /* 0.275957894 */, 18 },
- /* 4412 */ { MAD_F(0x046aaa4b) /* 0.276041312 */, 18 },
- /* 4413 */ { MAD_F(0x046b01c5) /* 0.276124737 */, 18 },
- /* 4414 */ { MAD_F(0x046b5941) /* 0.276208167 */, 18 },
- /* 4415 */ { MAD_F(0x046bb0bf) /* 0.276291605 */, 18 },
-
- /* 4416 */ { MAD_F(0x046c083e) /* 0.276375048 */, 18 },
- /* 4417 */ { MAD_F(0x046c5fbf) /* 0.276458498 */, 18 },
- /* 4418 */ { MAD_F(0x046cb741) /* 0.276541954 */, 18 },
- /* 4419 */ { MAD_F(0x046d0ec5) /* 0.276625416 */, 18 },
- /* 4420 */ { MAD_F(0x046d664b) /* 0.276708885 */, 18 },
- /* 4421 */ { MAD_F(0x046dbdd3) /* 0.276792360 */, 18 },
- /* 4422 */ { MAD_F(0x046e155c) /* 0.276875841 */, 18 },
- /* 4423 */ { MAD_F(0x046e6ce7) /* 0.276959328 */, 18 },
- /* 4424 */ { MAD_F(0x046ec474) /* 0.277042822 */, 18 },
- /* 4425 */ { MAD_F(0x046f1c02) /* 0.277126322 */, 18 },
- /* 4426 */ { MAD_F(0x046f7392) /* 0.277209829 */, 18 },
- /* 4427 */ { MAD_F(0x046fcb24) /* 0.277293341 */, 18 },
- /* 4428 */ { MAD_F(0x047022b8) /* 0.277376860 */, 18 },
- /* 4429 */ { MAD_F(0x04707a4d) /* 0.277460385 */, 18 },
- /* 4430 */ { MAD_F(0x0470d1e4) /* 0.277543917 */, 18 },
- /* 4431 */ { MAD_F(0x0471297c) /* 0.277627455 */, 18 },
-
- /* 4432 */ { MAD_F(0x04718116) /* 0.277710999 */, 18 },
- /* 4433 */ { MAD_F(0x0471d8b2) /* 0.277794549 */, 18 },
- /* 4434 */ { MAD_F(0x04723050) /* 0.277878106 */, 18 },
- /* 4435 */ { MAD_F(0x047287ef) /* 0.277961669 */, 18 },
- /* 4436 */ { MAD_F(0x0472df90) /* 0.278045238 */, 18 },
- /* 4437 */ { MAD_F(0x04733733) /* 0.278128813 */, 18 },
- /* 4438 */ { MAD_F(0x04738ed7) /* 0.278212395 */, 18 },
- /* 4439 */ { MAD_F(0x0473e67d) /* 0.278295983 */, 18 },
- /* 4440 */ { MAD_F(0x04743e25) /* 0.278379578 */, 18 },
- /* 4441 */ { MAD_F(0x047495ce) /* 0.278463178 */, 18 },
- /* 4442 */ { MAD_F(0x0474ed79) /* 0.278546785 */, 18 },
- /* 4443 */ { MAD_F(0x04754526) /* 0.278630398 */, 18 },
- /* 4444 */ { MAD_F(0x04759cd4) /* 0.278714018 */, 18 },
- /* 4445 */ { MAD_F(0x0475f484) /* 0.278797643 */, 18 },
- /* 4446 */ { MAD_F(0x04764c36) /* 0.278881275 */, 18 },
- /* 4447 */ { MAD_F(0x0476a3ea) /* 0.278964914 */, 18 },
-
- /* 4448 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 18 },
- /* 4449 */ { MAD_F(0x04775356) /* 0.279132209 */, 18 },
- /* 4450 */ { MAD_F(0x0477ab0e) /* 0.279215866 */, 18 },
- /* 4451 */ { MAD_F(0x047802c8) /* 0.279299529 */, 18 },
- /* 4452 */ { MAD_F(0x04785a84) /* 0.279383199 */, 18 },
- /* 4453 */ { MAD_F(0x0478b242) /* 0.279466875 */, 18 },
- /* 4454 */ { MAD_F(0x04790a01) /* 0.279550557 */, 18 },
- /* 4455 */ { MAD_F(0x047961c2) /* 0.279634245 */, 18 },
- /* 4456 */ { MAD_F(0x0479b984) /* 0.279717940 */, 18 },
- /* 4457 */ { MAD_F(0x047a1149) /* 0.279801641 */, 18 },
- /* 4458 */ { MAD_F(0x047a690f) /* 0.279885348 */, 18 },
- /* 4459 */ { MAD_F(0x047ac0d6) /* 0.279969061 */, 18 },
- /* 4460 */ { MAD_F(0x047b18a0) /* 0.280052781 */, 18 },
- /* 4461 */ { MAD_F(0x047b706b) /* 0.280136507 */, 18 },
- /* 4462 */ { MAD_F(0x047bc837) /* 0.280220239 */, 18 },
- /* 4463 */ { MAD_F(0x047c2006) /* 0.280303978 */, 18 },
-
- /* 4464 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 18 },
- /* 4465 */ { MAD_F(0x047ccfa8) /* 0.280471473 */, 18 },
- /* 4466 */ { MAD_F(0x047d277b) /* 0.280555230 */, 18 },
- /* 4467 */ { MAD_F(0x047d7f50) /* 0.280638994 */, 18 },
- /* 4468 */ { MAD_F(0x047dd727) /* 0.280722764 */, 18 },
- /* 4469 */ { MAD_F(0x047e2eff) /* 0.280806540 */, 18 },
- /* 4470 */ { MAD_F(0x047e86d9) /* 0.280890322 */, 18 },
- /* 4471 */ { MAD_F(0x047edeb5) /* 0.280974110 */, 18 },
- /* 4472 */ { MAD_F(0x047f3693) /* 0.281057905 */, 18 },
- /* 4473 */ { MAD_F(0x047f8e72) /* 0.281141706 */, 18 },
- /* 4474 */ { MAD_F(0x047fe653) /* 0.281225513 */, 18 },
- /* 4475 */ { MAD_F(0x04803e35) /* 0.281309326 */, 18 },
- /* 4476 */ { MAD_F(0x04809619) /* 0.281393146 */, 18 },
- /* 4477 */ { MAD_F(0x0480edff) /* 0.281476972 */, 18 },
- /* 4478 */ { MAD_F(0x048145e7) /* 0.281560804 */, 18 },
- /* 4479 */ { MAD_F(0x04819dd0) /* 0.281644643 */, 18 },
-
- /* 4480 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 18 },
- /* 4481 */ { MAD_F(0x04824da7) /* 0.281812338 */, 18 },
- /* 4482 */ { MAD_F(0x0482a595) /* 0.281896195 */, 18 },
- /* 4483 */ { MAD_F(0x0482fd85) /* 0.281980059 */, 18 },
- /* 4484 */ { MAD_F(0x04835577) /* 0.282063928 */, 18 },
- /* 4485 */ { MAD_F(0x0483ad6a) /* 0.282147804 */, 18 },
- /* 4486 */ { MAD_F(0x0484055f) /* 0.282231686 */, 18 },
- /* 4487 */ { MAD_F(0x04845d56) /* 0.282315574 */, 18 },
- /* 4488 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 18 },
- /* 4489 */ { MAD_F(0x04850d48) /* 0.282483370 */, 18 },
- /* 4490 */ { MAD_F(0x04856544) /* 0.282567277 */, 18 },
- /* 4491 */ { MAD_F(0x0485bd41) /* 0.282651190 */, 18 },
- /* 4492 */ { MAD_F(0x04861540) /* 0.282735109 */, 18 },
- /* 4493 */ { MAD_F(0x04866d40) /* 0.282819035 */, 18 },
- /* 4494 */ { MAD_F(0x0486c543) /* 0.282902967 */, 18 },
- /* 4495 */ { MAD_F(0x04871d47) /* 0.282986905 */, 18 },
-
- /* 4496 */ { MAD_F(0x0487754c) /* 0.283070849 */, 18 },
- /* 4497 */ { MAD_F(0x0487cd54) /* 0.283154800 */, 18 },
- /* 4498 */ { MAD_F(0x0488255d) /* 0.283238757 */, 18 },
- /* 4499 */ { MAD_F(0x04887d67) /* 0.283322720 */, 18 },
- /* 4500 */ { MAD_F(0x0488d574) /* 0.283406689 */, 18 },
- /* 4501 */ { MAD_F(0x04892d82) /* 0.283490665 */, 18 },
- /* 4502 */ { MAD_F(0x04898591) /* 0.283574646 */, 18 },
- /* 4503 */ { MAD_F(0x0489dda3) /* 0.283658634 */, 18 },
- /* 4504 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 18 },
- /* 4505 */ { MAD_F(0x048a8dca) /* 0.283826629 */, 18 },
- /* 4506 */ { MAD_F(0x048ae5e1) /* 0.283910635 */, 18 },
- /* 4507 */ { MAD_F(0x048b3df9) /* 0.283994648 */, 18 },
- /* 4508 */ { MAD_F(0x048b9612) /* 0.284078667 */, 18 },
- /* 4509 */ { MAD_F(0x048bee2e) /* 0.284162692 */, 18 },
- /* 4510 */ { MAD_F(0x048c464b) /* 0.284246723 */, 18 },
- /* 4511 */ { MAD_F(0x048c9e69) /* 0.284330761 */, 18 },
-
- /* 4512 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 18 },
- /* 4513 */ { MAD_F(0x048d4eac) /* 0.284498855 */, 18 },
- /* 4514 */ { MAD_F(0x048da6cf) /* 0.284582911 */, 18 },
- /* 4515 */ { MAD_F(0x048dfef5) /* 0.284666974 */, 18 },
- /* 4516 */ { MAD_F(0x048e571c) /* 0.284751042 */, 18 },
- /* 4517 */ { MAD_F(0x048eaf44) /* 0.284835117 */, 18 },
- /* 4518 */ { MAD_F(0x048f076f) /* 0.284919198 */, 18 },
- /* 4519 */ { MAD_F(0x048f5f9b) /* 0.285003285 */, 18 },
- /* 4520 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 18 },
- /* 4521 */ { MAD_F(0x04900ff8) /* 0.285171479 */, 18 },
- /* 4522 */ { MAD_F(0x04906829) /* 0.285255584 */, 18 },
- /* 4523 */ { MAD_F(0x0490c05b) /* 0.285339697 */, 18 },
- /* 4524 */ { MAD_F(0x04911890) /* 0.285423815 */, 18 },
- /* 4525 */ { MAD_F(0x049170c6) /* 0.285507939 */, 18 },
- /* 4526 */ { MAD_F(0x0491c8fd) /* 0.285592070 */, 18 },
- /* 4527 */ { MAD_F(0x04922137) /* 0.285676207 */, 18 },
-
- /* 4528 */ { MAD_F(0x04927972) /* 0.285760350 */, 18 },
- /* 4529 */ { MAD_F(0x0492d1ae) /* 0.285844499 */, 18 },
- /* 4530 */ { MAD_F(0x049329ed) /* 0.285928655 */, 18 },
- /* 4531 */ { MAD_F(0x0493822c) /* 0.286012816 */, 18 },
- /* 4532 */ { MAD_F(0x0493da6e) /* 0.286096984 */, 18 },
- /* 4533 */ { MAD_F(0x049432b1) /* 0.286181158 */, 18 },
- /* 4534 */ { MAD_F(0x04948af6) /* 0.286265338 */, 18 },
- /* 4535 */ { MAD_F(0x0494e33d) /* 0.286349525 */, 18 },
- /* 4536 */ { MAD_F(0x04953b85) /* 0.286433717 */, 18 },
- /* 4537 */ { MAD_F(0x049593cf) /* 0.286517916 */, 18 },
- /* 4538 */ { MAD_F(0x0495ec1b) /* 0.286602121 */, 18 },
- /* 4539 */ { MAD_F(0x04964468) /* 0.286686332 */, 18 },
- /* 4540 */ { MAD_F(0x04969cb7) /* 0.286770550 */, 18 },
- /* 4541 */ { MAD_F(0x0496f508) /* 0.286854773 */, 18 },
- /* 4542 */ { MAD_F(0x04974d5a) /* 0.286939003 */, 18 },
- /* 4543 */ { MAD_F(0x0497a5ae) /* 0.287023239 */, 18 },
-
- /* 4544 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 18 },
- /* 4545 */ { MAD_F(0x0498565a) /* 0.287191729 */, 18 },
- /* 4546 */ { MAD_F(0x0498aeb3) /* 0.287275983 */, 18 },
- /* 4547 */ { MAD_F(0x0499070e) /* 0.287360244 */, 18 },
- /* 4548 */ { MAD_F(0x04995f6a) /* 0.287444511 */, 18 },
- /* 4549 */ { MAD_F(0x0499b7c8) /* 0.287528784 */, 18 },
- /* 4550 */ { MAD_F(0x049a1027) /* 0.287613063 */, 18 },
- /* 4551 */ { MAD_F(0x049a6889) /* 0.287697348 */, 18 },
- /* 4552 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 18 },
- /* 4553 */ { MAD_F(0x049b1950) /* 0.287865937 */, 18 },
- /* 4554 */ { MAD_F(0x049b71b6) /* 0.287950241 */, 18 },
- /* 4555 */ { MAD_F(0x049bca1e) /* 0.288034551 */, 18 },
- /* 4556 */ { MAD_F(0x049c2287) /* 0.288118867 */, 18 },
- /* 4557 */ { MAD_F(0x049c7af2) /* 0.288203190 */, 18 },
- /* 4558 */ { MAD_F(0x049cd35f) /* 0.288287518 */, 18 },
- /* 4559 */ { MAD_F(0x049d2bce) /* 0.288371853 */, 18 },
-
- /* 4560 */ { MAD_F(0x049d843e) /* 0.288456194 */, 18 },
- /* 4561 */ { MAD_F(0x049ddcaf) /* 0.288540541 */, 18 },
- /* 4562 */ { MAD_F(0x049e3523) /* 0.288624894 */, 18 },
- /* 4563 */ { MAD_F(0x049e8d98) /* 0.288709253 */, 18 },
- /* 4564 */ { MAD_F(0x049ee60e) /* 0.288793619 */, 18 },
- /* 4565 */ { MAD_F(0x049f3e87) /* 0.288877990 */, 18 },
- /* 4566 */ { MAD_F(0x049f9701) /* 0.288962368 */, 18 },
- /* 4567 */ { MAD_F(0x049fef7c) /* 0.289046752 */, 18 },
- /* 4568 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 18 },
- /* 4569 */ { MAD_F(0x04a0a079) /* 0.289215538 */, 18 },
- /* 4570 */ { MAD_F(0x04a0f8f9) /* 0.289299941 */, 18 },
- /* 4571 */ { MAD_F(0x04a1517c) /* 0.289384349 */, 18 },
- /* 4572 */ { MAD_F(0x04a1a9ff) /* 0.289468764 */, 18 },
- /* 4573 */ { MAD_F(0x04a20285) /* 0.289553185 */, 18 },
- /* 4574 */ { MAD_F(0x04a25b0c) /* 0.289637612 */, 18 },
- /* 4575 */ { MAD_F(0x04a2b395) /* 0.289722045 */, 18 },
-
- /* 4576 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 18 },
- /* 4577 */ { MAD_F(0x04a364ac) /* 0.289890930 */, 18 },
- /* 4578 */ { MAD_F(0x04a3bd3a) /* 0.289975382 */, 18 },
- /* 4579 */ { MAD_F(0x04a415c9) /* 0.290059840 */, 18 },
- /* 4580 */ { MAD_F(0x04a46e5a) /* 0.290144304 */, 18 },
- /* 4581 */ { MAD_F(0x04a4c6ed) /* 0.290228774 */, 18 },
- /* 4582 */ { MAD_F(0x04a51f81) /* 0.290313250 */, 18 },
- /* 4583 */ { MAD_F(0x04a57818) /* 0.290397733 */, 18 },
- /* 4584 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 18 },
- /* 4585 */ { MAD_F(0x04a62949) /* 0.290566716 */, 18 },
- /* 4586 */ { MAD_F(0x04a681e4) /* 0.290651217 */, 18 },
- /* 4587 */ { MAD_F(0x04a6da80) /* 0.290735724 */, 18 },
- /* 4588 */ { MAD_F(0x04a7331f) /* 0.290820237 */, 18 },
- /* 4589 */ { MAD_F(0x04a78bbf) /* 0.290904756 */, 18 },
- /* 4590 */ { MAD_F(0x04a7e460) /* 0.290989281 */, 18 },
- /* 4591 */ { MAD_F(0x04a83d03) /* 0.291073813 */, 18 },
-
- /* 4592 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 18 },
- /* 4593 */ { MAD_F(0x04a8ee4f) /* 0.291242894 */, 18 },
- /* 4594 */ { MAD_F(0x04a946f7) /* 0.291327444 */, 18 },
- /* 4595 */ { MAD_F(0x04a99fa1) /* 0.291412001 */, 18 },
- /* 4596 */ { MAD_F(0x04a9f84c) /* 0.291496563 */, 18 },
- /* 4597 */ { MAD_F(0x04aa50fa) /* 0.291581131 */, 18 },
- /* 4598 */ { MAD_F(0x04aaa9a8) /* 0.291665706 */, 18 },
- /* 4599 */ { MAD_F(0x04ab0259) /* 0.291750286 */, 18 },
- /* 4600 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 18 },
- /* 4601 */ { MAD_F(0x04abb3bf) /* 0.291919466 */, 18 },
- /* 4602 */ { MAD_F(0x04ac0c74) /* 0.292004065 */, 18 },
- /* 4603 */ { MAD_F(0x04ac652b) /* 0.292088670 */, 18 },
- /* 4604 */ { MAD_F(0x04acbde4) /* 0.292173281 */, 18 },
- /* 4605 */ { MAD_F(0x04ad169e) /* 0.292257899 */, 18 },
- /* 4606 */ { MAD_F(0x04ad6f5a) /* 0.292342522 */, 18 },
- /* 4607 */ { MAD_F(0x04adc818) /* 0.292427152 */, 18 },
-
- /* 4608 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 18 },
- /* 4609 */ { MAD_F(0x04ae7998) /* 0.292596430 */, 18 },
- /* 4610 */ { MAD_F(0x04aed25a) /* 0.292681078 */, 18 },
- /* 4611 */ { MAD_F(0x04af2b1e) /* 0.292765732 */, 18 },
- /* 4612 */ { MAD_F(0x04af83e4) /* 0.292850392 */, 18 },
- /* 4613 */ { MAD_F(0x04afdcac) /* 0.292935058 */, 18 },
- /* 4614 */ { MAD_F(0x04b03575) /* 0.293019731 */, 18 },
- /* 4615 */ { MAD_F(0x04b08e40) /* 0.293104409 */, 18 },
- /* 4616 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 18 },
- /* 4617 */ { MAD_F(0x04b13fda) /* 0.293273785 */, 18 },
- /* 4618 */ { MAD_F(0x04b198aa) /* 0.293358482 */, 18 },
- /* 4619 */ { MAD_F(0x04b1f17b) /* 0.293443185 */, 18 },
- /* 4620 */ { MAD_F(0x04b24a4e) /* 0.293527894 */, 18 },
- /* 4621 */ { MAD_F(0x04b2a322) /* 0.293612609 */, 18 },
- /* 4622 */ { MAD_F(0x04b2fbf9) /* 0.293697331 */, 18 },
- /* 4623 */ { MAD_F(0x04b354d1) /* 0.293782058 */, 18 },
-
- /* 4624 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 18 },
- /* 4625 */ { MAD_F(0x04b40685) /* 0.293951532 */, 18 },
- /* 4626 */ { MAD_F(0x04b45f62) /* 0.294036278 */, 18 },
- /* 4627 */ { MAD_F(0x04b4b840) /* 0.294121029 */, 18 },
- /* 4628 */ { MAD_F(0x04b51120) /* 0.294205788 */, 18 },
- /* 4629 */ { MAD_F(0x04b56a02) /* 0.294290552 */, 18 },
- /* 4630 */ { MAD_F(0x04b5c2e6) /* 0.294375322 */, 18 },
- /* 4631 */ { MAD_F(0x04b61bcb) /* 0.294460098 */, 18 },
- /* 4632 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 18 },
- /* 4633 */ { MAD_F(0x04b6cd99) /* 0.294629669 */, 18 },
- /* 4634 */ { MAD_F(0x04b72683) /* 0.294714464 */, 18 },
- /* 4635 */ { MAD_F(0x04b77f6f) /* 0.294799265 */, 18 },
- /* 4636 */ { MAD_F(0x04b7d85c) /* 0.294884072 */, 18 },
- /* 4637 */ { MAD_F(0x04b8314b) /* 0.294968885 */, 18 },
- /* 4638 */ { MAD_F(0x04b88a3b) /* 0.295053704 */, 18 },
- /* 4639 */ { MAD_F(0x04b8e32d) /* 0.295138529 */, 18 },
-
- /* 4640 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 18 },
- /* 4641 */ { MAD_F(0x04b99516) /* 0.295308197 */, 18 },
- /* 4642 */ { MAD_F(0x04b9ee0d) /* 0.295393041 */, 18 },
- /* 4643 */ { MAD_F(0x04ba4706) /* 0.295477890 */, 18 },
- /* 4644 */ { MAD_F(0x04baa000) /* 0.295562746 */, 18 },
- /* 4645 */ { MAD_F(0x04baf8fc) /* 0.295647608 */, 18 },
- /* 4646 */ { MAD_F(0x04bb51fa) /* 0.295732476 */, 18 },
- /* 4647 */ { MAD_F(0x04bbaaf9) /* 0.295817349 */, 18 },
- /* 4648 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 18 },
- /* 4649 */ { MAD_F(0x04bc5cfc) /* 0.295987115 */, 18 },
- /* 4650 */ { MAD_F(0x04bcb600) /* 0.296072008 */, 18 },
- /* 4651 */ { MAD_F(0x04bd0f06) /* 0.296156906 */, 18 },
- /* 4652 */ { MAD_F(0x04bd680d) /* 0.296241810 */, 18 },
- /* 4653 */ { MAD_F(0x04bdc116) /* 0.296326721 */, 18 },
- /* 4654 */ { MAD_F(0x04be1a21) /* 0.296411637 */, 18 },
- /* 4655 */ { MAD_F(0x04be732d) /* 0.296496560 */, 18 },
-
- /* 4656 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 18 },
- /* 4657 */ { MAD_F(0x04bf254a) /* 0.296666423 */, 18 },
- /* 4658 */ { MAD_F(0x04bf7e5b) /* 0.296751364 */, 18 },
- /* 4659 */ { MAD_F(0x04bfd76e) /* 0.296836311 */, 18 },
- /* 4660 */ { MAD_F(0x04c03083) /* 0.296921264 */, 18 },
- /* 4661 */ { MAD_F(0x04c08999) /* 0.297006223 */, 18 },
- /* 4662 */ { MAD_F(0x04c0e2b0) /* 0.297091188 */, 18 },
- /* 4663 */ { MAD_F(0x04c13bca) /* 0.297176159 */, 18 },
- /* 4664 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 18 },
- /* 4665 */ { MAD_F(0x04c1ee01) /* 0.297346120 */, 18 },
- /* 4666 */ { MAD_F(0x04c2471f) /* 0.297431109 */, 18 },
- /* 4667 */ { MAD_F(0x04c2a03f) /* 0.297516105 */, 18 },
- /* 4668 */ { MAD_F(0x04c2f960) /* 0.297601106 */, 18 },
- /* 4669 */ { MAD_F(0x04c35283) /* 0.297686114 */, 18 },
- /* 4670 */ { MAD_F(0x04c3aba8) /* 0.297771128 */, 18 },
- /* 4671 */ { MAD_F(0x04c404ce) /* 0.297856147 */, 18 },
-
- /* 4672 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 18 },
- /* 4673 */ { MAD_F(0x04c4b720) /* 0.298026205 */, 18 },
- /* 4674 */ { MAD_F(0x04c5104b) /* 0.298111243 */, 18 },
- /* 4675 */ { MAD_F(0x04c56978) /* 0.298196287 */, 18 },
- /* 4676 */ { MAD_F(0x04c5c2a7) /* 0.298281337 */, 18 },
- /* 4677 */ { MAD_F(0x04c61bd7) /* 0.298366393 */, 18 },
- /* 4678 */ { MAD_F(0x04c67508) /* 0.298451456 */, 18 },
- /* 4679 */ { MAD_F(0x04c6ce3c) /* 0.298536524 */, 18 },
- /* 4680 */ { MAD_F(0x04c72771) /* 0.298621598 */, 18 },
- /* 4681 */ { MAD_F(0x04c780a7) /* 0.298706679 */, 18 },
- /* 4682 */ { MAD_F(0x04c7d9df) /* 0.298791765 */, 18 },
- /* 4683 */ { MAD_F(0x04c83319) /* 0.298876858 */, 18 },
- /* 4684 */ { MAD_F(0x04c88c55) /* 0.298961956 */, 18 },
- /* 4685 */ { MAD_F(0x04c8e592) /* 0.299047061 */, 18 },
- /* 4686 */ { MAD_F(0x04c93ed1) /* 0.299132172 */, 18 },
- /* 4687 */ { MAD_F(0x04c99811) /* 0.299217288 */, 18 },
-
- /* 4688 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 18 },
- /* 4689 */ { MAD_F(0x04ca4a97) /* 0.299387540 */, 18 },
- /* 4690 */ { MAD_F(0x04caa3dc) /* 0.299472675 */, 18 },
- /* 4691 */ { MAD_F(0x04cafd23) /* 0.299557816 */, 18 },
- /* 4692 */ { MAD_F(0x04cb566b) /* 0.299642963 */, 18 },
- /* 4693 */ { MAD_F(0x04cbafb5) /* 0.299728116 */, 18 },
- /* 4694 */ { MAD_F(0x04cc0901) /* 0.299813275 */, 18 },
- /* 4695 */ { MAD_F(0x04cc624e) /* 0.299898440 */, 18 },
- /* 4696 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 18 },
- /* 4697 */ { MAD_F(0x04cd14ee) /* 0.300068789 */, 18 },
- /* 4698 */ { MAD_F(0x04cd6e40) /* 0.300153972 */, 18 },
- /* 4699 */ { MAD_F(0x04cdc794) /* 0.300239161 */, 18 },
- /* 4700 */ { MAD_F(0x04ce20e9) /* 0.300324357 */, 18 },
- /* 4701 */ { MAD_F(0x04ce7a40) /* 0.300409558 */, 18 },
- /* 4702 */ { MAD_F(0x04ced399) /* 0.300494765 */, 18 },
- /* 4703 */ { MAD_F(0x04cf2cf3) /* 0.300579979 */, 18 },
-
- /* 4704 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 18 },
- /* 4705 */ { MAD_F(0x04cfdfad) /* 0.300750424 */, 18 },
- /* 4706 */ { MAD_F(0x04d0390c) /* 0.300835656 */, 18 },
- /* 4707 */ { MAD_F(0x04d0926d) /* 0.300920893 */, 18 },
- /* 4708 */ { MAD_F(0x04d0ebcf) /* 0.301006137 */, 18 },
- /* 4709 */ { MAD_F(0x04d14533) /* 0.301091387 */, 18 },
- /* 4710 */ { MAD_F(0x04d19e99) /* 0.301176643 */, 18 },
- /* 4711 */ { MAD_F(0x04d1f800) /* 0.301261904 */, 18 },
- /* 4712 */ { MAD_F(0x04d25169) /* 0.301347172 */, 18 },
- /* 4713 */ { MAD_F(0x04d2aad4) /* 0.301432446 */, 18 },
- /* 4714 */ { MAD_F(0x04d30440) /* 0.301517726 */, 18 },
- /* 4715 */ { MAD_F(0x04d35dae) /* 0.301603012 */, 18 },
- /* 4716 */ { MAD_F(0x04d3b71d) /* 0.301688304 */, 18 },
- /* 4717 */ { MAD_F(0x04d4108e) /* 0.301773602 */, 18 },
- /* 4718 */ { MAD_F(0x04d46a01) /* 0.301858906 */, 18 },
- /* 4719 */ { MAD_F(0x04d4c375) /* 0.301944216 */, 18 },
-
- /* 4720 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 18 },
- /* 4721 */ { MAD_F(0x04d57662) /* 0.302114854 */, 18 },
- /* 4722 */ { MAD_F(0x04d5cfdb) /* 0.302200182 */, 18 },
- /* 4723 */ { MAD_F(0x04d62956) /* 0.302285516 */, 18 },
- /* 4724 */ { MAD_F(0x04d682d2) /* 0.302370856 */, 18 },
- /* 4725 */ { MAD_F(0x04d6dc50) /* 0.302456203 */, 18 },
- /* 4726 */ { MAD_F(0x04d735d0) /* 0.302541555 */, 18 },
- /* 4727 */ { MAD_F(0x04d78f51) /* 0.302626913 */, 18 },
- /* 4728 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 18 },
- /* 4729 */ { MAD_F(0x04d84258) /* 0.302797648 */, 18 },
- /* 4730 */ { MAD_F(0x04d89bde) /* 0.302883024 */, 18 },
- /* 4731 */ { MAD_F(0x04d8f566) /* 0.302968406 */, 18 },
- /* 4732 */ { MAD_F(0x04d94eef) /* 0.303053794 */, 18 },
- /* 4733 */ { MAD_F(0x04d9a87a) /* 0.303139189 */, 18 },
- /* 4734 */ { MAD_F(0x04da0207) /* 0.303224589 */, 18 },
- /* 4735 */ { MAD_F(0x04da5b95) /* 0.303309995 */, 18 },
-
- /* 4736 */ { MAD_F(0x04dab524) /* 0.303395408 */, 18 },
- /* 4737 */ { MAD_F(0x04db0eb6) /* 0.303480826 */, 18 },
- /* 4738 */ { MAD_F(0x04db6849) /* 0.303566251 */, 18 },
- /* 4739 */ { MAD_F(0x04dbc1dd) /* 0.303651681 */, 18 },
- /* 4740 */ { MAD_F(0x04dc1b73) /* 0.303737117 */, 18 },
- /* 4741 */ { MAD_F(0x04dc750b) /* 0.303822560 */, 18 },
- /* 4742 */ { MAD_F(0x04dccea5) /* 0.303908008 */, 18 },
- /* 4743 */ { MAD_F(0x04dd2840) /* 0.303993463 */, 18 },
- /* 4744 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 18 },
- /* 4745 */ { MAD_F(0x04dddb7a) /* 0.304164390 */, 18 },
- /* 4746 */ { MAD_F(0x04de351a) /* 0.304249862 */, 18 },
- /* 4747 */ { MAD_F(0x04de8ebc) /* 0.304335340 */, 18 },
- /* 4748 */ { MAD_F(0x04dee85f) /* 0.304420825 */, 18 },
- /* 4749 */ { MAD_F(0x04df4203) /* 0.304506315 */, 18 },
- /* 4750 */ { MAD_F(0x04df9baa) /* 0.304591812 */, 18 },
- /* 4751 */ { MAD_F(0x04dff552) /* 0.304677314 */, 18 },
-
- /* 4752 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 18 },
- /* 4753 */ { MAD_F(0x04e0a8a6) /* 0.304848337 */, 18 },
- /* 4754 */ { MAD_F(0x04e10253) /* 0.304933858 */, 18 },
- /* 4755 */ { MAD_F(0x04e15c01) /* 0.305019384 */, 18 },
- /* 4756 */ { MAD_F(0x04e1b5b1) /* 0.305104917 */, 18 },
- /* 4757 */ { MAD_F(0x04e20f63) /* 0.305190455 */, 18 },
- /* 4758 */ { MAD_F(0x04e26916) /* 0.305275999 */, 18 },
- /* 4759 */ { MAD_F(0x04e2c2cb) /* 0.305361550 */, 18 },
- /* 4760 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 18 },
- /* 4761 */ { MAD_F(0x04e37639) /* 0.305532669 */, 18 },
- /* 4762 */ { MAD_F(0x04e3cff3) /* 0.305618237 */, 18 },
- /* 4763 */ { MAD_F(0x04e429ae) /* 0.305703811 */, 18 },
- /* 4764 */ { MAD_F(0x04e4836b) /* 0.305789392 */, 18 },
- /* 4765 */ { MAD_F(0x04e4dd29) /* 0.305874978 */, 18 },
- /* 4766 */ { MAD_F(0x04e536e9) /* 0.305960571 */, 18 },
- /* 4767 */ { MAD_F(0x04e590ab) /* 0.306046169 */, 18 },
-
- /* 4768 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 18 },
- /* 4769 */ { MAD_F(0x04e64433) /* 0.306217383 */, 18 },
- /* 4770 */ { MAD_F(0x04e69df9) /* 0.306303000 */, 18 },
- /* 4771 */ { MAD_F(0x04e6f7c1) /* 0.306388622 */, 18 },
- /* 4772 */ { MAD_F(0x04e7518b) /* 0.306474250 */, 18 },
- /* 4773 */ { MAD_F(0x04e7ab56) /* 0.306559885 */, 18 },
- /* 4774 */ { MAD_F(0x04e80523) /* 0.306645525 */, 18 },
- /* 4775 */ { MAD_F(0x04e85ef2) /* 0.306731171 */, 18 },
- /* 4776 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 18 },
- /* 4777 */ { MAD_F(0x04e91293) /* 0.306902481 */, 18 },
- /* 4778 */ { MAD_F(0x04e96c67) /* 0.306988145 */, 18 },
- /* 4779 */ { MAD_F(0x04e9c63b) /* 0.307073816 */, 18 },
- /* 4780 */ { MAD_F(0x04ea2012) /* 0.307159492 */, 18 },
- /* 4781 */ { MAD_F(0x04ea79ea) /* 0.307245174 */, 18 },
- /* 4782 */ { MAD_F(0x04ead3c4) /* 0.307330862 */, 18 },
- /* 4783 */ { MAD_F(0x04eb2d9f) /* 0.307416556 */, 18 },
-
- /* 4784 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 18 },
- /* 4785 */ { MAD_F(0x04ebe15b) /* 0.307587962 */, 18 },
- /* 4786 */ { MAD_F(0x04ec3b3b) /* 0.307673674 */, 18 },
- /* 4787 */ { MAD_F(0x04ec951c) /* 0.307759392 */, 18 },
- /* 4788 */ { MAD_F(0x04ecef00) /* 0.307845115 */, 18 },
- /* 4789 */ { MAD_F(0x04ed48e5) /* 0.307930845 */, 18 },
- /* 4790 */ { MAD_F(0x04eda2cb) /* 0.308016581 */, 18 },
- /* 4791 */ { MAD_F(0x04edfcb3) /* 0.308102323 */, 18 },
- /* 4792 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 18 },
- /* 4793 */ { MAD_F(0x04eeb088) /* 0.308273824 */, 18 },
- /* 4794 */ { MAD_F(0x04ef0a75) /* 0.308359584 */, 18 },
- /* 4795 */ { MAD_F(0x04ef6464) /* 0.308445350 */, 18 },
- /* 4796 */ { MAD_F(0x04efbe54) /* 0.308531121 */, 18 },
- /* 4797 */ { MAD_F(0x04f01846) /* 0.308616899 */, 18 },
- /* 4798 */ { MAD_F(0x04f07239) /* 0.308702682 */, 18 },
- /* 4799 */ { MAD_F(0x04f0cc2e) /* 0.308788472 */, 18 },
-
- /* 4800 */ { MAD_F(0x04f12624) /* 0.308874267 */, 18 },
- /* 4801 */ { MAD_F(0x04f1801d) /* 0.308960068 */, 18 },
- /* 4802 */ { MAD_F(0x04f1da16) /* 0.309045876 */, 18 },
- /* 4803 */ { MAD_F(0x04f23412) /* 0.309131689 */, 18 },
- /* 4804 */ { MAD_F(0x04f28e0f) /* 0.309217508 */, 18 },
- /* 4805 */ { MAD_F(0x04f2e80d) /* 0.309303334 */, 18 },
- /* 4806 */ { MAD_F(0x04f3420d) /* 0.309389165 */, 18 },
- /* 4807 */ { MAD_F(0x04f39c0f) /* 0.309475002 */, 18 },
- /* 4808 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 18 },
- /* 4809 */ { MAD_F(0x04f45017) /* 0.309646694 */, 18 },
- /* 4810 */ { MAD_F(0x04f4aa1e) /* 0.309732549 */, 18 },
- /* 4811 */ { MAD_F(0x04f50426) /* 0.309818410 */, 18 },
- /* 4812 */ { MAD_F(0x04f55e30) /* 0.309904277 */, 18 },
- /* 4813 */ { MAD_F(0x04f5b83b) /* 0.309990150 */, 18 },
- /* 4814 */ { MAD_F(0x04f61248) /* 0.310076028 */, 18 },
- /* 4815 */ { MAD_F(0x04f66c56) /* 0.310161913 */, 18 },
-
- /* 4816 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 18 },
- /* 4817 */ { MAD_F(0x04f72078) /* 0.310333700 */, 18 },
- /* 4818 */ { MAD_F(0x04f77a8b) /* 0.310419603 */, 18 },
- /* 4819 */ { MAD_F(0x04f7d4a0) /* 0.310505511 */, 18 },
- /* 4820 */ { MAD_F(0x04f82eb7) /* 0.310591426 */, 18 },
- /* 4821 */ { MAD_F(0x04f888cf) /* 0.310677346 */, 18 },
- /* 4822 */ { MAD_F(0x04f8e2e9) /* 0.310763272 */, 18 },
- /* 4823 */ { MAD_F(0x04f93d04) /* 0.310849205 */, 18 },
- /* 4824 */ { MAD_F(0x04f99721) /* 0.310935143 */, 18 },
- /* 4825 */ { MAD_F(0x04f9f13f) /* 0.311021087 */, 18 },
- /* 4826 */ { MAD_F(0x04fa4b5f) /* 0.311107037 */, 18 },
- /* 4827 */ { MAD_F(0x04faa581) /* 0.311192993 */, 18 },
- /* 4828 */ { MAD_F(0x04faffa4) /* 0.311278955 */, 18 },
- /* 4829 */ { MAD_F(0x04fb59c9) /* 0.311364923 */, 18 },
- /* 4830 */ { MAD_F(0x04fbb3ef) /* 0.311450897 */, 18 },
- /* 4831 */ { MAD_F(0x04fc0e17) /* 0.311536877 */, 18 },
-
- /* 4832 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 18 },
- /* 4833 */ { MAD_F(0x04fcc26c) /* 0.311708854 */, 18 },
- /* 4834 */ { MAD_F(0x04fd1c99) /* 0.311794851 */, 18 },
- /* 4835 */ { MAD_F(0x04fd76c7) /* 0.311880855 */, 18 },
- /* 4836 */ { MAD_F(0x04fdd0f7) /* 0.311966864 */, 18 },
- /* 4837 */ { MAD_F(0x04fe2b29) /* 0.312052880 */, 18 },
- /* 4838 */ { MAD_F(0x04fe855c) /* 0.312138901 */, 18 },
- /* 4839 */ { MAD_F(0x04fedf91) /* 0.312224928 */, 18 },
- /* 4840 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 18 },
- /* 4841 */ { MAD_F(0x04ff93ff) /* 0.312397000 */, 18 },
- /* 4842 */ { MAD_F(0x04ffee38) /* 0.312483045 */, 18 },
- /* 4843 */ { MAD_F(0x05004874) /* 0.312569096 */, 18 },
- /* 4844 */ { MAD_F(0x0500a2b0) /* 0.312655153 */, 18 },
- /* 4845 */ { MAD_F(0x0500fcef) /* 0.312741216 */, 18 },
- /* 4846 */ { MAD_F(0x0501572e) /* 0.312827284 */, 18 },
- /* 4847 */ { MAD_F(0x0501b170) /* 0.312913359 */, 18 },
-
- /* 4848 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 18 },
- /* 4849 */ { MAD_F(0x050265f8) /* 0.313085526 */, 18 },
- /* 4850 */ { MAD_F(0x0502c03e) /* 0.313171618 */, 18 },
- /* 4851 */ { MAD_F(0x05031a86) /* 0.313257716 */, 18 },
- /* 4852 */ { MAD_F(0x050374cf) /* 0.313343820 */, 18 },
- /* 4853 */ { MAD_F(0x0503cf1a) /* 0.313429931 */, 18 },
- /* 4854 */ { MAD_F(0x05042967) /* 0.313516047 */, 18 },
- /* 4855 */ { MAD_F(0x050483b5) /* 0.313602168 */, 18 },
- /* 4856 */ { MAD_F(0x0504de05) /* 0.313688296 */, 18 },
- /* 4857 */ { MAD_F(0x05053856) /* 0.313774430 */, 18 },
- /* 4858 */ { MAD_F(0x050592a9) /* 0.313860570 */, 18 },
- /* 4859 */ { MAD_F(0x0505ecfd) /* 0.313946715 */, 18 },
- /* 4860 */ { MAD_F(0x05064754) /* 0.314032867 */, 18 },
- /* 4861 */ { MAD_F(0x0506a1ab) /* 0.314119024 */, 18 },
- /* 4862 */ { MAD_F(0x0506fc04) /* 0.314205187 */, 18 },
- /* 4863 */ { MAD_F(0x0507565f) /* 0.314291357 */, 18 },
-
- /* 4864 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 18 },
- /* 4865 */ { MAD_F(0x05080b1a) /* 0.314463713 */, 18 },
- /* 4866 */ { MAD_F(0x05086579) /* 0.314549900 */, 18 },
- /* 4867 */ { MAD_F(0x0508bfdb) /* 0.314636092 */, 18 },
- /* 4868 */ { MAD_F(0x05091a3d) /* 0.314722291 */, 18 },
- /* 4869 */ { MAD_F(0x050974a2) /* 0.314808496 */, 18 },
- /* 4870 */ { MAD_F(0x0509cf08) /* 0.314894706 */, 18 },
- /* 4871 */ { MAD_F(0x050a296f) /* 0.314980923 */, 18 },
- /* 4872 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 18 },
- /* 4873 */ { MAD_F(0x050ade43) /* 0.315153373 */, 18 },
- /* 4874 */ { MAD_F(0x050b38af) /* 0.315239607 */, 18 },
- /* 4875 */ { MAD_F(0x050b931d) /* 0.315325847 */, 18 },
- /* 4876 */ { MAD_F(0x050bed8d) /* 0.315412093 */, 18 },
- /* 4877 */ { MAD_F(0x050c47fe) /* 0.315498345 */, 18 },
- /* 4878 */ { MAD_F(0x050ca271) /* 0.315584603 */, 18 },
- /* 4879 */ { MAD_F(0x050cfce5) /* 0.315670866 */, 18 },
-
- /* 4880 */ { MAD_F(0x050d575b) /* 0.315757136 */, 18 },
- /* 4881 */ { MAD_F(0x050db1d2) /* 0.315843411 */, 18 },
- /* 4882 */ { MAD_F(0x050e0c4b) /* 0.315929693 */, 18 },
- /* 4883 */ { MAD_F(0x050e66c5) /* 0.316015980 */, 18 },
- /* 4884 */ { MAD_F(0x050ec141) /* 0.316102273 */, 18 },
- /* 4885 */ { MAD_F(0x050f1bbf) /* 0.316188572 */, 18 },
- /* 4886 */ { MAD_F(0x050f763e) /* 0.316274877 */, 18 },
- /* 4887 */ { MAD_F(0x050fd0bf) /* 0.316361187 */, 18 },
- /* 4888 */ { MAD_F(0x05102b42) /* 0.316447504 */, 18 },
- /* 4889 */ { MAD_F(0x051085c6) /* 0.316533826 */, 18 },
- /* 4890 */ { MAD_F(0x0510e04b) /* 0.316620155 */, 18 },
- /* 4891 */ { MAD_F(0x05113ad3) /* 0.316706489 */, 18 },
- /* 4892 */ { MAD_F(0x0511955b) /* 0.316792829 */, 18 },
- /* 4893 */ { MAD_F(0x0511efe6) /* 0.316879175 */, 18 },
- /* 4894 */ { MAD_F(0x05124a72) /* 0.316965527 */, 18 },
- /* 4895 */ { MAD_F(0x0512a4ff) /* 0.317051885 */, 18 },
-
- /* 4896 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 18 },
- /* 4897 */ { MAD_F(0x05135a1f) /* 0.317224618 */, 18 },
- /* 4898 */ { MAD_F(0x0513b4b1) /* 0.317310994 */, 18 },
- /* 4899 */ { MAD_F(0x05140f45) /* 0.317397375 */, 18 },
- /* 4900 */ { MAD_F(0x051469da) /* 0.317483762 */, 18 },
- /* 4901 */ { MAD_F(0x0514c471) /* 0.317570155 */, 18 },
- /* 4902 */ { MAD_F(0x05151f0a) /* 0.317656554 */, 18 },
- /* 4903 */ { MAD_F(0x051579a4) /* 0.317742959 */, 18 },
- /* 4904 */ { MAD_F(0x0515d440) /* 0.317829370 */, 18 },
- /* 4905 */ { MAD_F(0x05162edd) /* 0.317915786 */, 18 },
- /* 4906 */ { MAD_F(0x0516897c) /* 0.318002209 */, 18 },
- /* 4907 */ { MAD_F(0x0516e41c) /* 0.318088637 */, 18 },
- /* 4908 */ { MAD_F(0x05173ebe) /* 0.318175071 */, 18 },
- /* 4909 */ { MAD_F(0x05179962) /* 0.318261511 */, 18 },
- /* 4910 */ { MAD_F(0x0517f407) /* 0.318347957 */, 18 },
- /* 4911 */ { MAD_F(0x05184eae) /* 0.318434409 */, 18 },
-
- /* 4912 */ { MAD_F(0x0518a956) /* 0.318520867 */, 18 },
- /* 4913 */ { MAD_F(0x05190400) /* 0.318607330 */, 18 },
- /* 4914 */ { MAD_F(0x05195eab) /* 0.318693800 */, 18 },
- /* 4915 */ { MAD_F(0x0519b958) /* 0.318780275 */, 18 },
- /* 4916 */ { MAD_F(0x051a1407) /* 0.318866756 */, 18 },
- /* 4917 */ { MAD_F(0x051a6eb7) /* 0.318953243 */, 18 },
- /* 4918 */ { MAD_F(0x051ac969) /* 0.319039736 */, 18 },
- /* 4919 */ { MAD_F(0x051b241c) /* 0.319126235 */, 18 },
- /* 4920 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 18 },
- /* 4921 */ { MAD_F(0x051bd987) /* 0.319299250 */, 18 },
- /* 4922 */ { MAD_F(0x051c3440) /* 0.319385766 */, 18 },
- /* 4923 */ { MAD_F(0x051c8ef9) /* 0.319472288 */, 18 },
- /* 4924 */ { MAD_F(0x051ce9b4) /* 0.319558816 */, 18 },
- /* 4925 */ { MAD_F(0x051d4471) /* 0.319645350 */, 18 },
- /* 4926 */ { MAD_F(0x051d9f2f) /* 0.319731890 */, 18 },
- /* 4927 */ { MAD_F(0x051df9ef) /* 0.319818435 */, 18 },
-
- /* 4928 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 18 },
- /* 4929 */ { MAD_F(0x051eaf74) /* 0.319991544 */, 18 },
- /* 4930 */ { MAD_F(0x051f0a38) /* 0.320078107 */, 18 },
- /* 4931 */ { MAD_F(0x051f64ff) /* 0.320164676 */, 18 },
- /* 4932 */ { MAD_F(0x051fbfc6) /* 0.320251251 */, 18 },
- /* 4933 */ { MAD_F(0x05201a90) /* 0.320337832 */, 18 },
- /* 4934 */ { MAD_F(0x0520755b) /* 0.320424419 */, 18 },
- /* 4935 */ { MAD_F(0x0520d027) /* 0.320511011 */, 18 },
- /* 4936 */ { MAD_F(0x05212af5) /* 0.320597609 */, 18 },
- /* 4937 */ { MAD_F(0x052185c5) /* 0.320684213 */, 18 },
- /* 4938 */ { MAD_F(0x0521e096) /* 0.320770823 */, 18 },
- /* 4939 */ { MAD_F(0x05223b69) /* 0.320857439 */, 18 },
- /* 4940 */ { MAD_F(0x0522963d) /* 0.320944061 */, 18 },
- /* 4941 */ { MAD_F(0x0522f113) /* 0.321030688 */, 18 },
- /* 4942 */ { MAD_F(0x05234bea) /* 0.321117322 */, 18 },
- /* 4943 */ { MAD_F(0x0523a6c3) /* 0.321203961 */, 18 },
-
- /* 4944 */ { MAD_F(0x0524019e) /* 0.321290606 */, 18 },
- /* 4945 */ { MAD_F(0x05245c7a) /* 0.321377257 */, 18 },
- /* 4946 */ { MAD_F(0x0524b758) /* 0.321463913 */, 18 },
- /* 4947 */ { MAD_F(0x05251237) /* 0.321550576 */, 18 },
- /* 4948 */ { MAD_F(0x05256d18) /* 0.321637244 */, 18 },
- /* 4949 */ { MAD_F(0x0525c7fb) /* 0.321723919 */, 18 },
- /* 4950 */ { MAD_F(0x052622df) /* 0.321810599 */, 18 },
- /* 4951 */ { MAD_F(0x05267dc4) /* 0.321897285 */, 18 },
- /* 4952 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 18 },
- /* 4953 */ { MAD_F(0x05273394) /* 0.322070674 */, 18 },
- /* 4954 */ { MAD_F(0x05278e7e) /* 0.322157377 */, 18 },
- /* 4955 */ { MAD_F(0x0527e96a) /* 0.322244087 */, 18 },
- /* 4956 */ { MAD_F(0x05284457) /* 0.322330802 */, 18 },
- /* 4957 */ { MAD_F(0x05289f46) /* 0.322417523 */, 18 },
- /* 4958 */ { MAD_F(0x0528fa37) /* 0.322504249 */, 18 },
- /* 4959 */ { MAD_F(0x05295529) /* 0.322590982 */, 18 },
-
- /* 4960 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 18 },
- /* 4961 */ { MAD_F(0x052a0b12) /* 0.322764465 */, 18 },
- /* 4962 */ { MAD_F(0x052a6609) /* 0.322851215 */, 18 },
- /* 4963 */ { MAD_F(0x052ac101) /* 0.322937971 */, 18 },
- /* 4964 */ { MAD_F(0x052b1bfb) /* 0.323024732 */, 18 },
- /* 4965 */ { MAD_F(0x052b76f7) /* 0.323111500 */, 18 },
- /* 4966 */ { MAD_F(0x052bd1f4) /* 0.323198273 */, 18 },
- /* 4967 */ { MAD_F(0x052c2cf2) /* 0.323285052 */, 18 },
- /* 4968 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 18 },
- /* 4969 */ { MAD_F(0x052ce2f4) /* 0.323458628 */, 18 },
- /* 4970 */ { MAD_F(0x052d3df7) /* 0.323545425 */, 18 },
- /* 4971 */ { MAD_F(0x052d98fc) /* 0.323632227 */, 18 },
- /* 4972 */ { MAD_F(0x052df403) /* 0.323719036 */, 18 },
- /* 4973 */ { MAD_F(0x052e4f0b) /* 0.323805850 */, 18 },
- /* 4974 */ { MAD_F(0x052eaa14) /* 0.323892670 */, 18 },
- /* 4975 */ { MAD_F(0x052f051f) /* 0.323979496 */, 18 },
-
- /* 4976 */ { MAD_F(0x052f602c) /* 0.324066327 */, 18 },
- /* 4977 */ { MAD_F(0x052fbb3a) /* 0.324153165 */, 18 },
- /* 4978 */ { MAD_F(0x0530164a) /* 0.324240008 */, 18 },
- /* 4979 */ { MAD_F(0x0530715b) /* 0.324326857 */, 18 },
- /* 4980 */ { MAD_F(0x0530cc6e) /* 0.324413712 */, 18 },
- /* 4981 */ { MAD_F(0x05312783) /* 0.324500572 */, 18 },
- /* 4982 */ { MAD_F(0x05318299) /* 0.324587439 */, 18 },
- /* 4983 */ { MAD_F(0x0531ddb0) /* 0.324674311 */, 18 },
- /* 4984 */ { MAD_F(0x053238ca) /* 0.324761189 */, 18 },
- /* 4985 */ { MAD_F(0x053293e4) /* 0.324848073 */, 18 },
- /* 4986 */ { MAD_F(0x0532ef01) /* 0.324934963 */, 18 },
- /* 4987 */ { MAD_F(0x05334a1e) /* 0.325021858 */, 18 },
- /* 4988 */ { MAD_F(0x0533a53e) /* 0.325108760 */, 18 },
- /* 4989 */ { MAD_F(0x0534005f) /* 0.325195667 */, 18 },
- /* 4990 */ { MAD_F(0x05345b81) /* 0.325282580 */, 18 },
- /* 4991 */ { MAD_F(0x0534b6a5) /* 0.325369498 */, 18 },
-
- /* 4992 */ { MAD_F(0x053511cb) /* 0.325456423 */, 18 },
- /* 4993 */ { MAD_F(0x05356cf2) /* 0.325543353 */, 18 },
- /* 4994 */ { MAD_F(0x0535c81b) /* 0.325630290 */, 18 },
- /* 4995 */ { MAD_F(0x05362345) /* 0.325717232 */, 18 },
- /* 4996 */ { MAD_F(0x05367e71) /* 0.325804179 */, 18 },
- /* 4997 */ { MAD_F(0x0536d99f) /* 0.325891133 */, 18 },
- /* 4998 */ { MAD_F(0x053734ce) /* 0.325978092 */, 18 },
- /* 4999 */ { MAD_F(0x05378ffe) /* 0.326065057 */, 18 },
- /* 5000 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 18 },
- /* 5001 */ { MAD_F(0x05384664) /* 0.326239005 */, 18 },
- /* 5002 */ { MAD_F(0x0538a199) /* 0.326325988 */, 18 },
- /* 5003 */ { MAD_F(0x0538fcd0) /* 0.326412976 */, 18 },
- /* 5004 */ { MAD_F(0x05395808) /* 0.326499970 */, 18 },
- /* 5005 */ { MAD_F(0x0539b342) /* 0.326586970 */, 18 },
- /* 5006 */ { MAD_F(0x053a0e7d) /* 0.326673976 */, 18 },
- /* 5007 */ { MAD_F(0x053a69ba) /* 0.326760988 */, 18 },
-
- /* 5008 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 18 },
- /* 5009 */ { MAD_F(0x053b2039) /* 0.326935028 */, 18 },
- /* 5010 */ { MAD_F(0x053b7b7b) /* 0.327022057 */, 18 },
- /* 5011 */ { MAD_F(0x053bd6be) /* 0.327109092 */, 18 },
- /* 5012 */ { MAD_F(0x053c3203) /* 0.327196132 */, 18 },
- /* 5013 */ { MAD_F(0x053c8d49) /* 0.327283178 */, 18 },
- /* 5014 */ { MAD_F(0x053ce891) /* 0.327370231 */, 18 },
- /* 5015 */ { MAD_F(0x053d43da) /* 0.327457288 */, 18 },
- /* 5016 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 18 },
- /* 5017 */ { MAD_F(0x053dfa72) /* 0.327631421 */, 18 },
- /* 5018 */ { MAD_F(0x053e55c0) /* 0.327718497 */, 18 },
- /* 5019 */ { MAD_F(0x053eb10f) /* 0.327805578 */, 18 },
- /* 5020 */ { MAD_F(0x053f0c61) /* 0.327892665 */, 18 },
- /* 5021 */ { MAD_F(0x053f67b3) /* 0.327979757 */, 18 },
- /* 5022 */ { MAD_F(0x053fc308) /* 0.328066855 */, 18 },
- /* 5023 */ { MAD_F(0x05401e5e) /* 0.328153960 */, 18 },
-
- /* 5024 */ { MAD_F(0x054079b5) /* 0.328241070 */, 18 },
- /* 5025 */ { MAD_F(0x0540d50e) /* 0.328328185 */, 18 },
- /* 5026 */ { MAD_F(0x05413068) /* 0.328415307 */, 18 },
- /* 5027 */ { MAD_F(0x05418bc4) /* 0.328502434 */, 18 },
- /* 5028 */ { MAD_F(0x0541e722) /* 0.328589567 */, 18 },
- /* 5029 */ { MAD_F(0x05424281) /* 0.328676706 */, 18 },
- /* 5030 */ { MAD_F(0x05429de2) /* 0.328763850 */, 18 },
- /* 5031 */ { MAD_F(0x0542f944) /* 0.328851001 */, 18 },
- /* 5032 */ { MAD_F(0x054354a8) /* 0.328938157 */, 18 },
- /* 5033 */ { MAD_F(0x0543b00d) /* 0.329025319 */, 18 },
- /* 5034 */ { MAD_F(0x05440b74) /* 0.329112486 */, 18 },
- /* 5035 */ { MAD_F(0x054466dd) /* 0.329199660 */, 18 },
- /* 5036 */ { MAD_F(0x0544c247) /* 0.329286839 */, 18 },
- /* 5037 */ { MAD_F(0x05451db2) /* 0.329374024 */, 18 },
- /* 5038 */ { MAD_F(0x0545791f) /* 0.329461215 */, 18 },
- /* 5039 */ { MAD_F(0x0545d48e) /* 0.329548411 */, 18 },
-
- /* 5040 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 18 },
- /* 5041 */ { MAD_F(0x05468b70) /* 0.329722822 */, 18 },
- /* 5042 */ { MAD_F(0x0546e6e3) /* 0.329810036 */, 18 },
- /* 5043 */ { MAD_F(0x05474258) /* 0.329897255 */, 18 },
- /* 5044 */ { MAD_F(0x05479dce) /* 0.329984481 */, 18 },
- /* 5045 */ { MAD_F(0x0547f946) /* 0.330071712 */, 18 },
- /* 5046 */ { MAD_F(0x054854c0) /* 0.330158949 */, 18 },
- /* 5047 */ { MAD_F(0x0548b03b) /* 0.330246191 */, 18 },
- /* 5048 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 18 },
- /* 5049 */ { MAD_F(0x05496735) /* 0.330420694 */, 18 },
- /* 5050 */ { MAD_F(0x0549c2b5) /* 0.330507954 */, 18 },
- /* 5051 */ { MAD_F(0x054a1e36) /* 0.330595220 */, 18 },
- /* 5052 */ { MAD_F(0x054a79b9) /* 0.330682491 */, 18 },
- /* 5053 */ { MAD_F(0x054ad53d) /* 0.330769768 */, 18 },
- /* 5054 */ { MAD_F(0x054b30c3) /* 0.330857051 */, 18 },
- /* 5055 */ { MAD_F(0x054b8c4b) /* 0.330944340 */, 18 },
-
- /* 5056 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 18 },
- /* 5057 */ { MAD_F(0x054c435e) /* 0.331118935 */, 18 },
- /* 5058 */ { MAD_F(0x054c9eea) /* 0.331206241 */, 18 },
- /* 5059 */ { MAD_F(0x054cfa78) /* 0.331293553 */, 18 },
- /* 5060 */ { MAD_F(0x054d5607) /* 0.331380870 */, 18 },
- /* 5061 */ { MAD_F(0x054db197) /* 0.331468193 */, 18 },
- /* 5062 */ { MAD_F(0x054e0d2a) /* 0.331555522 */, 18 },
- /* 5063 */ { MAD_F(0x054e68bd) /* 0.331642857 */, 18 },
- /* 5064 */ { MAD_F(0x054ec453) /* 0.331730198 */, 18 },
- /* 5065 */ { MAD_F(0x054f1fe9) /* 0.331817544 */, 18 },
- /* 5066 */ { MAD_F(0x054f7b82) /* 0.331904896 */, 18 },
- /* 5067 */ { MAD_F(0x054fd71c) /* 0.331992254 */, 18 },
- /* 5068 */ { MAD_F(0x055032b7) /* 0.332079617 */, 18 },
- /* 5069 */ { MAD_F(0x05508e54) /* 0.332166986 */, 18 },
- /* 5070 */ { MAD_F(0x0550e9f3) /* 0.332254361 */, 18 },
- /* 5071 */ { MAD_F(0x05514593) /* 0.332341742 */, 18 },
-
- /* 5072 */ { MAD_F(0x0551a134) /* 0.332429129 */, 18 },
- /* 5073 */ { MAD_F(0x0551fcd8) /* 0.332516521 */, 18 },
- /* 5074 */ { MAD_F(0x0552587c) /* 0.332603919 */, 18 },
- /* 5075 */ { MAD_F(0x0552b423) /* 0.332691323 */, 18 },
- /* 5076 */ { MAD_F(0x05530fca) /* 0.332778732 */, 18 },
- /* 5077 */ { MAD_F(0x05536b74) /* 0.332866147 */, 18 },
- /* 5078 */ { MAD_F(0x0553c71f) /* 0.332953568 */, 18 },
- /* 5079 */ { MAD_F(0x055422cb) /* 0.333040995 */, 18 },
- /* 5080 */ { MAD_F(0x05547e79) /* 0.333128427 */, 18 },
- /* 5081 */ { MAD_F(0x0554da29) /* 0.333215865 */, 18 },
- /* 5082 */ { MAD_F(0x055535da) /* 0.333303309 */, 18 },
- /* 5083 */ { MAD_F(0x0555918c) /* 0.333390759 */, 18 },
- /* 5084 */ { MAD_F(0x0555ed40) /* 0.333478214 */, 18 },
- /* 5085 */ { MAD_F(0x055648f6) /* 0.333565675 */, 18 },
- /* 5086 */ { MAD_F(0x0556a4ad) /* 0.333653142 */, 18 },
- /* 5087 */ { MAD_F(0x05570066) /* 0.333740615 */, 18 },
-
- /* 5088 */ { MAD_F(0x05575c20) /* 0.333828093 */, 18 },
- /* 5089 */ { MAD_F(0x0557b7dc) /* 0.333915577 */, 18 },
- /* 5090 */ { MAD_F(0x05581399) /* 0.334003067 */, 18 },
- /* 5091 */ { MAD_F(0x05586f58) /* 0.334090562 */, 18 },
- /* 5092 */ { MAD_F(0x0558cb19) /* 0.334178063 */, 18 },
- /* 5093 */ { MAD_F(0x055926db) /* 0.334265570 */, 18 },
- /* 5094 */ { MAD_F(0x0559829e) /* 0.334353083 */, 18 },
- /* 5095 */ { MAD_F(0x0559de63) /* 0.334440601 */, 18 },
- /* 5096 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 18 },
- /* 5097 */ { MAD_F(0x055a95f2) /* 0.334615655 */, 18 },
- /* 5098 */ { MAD_F(0x055af1bb) /* 0.334703191 */, 18 },
- /* 5099 */ { MAD_F(0x055b4d87) /* 0.334790732 */, 18 },
- /* 5100 */ { MAD_F(0x055ba953) /* 0.334878279 */, 18 },
- /* 5101 */ { MAD_F(0x055c0522) /* 0.334965832 */, 18 },
- /* 5102 */ { MAD_F(0x055c60f1) /* 0.335053391 */, 18 },
- /* 5103 */ { MAD_F(0x055cbcc3) /* 0.335140955 */, 18 },
-
- /* 5104 */ { MAD_F(0x055d1896) /* 0.335228525 */, 18 },
- /* 5105 */ { MAD_F(0x055d746a) /* 0.335316100 */, 18 },
- /* 5106 */ { MAD_F(0x055dd040) /* 0.335403682 */, 18 },
- /* 5107 */ { MAD_F(0x055e2c17) /* 0.335491269 */, 18 },
- /* 5108 */ { MAD_F(0x055e87f0) /* 0.335578861 */, 18 },
- /* 5109 */ { MAD_F(0x055ee3cb) /* 0.335666460 */, 18 },
- /* 5110 */ { MAD_F(0x055f3fa7) /* 0.335754064 */, 18 },
- /* 5111 */ { MAD_F(0x055f9b85) /* 0.335841674 */, 18 },
- /* 5112 */ { MAD_F(0x055ff764) /* 0.335929290 */, 18 },
- /* 5113 */ { MAD_F(0x05605344) /* 0.336016911 */, 18 },
- /* 5114 */ { MAD_F(0x0560af27) /* 0.336104538 */, 18 },
- /* 5115 */ { MAD_F(0x05610b0a) /* 0.336192171 */, 18 },
- /* 5116 */ { MAD_F(0x056166f0) /* 0.336279809 */, 18 },
- /* 5117 */ { MAD_F(0x0561c2d7) /* 0.336367453 */, 18 },
- /* 5118 */ { MAD_F(0x05621ebf) /* 0.336455103 */, 18 },
- /* 5119 */ { MAD_F(0x05627aa9) /* 0.336542759 */, 18 },
-
- /* 5120 */ { MAD_F(0x0562d694) /* 0.336630420 */, 18 },
- /* 5121 */ { MAD_F(0x05633281) /* 0.336718087 */, 18 },
- /* 5122 */ { MAD_F(0x05638e70) /* 0.336805760 */, 18 },
- /* 5123 */ { MAD_F(0x0563ea60) /* 0.336893439 */, 18 },
- /* 5124 */ { MAD_F(0x05644651) /* 0.336981123 */, 18 },
- /* 5125 */ { MAD_F(0x0564a244) /* 0.337068813 */, 18 },
- /* 5126 */ { MAD_F(0x0564fe39) /* 0.337156508 */, 18 },
- /* 5127 */ { MAD_F(0x05655a2f) /* 0.337244209 */, 18 },
- /* 5128 */ { MAD_F(0x0565b627) /* 0.337331916 */, 18 },
- /* 5129 */ { MAD_F(0x05661220) /* 0.337419629 */, 18 },
- /* 5130 */ { MAD_F(0x05666e1a) /* 0.337507347 */, 18 },
- /* 5131 */ { MAD_F(0x0566ca17) /* 0.337595071 */, 18 },
- /* 5132 */ { MAD_F(0x05672614) /* 0.337682801 */, 18 },
- /* 5133 */ { MAD_F(0x05678214) /* 0.337770537 */, 18 },
- /* 5134 */ { MAD_F(0x0567de15) /* 0.337858278 */, 18 },
- /* 5135 */ { MAD_F(0x05683a17) /* 0.337946025 */, 18 },
-
- /* 5136 */ { MAD_F(0x0568961b) /* 0.338033777 */, 18 },
- /* 5137 */ { MAD_F(0x0568f220) /* 0.338121535 */, 18 },
- /* 5138 */ { MAD_F(0x05694e27) /* 0.338209299 */, 18 },
- /* 5139 */ { MAD_F(0x0569aa30) /* 0.338297069 */, 18 },
- /* 5140 */ { MAD_F(0x056a063a) /* 0.338384844 */, 18 },
- /* 5141 */ { MAD_F(0x056a6245) /* 0.338472625 */, 18 },
- /* 5142 */ { MAD_F(0x056abe52) /* 0.338560412 */, 18 },
- /* 5143 */ { MAD_F(0x056b1a61) /* 0.338648204 */, 18 },
- /* 5144 */ { MAD_F(0x056b7671) /* 0.338736002 */, 18 },
- /* 5145 */ { MAD_F(0x056bd283) /* 0.338823806 */, 18 },
- /* 5146 */ { MAD_F(0x056c2e96) /* 0.338911616 */, 18 },
- /* 5147 */ { MAD_F(0x056c8aab) /* 0.338999431 */, 18 },
- /* 5148 */ { MAD_F(0x056ce6c1) /* 0.339087252 */, 18 },
- /* 5149 */ { MAD_F(0x056d42d9) /* 0.339175078 */, 18 },
- /* 5150 */ { MAD_F(0x056d9ef2) /* 0.339262910 */, 18 },
- /* 5151 */ { MAD_F(0x056dfb0d) /* 0.339350748 */, 18 },
-
- /* 5152 */ { MAD_F(0x056e5729) /* 0.339438592 */, 18 },
- /* 5153 */ { MAD_F(0x056eb347) /* 0.339526441 */, 18 },
- /* 5154 */ { MAD_F(0x056f0f66) /* 0.339614296 */, 18 },
- /* 5155 */ { MAD_F(0x056f6b87) /* 0.339702157 */, 18 },
- /* 5156 */ { MAD_F(0x056fc7aa) /* 0.339790023 */, 18 },
- /* 5157 */ { MAD_F(0x057023cd) /* 0.339877895 */, 18 },
- /* 5158 */ { MAD_F(0x05707ff3) /* 0.339965773 */, 18 },
- /* 5159 */ { MAD_F(0x0570dc1a) /* 0.340053656 */, 18 },
- /* 5160 */ { MAD_F(0x05713843) /* 0.340141545 */, 18 },
- /* 5161 */ { MAD_F(0x0571946d) /* 0.340229440 */, 18 },
- /* 5162 */ { MAD_F(0x0571f098) /* 0.340317340 */, 18 },
- /* 5163 */ { MAD_F(0x05724cc5) /* 0.340405246 */, 18 },
- /* 5164 */ { MAD_F(0x0572a8f4) /* 0.340493158 */, 18 },
- /* 5165 */ { MAD_F(0x05730524) /* 0.340581075 */, 18 },
- /* 5166 */ { MAD_F(0x05736156) /* 0.340668999 */, 18 },
- /* 5167 */ { MAD_F(0x0573bd89) /* 0.340756927 */, 18 },
-
- /* 5168 */ { MAD_F(0x057419be) /* 0.340844862 */, 18 },
- /* 5169 */ { MAD_F(0x057475f4) /* 0.340932802 */, 18 },
- /* 5170 */ { MAD_F(0x0574d22c) /* 0.341020748 */, 18 },
- /* 5171 */ { MAD_F(0x05752e65) /* 0.341108699 */, 18 },
- /* 5172 */ { MAD_F(0x05758aa0) /* 0.341196656 */, 18 },
- /* 5173 */ { MAD_F(0x0575e6dc) /* 0.341284619 */, 18 },
- /* 5174 */ { MAD_F(0x0576431a) /* 0.341372587 */, 18 },
- /* 5175 */ { MAD_F(0x05769f59) /* 0.341460562 */, 18 },
- /* 5176 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 18 },
- /* 5177 */ { MAD_F(0x057757dd) /* 0.341636527 */, 18 },
- /* 5178 */ { MAD_F(0x0577b421) /* 0.341724518 */, 18 },
- /* 5179 */ { MAD_F(0x05781066) /* 0.341812515 */, 18 },
- /* 5180 */ { MAD_F(0x05786cad) /* 0.341900517 */, 18 },
- /* 5181 */ { MAD_F(0x0578c8f5) /* 0.341988525 */, 18 },
- /* 5182 */ { MAD_F(0x0579253f) /* 0.342076539 */, 18 },
- /* 5183 */ { MAD_F(0x0579818b) /* 0.342164558 */, 18 },
-
- /* 5184 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 18 },
- /* 5185 */ { MAD_F(0x057a3a27) /* 0.342340614 */, 18 },
- /* 5186 */ { MAD_F(0x057a9677) /* 0.342428651 */, 18 },
- /* 5187 */ { MAD_F(0x057af2c8) /* 0.342516693 */, 18 },
- /* 5188 */ { MAD_F(0x057b4f1c) /* 0.342604741 */, 18 },
- /* 5189 */ { MAD_F(0x057bab70) /* 0.342692794 */, 18 },
- /* 5190 */ { MAD_F(0x057c07c6) /* 0.342780853 */, 18 },
- /* 5191 */ { MAD_F(0x057c641e) /* 0.342868918 */, 18 },
- /* 5192 */ { MAD_F(0x057cc077) /* 0.342956988 */, 18 },
- /* 5193 */ { MAD_F(0x057d1cd2) /* 0.343045064 */, 18 },
- /* 5194 */ { MAD_F(0x057d792e) /* 0.343133146 */, 18 },
- /* 5195 */ { MAD_F(0x057dd58c) /* 0.343221233 */, 18 },
- /* 5196 */ { MAD_F(0x057e31eb) /* 0.343309326 */, 18 },
- /* 5197 */ { MAD_F(0x057e8e4c) /* 0.343397425 */, 18 },
- /* 5198 */ { MAD_F(0x057eeaae) /* 0.343485529 */, 18 },
- /* 5199 */ { MAD_F(0x057f4712) /* 0.343573639 */, 18 },
-
- /* 5200 */ { MAD_F(0x057fa378) /* 0.343661754 */, 18 },
- /* 5201 */ { MAD_F(0x057fffde) /* 0.343749876 */, 18 },
- /* 5202 */ { MAD_F(0x05805c47) /* 0.343838003 */, 18 },
- /* 5203 */ { MAD_F(0x0580b8b1) /* 0.343926135 */, 18 },
- /* 5204 */ { MAD_F(0x0581151c) /* 0.344014273 */, 18 },
- /* 5205 */ { MAD_F(0x05817189) /* 0.344102417 */, 18 },
- /* 5206 */ { MAD_F(0x0581cdf7) /* 0.344190566 */, 18 },
- /* 5207 */ { MAD_F(0x05822a67) /* 0.344278722 */, 18 },
- /* 5208 */ { MAD_F(0x058286d9) /* 0.344366882 */, 18 },
- /* 5209 */ { MAD_F(0x0582e34c) /* 0.344455049 */, 18 },
- /* 5210 */ { MAD_F(0x05833fc0) /* 0.344543221 */, 18 },
- /* 5211 */ { MAD_F(0x05839c36) /* 0.344631398 */, 18 },
- /* 5212 */ { MAD_F(0x0583f8ae) /* 0.344719582 */, 18 },
- /* 5213 */ { MAD_F(0x05845527) /* 0.344807771 */, 18 },
- /* 5214 */ { MAD_F(0x0584b1a1) /* 0.344895965 */, 18 },
- /* 5215 */ { MAD_F(0x05850e1e) /* 0.344984165 */, 18 },
-
- /* 5216 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 18 },
- /* 5217 */ { MAD_F(0x0585c71a) /* 0.345160583 */, 18 },
- /* 5218 */ { MAD_F(0x0586239b) /* 0.345248800 */, 18 },
- /* 5219 */ { MAD_F(0x0586801d) /* 0.345337023 */, 18 },
- /* 5220 */ { MAD_F(0x0586dca1) /* 0.345425251 */, 18 },
- /* 5221 */ { MAD_F(0x05873926) /* 0.345513485 */, 18 },
- /* 5222 */ { MAD_F(0x058795ac) /* 0.345601725 */, 18 },
- /* 5223 */ { MAD_F(0x0587f235) /* 0.345689970 */, 18 },
- /* 5224 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 18 },
- /* 5225 */ { MAD_F(0x0588ab49) /* 0.345866478 */, 18 },
- /* 5226 */ { MAD_F(0x058907d6) /* 0.345954740 */, 18 },
- /* 5227 */ { MAD_F(0x05896464) /* 0.346043008 */, 18 },
- /* 5228 */ { MAD_F(0x0589c0f4) /* 0.346131281 */, 18 },
- /* 5229 */ { MAD_F(0x058a1d85) /* 0.346219560 */, 18 },
- /* 5230 */ { MAD_F(0x058a7a18) /* 0.346307845 */, 18 },
- /* 5231 */ { MAD_F(0x058ad6ac) /* 0.346396135 */, 18 },
-
- /* 5232 */ { MAD_F(0x058b3342) /* 0.346484431 */, 18 },
- /* 5233 */ { MAD_F(0x058b8fd9) /* 0.346572733 */, 18 },
- /* 5234 */ { MAD_F(0x058bec72) /* 0.346661040 */, 18 },
- /* 5235 */ { MAD_F(0x058c490c) /* 0.346749353 */, 18 },
- /* 5236 */ { MAD_F(0x058ca5a8) /* 0.346837671 */, 18 },
- /* 5237 */ { MAD_F(0x058d0246) /* 0.346925996 */, 18 },
- /* 5238 */ { MAD_F(0x058d5ee4) /* 0.347014325 */, 18 },
- /* 5239 */ { MAD_F(0x058dbb85) /* 0.347102661 */, 18 },
- /* 5240 */ { MAD_F(0x058e1827) /* 0.347191002 */, 18 },
- /* 5241 */ { MAD_F(0x058e74ca) /* 0.347279348 */, 18 },
- /* 5242 */ { MAD_F(0x058ed16f) /* 0.347367700 */, 18 },
- /* 5243 */ { MAD_F(0x058f2e15) /* 0.347456058 */, 18 },
- /* 5244 */ { MAD_F(0x058f8abd) /* 0.347544422 */, 18 },
- /* 5245 */ { MAD_F(0x058fe766) /* 0.347632791 */, 18 },
- /* 5246 */ { MAD_F(0x05904411) /* 0.347721165 */, 18 },
- /* 5247 */ { MAD_F(0x0590a0be) /* 0.347809546 */, 18 },
-
- /* 5248 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 18 },
- /* 5249 */ { MAD_F(0x05915a1b) /* 0.347986323 */, 18 },
- /* 5250 */ { MAD_F(0x0591b6cc) /* 0.348074720 */, 18 },
- /* 5251 */ { MAD_F(0x0592137e) /* 0.348163123 */, 18 },
- /* 5252 */ { MAD_F(0x05927032) /* 0.348251531 */, 18 },
- /* 5253 */ { MAD_F(0x0592cce8) /* 0.348339945 */, 18 },
- /* 5254 */ { MAD_F(0x0593299f) /* 0.348428365 */, 18 },
- /* 5255 */ { MAD_F(0x05938657) /* 0.348516790 */, 18 },
- /* 5256 */ { MAD_F(0x0593e311) /* 0.348605221 */, 18 },
- /* 5257 */ { MAD_F(0x05943fcd) /* 0.348693657 */, 18 },
- /* 5258 */ { MAD_F(0x05949c8a) /* 0.348782099 */, 18 },
- /* 5259 */ { MAD_F(0x0594f948) /* 0.348870547 */, 18 },
- /* 5260 */ { MAD_F(0x05955608) /* 0.348959000 */, 18 },
- /* 5261 */ { MAD_F(0x0595b2ca) /* 0.349047459 */, 18 },
- /* 5262 */ { MAD_F(0x05960f8c) /* 0.349135923 */, 18 },
- /* 5263 */ { MAD_F(0x05966c51) /* 0.349224393 */, 18 },
-
- /* 5264 */ { MAD_F(0x0596c917) /* 0.349312869 */, 18 },
- /* 5265 */ { MAD_F(0x059725de) /* 0.349401350 */, 18 },
- /* 5266 */ { MAD_F(0x059782a7) /* 0.349489837 */, 18 },
- /* 5267 */ { MAD_F(0x0597df72) /* 0.349578329 */, 18 },
- /* 5268 */ { MAD_F(0x05983c3e) /* 0.349666827 */, 18 },
- /* 5269 */ { MAD_F(0x0598990c) /* 0.349755331 */, 18 },
- /* 5270 */ { MAD_F(0x0598f5db) /* 0.349843840 */, 18 },
- /* 5271 */ { MAD_F(0x059952ab) /* 0.349932355 */, 18 },
- /* 5272 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 18 },
- /* 5273 */ { MAD_F(0x059a0c51) /* 0.350109402 */, 18 },
- /* 5274 */ { MAD_F(0x059a6926) /* 0.350197933 */, 18 },
- /* 5275 */ { MAD_F(0x059ac5fc) /* 0.350286470 */, 18 },
- /* 5276 */ { MAD_F(0x059b22d4) /* 0.350375013 */, 18 },
- /* 5277 */ { MAD_F(0x059b7fae) /* 0.350463562 */, 18 },
- /* 5278 */ { MAD_F(0x059bdc89) /* 0.350552116 */, 18 },
- /* 5279 */ { MAD_F(0x059c3965) /* 0.350640675 */, 18 },
-
- /* 5280 */ { MAD_F(0x059c9643) /* 0.350729240 */, 18 },
- /* 5281 */ { MAD_F(0x059cf323) /* 0.350817811 */, 18 },
- /* 5282 */ { MAD_F(0x059d5004) /* 0.350906388 */, 18 },
- /* 5283 */ { MAD_F(0x059dace6) /* 0.350994970 */, 18 },
- /* 5284 */ { MAD_F(0x059e09cb) /* 0.351083557 */, 18 },
- /* 5285 */ { MAD_F(0x059e66b0) /* 0.351172150 */, 18 },
- /* 5286 */ { MAD_F(0x059ec397) /* 0.351260749 */, 18 },
- /* 5287 */ { MAD_F(0x059f2080) /* 0.351349353 */, 18 },
- /* 5288 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 18 },
- /* 5289 */ { MAD_F(0x059fda55) /* 0.351526579 */, 18 },
- /* 5290 */ { MAD_F(0x05a03742) /* 0.351615200 */, 18 },
- /* 5291 */ { MAD_F(0x05a09431) /* 0.351703827 */, 18 },
- /* 5292 */ { MAD_F(0x05a0f121) /* 0.351792459 */, 18 },
- /* 5293 */ { MAD_F(0x05a14e12) /* 0.351881097 */, 18 },
- /* 5294 */ { MAD_F(0x05a1ab05) /* 0.351969740 */, 18 },
- /* 5295 */ { MAD_F(0x05a207fa) /* 0.352058389 */, 18 },
-
- /* 5296 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 18 },
- /* 5297 */ { MAD_F(0x05a2c1e7) /* 0.352235704 */, 18 },
- /* 5298 */ { MAD_F(0x05a31ee1) /* 0.352324369 */, 18 },
- /* 5299 */ { MAD_F(0x05a37bdb) /* 0.352413041 */, 18 },
- /* 5300 */ { MAD_F(0x05a3d8d7) /* 0.352501718 */, 18 },
- /* 5301 */ { MAD_F(0x05a435d5) /* 0.352590400 */, 18 },
- /* 5302 */ { MAD_F(0x05a492d4) /* 0.352679088 */, 18 },
- /* 5303 */ { MAD_F(0x05a4efd4) /* 0.352767782 */, 18 },
- /* 5304 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 18 },
- /* 5305 */ { MAD_F(0x05a5a9da) /* 0.352945186 */, 18 },
- /* 5306 */ { MAD_F(0x05a606df) /* 0.353033896 */, 18 },
- /* 5307 */ { MAD_F(0x05a663e5) /* 0.353122612 */, 18 },
- /* 5308 */ { MAD_F(0x05a6c0ed) /* 0.353211333 */, 18 },
- /* 5309 */ { MAD_F(0x05a71df7) /* 0.353300061 */, 18 },
- /* 5310 */ { MAD_F(0x05a77b02) /* 0.353388793 */, 18 },
- /* 5311 */ { MAD_F(0x05a7d80e) /* 0.353477531 */, 18 },
-
- /* 5312 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 18 },
- /* 5313 */ { MAD_F(0x05a8922c) /* 0.353655024 */, 18 },
- /* 5314 */ { MAD_F(0x05a8ef3c) /* 0.353743779 */, 18 },
- /* 5315 */ { MAD_F(0x05a94c4f) /* 0.353832540 */, 18 },
- /* 5316 */ { MAD_F(0x05a9a963) /* 0.353921306 */, 18 },
- /* 5317 */ { MAD_F(0x05aa0678) /* 0.354010077 */, 18 },
- /* 5318 */ { MAD_F(0x05aa638f) /* 0.354098855 */, 18 },
- /* 5319 */ { MAD_F(0x05aac0a8) /* 0.354187637 */, 18 },
- /* 5320 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 18 },
- /* 5321 */ { MAD_F(0x05ab7add) /* 0.354365220 */, 18 },
- /* 5322 */ { MAD_F(0x05abd7fa) /* 0.354454019 */, 18 },
- /* 5323 */ { MAD_F(0x05ac3518) /* 0.354542824 */, 18 },
- /* 5324 */ { MAD_F(0x05ac9238) /* 0.354631635 */, 18 },
- /* 5325 */ { MAD_F(0x05acef5a) /* 0.354720451 */, 18 },
- /* 5326 */ { MAD_F(0x05ad4c7d) /* 0.354809272 */, 18 },
- /* 5327 */ { MAD_F(0x05ada9a1) /* 0.354898100 */, 18 },
-
- /* 5328 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 18 },
- /* 5329 */ { MAD_F(0x05ae63ee) /* 0.355075771 */, 18 },
- /* 5330 */ { MAD_F(0x05aec117) /* 0.355164615 */, 18 },
- /* 5331 */ { MAD_F(0x05af1e41) /* 0.355253464 */, 18 },
- /* 5332 */ { MAD_F(0x05af7b6d) /* 0.355342319 */, 18 },
- /* 5333 */ { MAD_F(0x05afd89b) /* 0.355431180 */, 18 },
- /* 5334 */ { MAD_F(0x05b035c9) /* 0.355520046 */, 18 },
- /* 5335 */ { MAD_F(0x05b092fa) /* 0.355608917 */, 18 },
- /* 5336 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 18 },
- /* 5337 */ { MAD_F(0x05b14d5f) /* 0.355786677 */, 18 },
- /* 5338 */ { MAD_F(0x05b1aa94) /* 0.355875566 */, 18 },
- /* 5339 */ { MAD_F(0x05b207ca) /* 0.355964460 */, 18 },
- /* 5340 */ { MAD_F(0x05b26502) /* 0.356053359 */, 18 },
- /* 5341 */ { MAD_F(0x05b2c23b) /* 0.356142264 */, 18 },
- /* 5342 */ { MAD_F(0x05b31f76) /* 0.356231175 */, 18 },
- /* 5343 */ { MAD_F(0x05b37cb2) /* 0.356320091 */, 18 },
-
- /* 5344 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 18 },
- /* 5345 */ { MAD_F(0x05b4372f) /* 0.356497940 */, 18 },
- /* 5346 */ { MAD_F(0x05b4946f) /* 0.356586872 */, 18 },
- /* 5347 */ { MAD_F(0x05b4f1b2) /* 0.356675811 */, 18 },
- /* 5348 */ { MAD_F(0x05b54ef5) /* 0.356764754 */, 18 },
- /* 5349 */ { MAD_F(0x05b5ac3a) /* 0.356853704 */, 18 },
- /* 5350 */ { MAD_F(0x05b60981) /* 0.356942659 */, 18 },
- /* 5351 */ { MAD_F(0x05b666c9) /* 0.357031619 */, 18 },
- /* 5352 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 18 },
- /* 5353 */ { MAD_F(0x05b7215e) /* 0.357209557 */, 18 },
- /* 5354 */ { MAD_F(0x05b77eab) /* 0.357298534 */, 18 },
- /* 5355 */ { MAD_F(0x05b7dbf9) /* 0.357387516 */, 18 },
- /* 5356 */ { MAD_F(0x05b83948) /* 0.357476504 */, 18 },
- /* 5357 */ { MAD_F(0x05b89699) /* 0.357565498 */, 18 },
- /* 5358 */ { MAD_F(0x05b8f3ec) /* 0.357654497 */, 18 },
- /* 5359 */ { MAD_F(0x05b95140) /* 0.357743502 */, 18 },
-
- /* 5360 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 18 },
- /* 5361 */ { MAD_F(0x05ba0bec) /* 0.357921528 */, 18 },
- /* 5362 */ { MAD_F(0x05ba6945) /* 0.358010550 */, 18 },
- /* 5363 */ { MAD_F(0x05bac69f) /* 0.358099576 */, 18 },
- /* 5364 */ { MAD_F(0x05bb23fa) /* 0.358188609 */, 18 },
- /* 5365 */ { MAD_F(0x05bb8157) /* 0.358277647 */, 18 },
- /* 5366 */ { MAD_F(0x05bbdeb6) /* 0.358366690 */, 18 },
- /* 5367 */ { MAD_F(0x05bc3c16) /* 0.358455739 */, 18 },
- /* 5368 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 18 },
- /* 5369 */ { MAD_F(0x05bcf6da) /* 0.358633854 */, 18 },
- /* 5370 */ { MAD_F(0x05bd543e) /* 0.358722920 */, 18 },
- /* 5371 */ { MAD_F(0x05bdb1a4) /* 0.358811991 */, 18 },
- /* 5372 */ { MAD_F(0x05be0f0b) /* 0.358901067 */, 18 },
- /* 5373 */ { MAD_F(0x05be6c74) /* 0.358990150 */, 18 },
- /* 5374 */ { MAD_F(0x05bec9df) /* 0.359079237 */, 18 },
- /* 5375 */ { MAD_F(0x05bf274a) /* 0.359168331 */, 18 },
-
- /* 5376 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 18 },
- /* 5377 */ { MAD_F(0x05bfe226) /* 0.359346534 */, 18 },
- /* 5378 */ { MAD_F(0x05c03f97) /* 0.359435644 */, 18 },
- /* 5379 */ { MAD_F(0x05c09d08) /* 0.359524759 */, 18 },
- /* 5380 */ { MAD_F(0x05c0fa7c) /* 0.359613880 */, 18 },
- /* 5381 */ { MAD_F(0x05c157f0) /* 0.359703006 */, 18 },
- /* 5382 */ { MAD_F(0x05c1b566) /* 0.359792138 */, 18 },
- /* 5383 */ { MAD_F(0x05c212de) /* 0.359881276 */, 18 },
- /* 5384 */ { MAD_F(0x05c27057) /* 0.359970419 */, 18 },
- /* 5385 */ { MAD_F(0x05c2cdd2) /* 0.360059567 */, 18 },
- /* 5386 */ { MAD_F(0x05c32b4e) /* 0.360148721 */, 18 },
- /* 5387 */ { MAD_F(0x05c388cb) /* 0.360237881 */, 18 },
- /* 5388 */ { MAD_F(0x05c3e64b) /* 0.360327046 */, 18 },
- /* 5389 */ { MAD_F(0x05c443cb) /* 0.360416216 */, 18 },
- /* 5390 */ { MAD_F(0x05c4a14d) /* 0.360505392 */, 18 },
- /* 5391 */ { MAD_F(0x05c4fed1) /* 0.360594574 */, 18 },
-
- /* 5392 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 18 },
- /* 5393 */ { MAD_F(0x05c5b9dc) /* 0.360772953 */, 18 },
- /* 5394 */ { MAD_F(0x05c61764) /* 0.360862152 */, 18 },
- /* 5395 */ { MAD_F(0x05c674ed) /* 0.360951355 */, 18 },
- /* 5396 */ { MAD_F(0x05c6d278) /* 0.361040564 */, 18 },
- /* 5397 */ { MAD_F(0x05c73005) /* 0.361129779 */, 18 },
- /* 5398 */ { MAD_F(0x05c78d93) /* 0.361218999 */, 18 },
- /* 5399 */ { MAD_F(0x05c7eb22) /* 0.361308225 */, 18 },
- /* 5400 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 18 },
- /* 5401 */ { MAD_F(0x05c8a645) /* 0.361486693 */, 18 },
- /* 5402 */ { MAD_F(0x05c903d9) /* 0.361575935 */, 18 },
- /* 5403 */ { MAD_F(0x05c9616e) /* 0.361665183 */, 18 },
- /* 5404 */ { MAD_F(0x05c9bf05) /* 0.361754436 */, 18 },
- /* 5405 */ { MAD_F(0x05ca1c9d) /* 0.361843695 */, 18 },
- /* 5406 */ { MAD_F(0x05ca7a37) /* 0.361932959 */, 18 },
- /* 5407 */ { MAD_F(0x05cad7d2) /* 0.362022229 */, 18 },
-
- /* 5408 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 18 },
- /* 5409 */ { MAD_F(0x05cb930d) /* 0.362200785 */, 18 },
- /* 5410 */ { MAD_F(0x05cbf0ac) /* 0.362290071 */, 18 },
- /* 5411 */ { MAD_F(0x05cc4e4d) /* 0.362379362 */, 18 },
- /* 5412 */ { MAD_F(0x05ccabf0) /* 0.362468660 */, 18 },
- /* 5413 */ { MAD_F(0x05cd0994) /* 0.362557962 */, 18 },
- /* 5414 */ { MAD_F(0x05cd6739) /* 0.362647271 */, 18 },
- /* 5415 */ { MAD_F(0x05cdc4e0) /* 0.362736584 */, 18 },
- /* 5416 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 18 },
- /* 5417 */ { MAD_F(0x05ce8033) /* 0.362915228 */, 18 },
- /* 5418 */ { MAD_F(0x05ceddde) /* 0.363004559 */, 18 },
- /* 5419 */ { MAD_F(0x05cf3b8b) /* 0.363093894 */, 18 },
- /* 5420 */ { MAD_F(0x05cf9939) /* 0.363183236 */, 18 },
- /* 5421 */ { MAD_F(0x05cff6e9) /* 0.363272582 */, 18 },
- /* 5422 */ { MAD_F(0x05d0549a) /* 0.363361935 */, 18 },
- /* 5423 */ { MAD_F(0x05d0b24d) /* 0.363451292 */, 18 },
-
- /* 5424 */ { MAD_F(0x05d11001) /* 0.363540655 */, 18 },
- /* 5425 */ { MAD_F(0x05d16db7) /* 0.363630024 */, 18 },
- /* 5426 */ { MAD_F(0x05d1cb6e) /* 0.363719398 */, 18 },
- /* 5427 */ { MAD_F(0x05d22927) /* 0.363808778 */, 18 },
- /* 5428 */ { MAD_F(0x05d286e1) /* 0.363898163 */, 18 },
- /* 5429 */ { MAD_F(0x05d2e49d) /* 0.363987554 */, 18 },
- /* 5430 */ { MAD_F(0x05d3425a) /* 0.364076950 */, 18 },
- /* 5431 */ { MAD_F(0x05d3a018) /* 0.364166352 */, 18 },
- /* 5432 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 18 },
- /* 5433 */ { MAD_F(0x05d45b9a) /* 0.364345171 */, 18 },
- /* 5434 */ { MAD_F(0x05d4b95d) /* 0.364434589 */, 18 },
- /* 5435 */ { MAD_F(0x05d51721) /* 0.364524013 */, 18 },
- /* 5436 */ { MAD_F(0x05d574e7) /* 0.364613442 */, 18 },
- /* 5437 */ { MAD_F(0x05d5d2af) /* 0.364702877 */, 18 },
- /* 5438 */ { MAD_F(0x05d63078) /* 0.364792317 */, 18 },
- /* 5439 */ { MAD_F(0x05d68e42) /* 0.364881762 */, 18 },
-
- /* 5440 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 18 },
- /* 5441 */ { MAD_F(0x05d749db) /* 0.365060669 */, 18 },
- /* 5442 */ { MAD_F(0x05d7a7aa) /* 0.365150131 */, 18 },
- /* 5443 */ { MAD_F(0x05d8057a) /* 0.365239599 */, 18 },
- /* 5444 */ { MAD_F(0x05d8634c) /* 0.365329072 */, 18 },
- /* 5445 */ { MAD_F(0x05d8c11f) /* 0.365418550 */, 18 },
- /* 5446 */ { MAD_F(0x05d91ef4) /* 0.365508034 */, 18 },
- /* 5447 */ { MAD_F(0x05d97cca) /* 0.365597523 */, 18 },
- /* 5448 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 18 },
- /* 5449 */ { MAD_F(0x05da387a) /* 0.365776518 */, 18 },
- /* 5450 */ { MAD_F(0x05da9655) /* 0.365866024 */, 18 },
- /* 5451 */ { MAD_F(0x05daf431) /* 0.365955536 */, 18 },
- /* 5452 */ { MAD_F(0x05db520e) /* 0.366045052 */, 18 },
- /* 5453 */ { MAD_F(0x05dbafed) /* 0.366134574 */, 18 },
- /* 5454 */ { MAD_F(0x05dc0dce) /* 0.366224102 */, 18 },
- /* 5455 */ { MAD_F(0x05dc6baf) /* 0.366313635 */, 18 },
-
- /* 5456 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 18 },
- /* 5457 */ { MAD_F(0x05dd2778) /* 0.366492718 */, 18 },
- /* 5458 */ { MAD_F(0x05dd855e) /* 0.366582267 */, 18 },
- /* 5459 */ { MAD_F(0x05dde346) /* 0.366671822 */, 18 },
- /* 5460 */ { MAD_F(0x05de412f) /* 0.366761383 */, 18 },
- /* 5461 */ { MAD_F(0x05de9f1a) /* 0.366850949 */, 18 },
- /* 5462 */ { MAD_F(0x05defd06) /* 0.366940520 */, 18 },
- /* 5463 */ { MAD_F(0x05df5af3) /* 0.367030097 */, 18 },
- /* 5464 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 18 },
- /* 5465 */ { MAD_F(0x05e016d3) /* 0.367209267 */, 18 },
- /* 5466 */ { MAD_F(0x05e074c5) /* 0.367298861 */, 18 },
- /* 5467 */ { MAD_F(0x05e0d2b8) /* 0.367388459 */, 18 },
- /* 5468 */ { MAD_F(0x05e130ad) /* 0.367478064 */, 18 },
- /* 5469 */ { MAD_F(0x05e18ea4) /* 0.367567673 */, 18 },
- /* 5470 */ { MAD_F(0x05e1ec9c) /* 0.367657288 */, 18 },
- /* 5471 */ { MAD_F(0x05e24a95) /* 0.367746909 */, 18 },
-
- /* 5472 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 18 },
- /* 5473 */ { MAD_F(0x05e3068c) /* 0.367926167 */, 18 },
- /* 5474 */ { MAD_F(0x05e3648a) /* 0.368015804 */, 18 },
- /* 5475 */ { MAD_F(0x05e3c289) /* 0.368105446 */, 18 },
- /* 5476 */ { MAD_F(0x05e4208a) /* 0.368195094 */, 18 },
- /* 5477 */ { MAD_F(0x05e47e8c) /* 0.368284747 */, 18 },
- /* 5478 */ { MAD_F(0x05e4dc8f) /* 0.368374406 */, 18 },
- /* 5479 */ { MAD_F(0x05e53a94) /* 0.368464070 */, 18 },
- /* 5480 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 18 },
- /* 5481 */ { MAD_F(0x05e5f6a3) /* 0.368643415 */, 18 },
- /* 5482 */ { MAD_F(0x05e654ac) /* 0.368733096 */, 18 },
- /* 5483 */ { MAD_F(0x05e6b2b7) /* 0.368822782 */, 18 },
- /* 5484 */ { MAD_F(0x05e710c4) /* 0.368912473 */, 18 },
- /* 5485 */ { MAD_F(0x05e76ed2) /* 0.369002170 */, 18 },
- /* 5486 */ { MAD_F(0x05e7cce1) /* 0.369091873 */, 18 },
- /* 5487 */ { MAD_F(0x05e82af2) /* 0.369181581 */, 18 },
-
- /* 5488 */ { MAD_F(0x05e88904) /* 0.369271294 */, 18 },
- /* 5489 */ { MAD_F(0x05e8e718) /* 0.369361013 */, 18 },
- /* 5490 */ { MAD_F(0x05e9452d) /* 0.369450737 */, 18 },
- /* 5491 */ { MAD_F(0x05e9a343) /* 0.369540467 */, 18 },
- /* 5492 */ { MAD_F(0x05ea015c) /* 0.369630202 */, 18 },
- /* 5493 */ { MAD_F(0x05ea5f75) /* 0.369719942 */, 18 },
- /* 5494 */ { MAD_F(0x05eabd90) /* 0.369809688 */, 18 },
- /* 5495 */ { MAD_F(0x05eb1bad) /* 0.369899440 */, 18 },
- /* 5496 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 18 },
- /* 5497 */ { MAD_F(0x05ebd7ea) /* 0.370078959 */, 18 },
- /* 5498 */ { MAD_F(0x05ec360b) /* 0.370168727 */, 18 },
- /* 5499 */ { MAD_F(0x05ec942d) /* 0.370258500 */, 18 },
- /* 5500 */ { MAD_F(0x05ecf251) /* 0.370348279 */, 18 },
- /* 5501 */ { MAD_F(0x05ed5076) /* 0.370438063 */, 18 },
- /* 5502 */ { MAD_F(0x05edae9d) /* 0.370527853 */, 18 },
- /* 5503 */ { MAD_F(0x05ee0cc5) /* 0.370617648 */, 18 },
-
- /* 5504 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 18 },
- /* 5505 */ { MAD_F(0x05eec91a) /* 0.370797254 */, 18 },
- /* 5506 */ { MAD_F(0x05ef2746) /* 0.370887065 */, 18 },
- /* 5507 */ { MAD_F(0x05ef8574) /* 0.370976882 */, 18 },
- /* 5508 */ { MAD_F(0x05efe3a4) /* 0.371066704 */, 18 },
- /* 5509 */ { MAD_F(0x05f041d5) /* 0.371156532 */, 18 },
- /* 5510 */ { MAD_F(0x05f0a007) /* 0.371246365 */, 18 },
- /* 5511 */ { MAD_F(0x05f0fe3b) /* 0.371336203 */, 18 },
- /* 5512 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 18 },
- /* 5513 */ { MAD_F(0x05f1baa7) /* 0.371515897 */, 18 },
- /* 5514 */ { MAD_F(0x05f218df) /* 0.371605751 */, 18 },
- /* 5515 */ { MAD_F(0x05f27719) /* 0.371695612 */, 18 },
- /* 5516 */ { MAD_F(0x05f2d554) /* 0.371785477 */, 18 },
- /* 5517 */ { MAD_F(0x05f33390) /* 0.371875348 */, 18 },
- /* 5518 */ { MAD_F(0x05f391cf) /* 0.371965225 */, 18 },
- /* 5519 */ { MAD_F(0x05f3f00e) /* 0.372055107 */, 18 },
-
- /* 5520 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 18 },
- /* 5521 */ { MAD_F(0x05f4ac91) /* 0.372234887 */, 18 },
- /* 5522 */ { MAD_F(0x05f50ad5) /* 0.372324785 */, 18 },
- /* 5523 */ { MAD_F(0x05f5691b) /* 0.372414689 */, 18 },
- /* 5524 */ { MAD_F(0x05f5c761) /* 0.372504598 */, 18 },
- /* 5525 */ { MAD_F(0x05f625aa) /* 0.372594513 */, 18 },
- /* 5526 */ { MAD_F(0x05f683f3) /* 0.372684433 */, 18 },
- /* 5527 */ { MAD_F(0x05f6e23f) /* 0.372774358 */, 18 },
- /* 5528 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 18 },
- /* 5529 */ { MAD_F(0x05f79ed9) /* 0.372954225 */, 18 },
- /* 5530 */ { MAD_F(0x05f7fd29) /* 0.373044167 */, 18 },
- /* 5531 */ { MAD_F(0x05f85b7a) /* 0.373134114 */, 18 },
- /* 5532 */ { MAD_F(0x05f8b9cc) /* 0.373224066 */, 18 },
- /* 5533 */ { MAD_F(0x05f91820) /* 0.373314024 */, 18 },
- /* 5534 */ { MAD_F(0x05f97675) /* 0.373403987 */, 18 },
- /* 5535 */ { MAD_F(0x05f9d4cc) /* 0.373493956 */, 18 },
-
- /* 5536 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 18 },
- /* 5537 */ { MAD_F(0x05fa917e) /* 0.373673910 */, 18 },
- /* 5538 */ { MAD_F(0x05faefd9) /* 0.373763895 */, 18 },
- /* 5539 */ { MAD_F(0x05fb4e36) /* 0.373853885 */, 18 },
- /* 5540 */ { MAD_F(0x05fbac94) /* 0.373943881 */, 18 },
- /* 5541 */ { MAD_F(0x05fc0af3) /* 0.374033882 */, 18 },
- /* 5542 */ { MAD_F(0x05fc6954) /* 0.374123889 */, 18 },
- /* 5543 */ { MAD_F(0x05fcc7b7) /* 0.374213901 */, 18 },
- /* 5544 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 18 },
- /* 5545 */ { MAD_F(0x05fd8480) /* 0.374393941 */, 18 },
- /* 5546 */ { MAD_F(0x05fde2e7) /* 0.374483970 */, 18 },
- /* 5547 */ { MAD_F(0x05fe414f) /* 0.374574003 */, 18 },
- /* 5548 */ { MAD_F(0x05fe9fb9) /* 0.374664042 */, 18 },
- /* 5549 */ { MAD_F(0x05fefe24) /* 0.374754087 */, 18 },
- /* 5550 */ { MAD_F(0x05ff5c91) /* 0.374844137 */, 18 },
- /* 5551 */ { MAD_F(0x05ffbaff) /* 0.374934192 */, 18 },
-
- /* 5552 */ { MAD_F(0x0600196e) /* 0.375024253 */, 18 },
- /* 5553 */ { MAD_F(0x060077df) /* 0.375114319 */, 18 },
- /* 5554 */ { MAD_F(0x0600d651) /* 0.375204391 */, 18 },
- /* 5555 */ { MAD_F(0x060134c5) /* 0.375294468 */, 18 },
- /* 5556 */ { MAD_F(0x0601933b) /* 0.375384550 */, 18 },
- /* 5557 */ { MAD_F(0x0601f1b1) /* 0.375474638 */, 18 },
- /* 5558 */ { MAD_F(0x0602502a) /* 0.375564731 */, 18 },
- /* 5559 */ { MAD_F(0x0602aea3) /* 0.375654830 */, 18 },
- /* 5560 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 18 },
- /* 5561 */ { MAD_F(0x06036b9b) /* 0.375835043 */, 18 },
- /* 5562 */ { MAD_F(0x0603ca19) /* 0.375925158 */, 18 },
- /* 5563 */ { MAD_F(0x06042898) /* 0.376015278 */, 18 },
- /* 5564 */ { MAD_F(0x06048719) /* 0.376105404 */, 18 },
- /* 5565 */ { MAD_F(0x0604e59c) /* 0.376195535 */, 18 },
- /* 5566 */ { MAD_F(0x0605441f) /* 0.376285671 */, 18 },
- /* 5567 */ { MAD_F(0x0605a2a5) /* 0.376375813 */, 18 },
-
- /* 5568 */ { MAD_F(0x0606012b) /* 0.376465960 */, 18 },
- /* 5569 */ { MAD_F(0x06065fb4) /* 0.376556113 */, 18 },
- /* 5570 */ { MAD_F(0x0606be3d) /* 0.376646271 */, 18 },
- /* 5571 */ { MAD_F(0x06071cc8) /* 0.376736434 */, 18 },
- /* 5572 */ { MAD_F(0x06077b55) /* 0.376826603 */, 18 },
- /* 5573 */ { MAD_F(0x0607d9e3) /* 0.376916777 */, 18 },
- /* 5574 */ { MAD_F(0x06083872) /* 0.377006957 */, 18 },
- /* 5575 */ { MAD_F(0x06089703) /* 0.377097141 */, 18 },
- /* 5576 */ { MAD_F(0x0608f595) /* 0.377187332 */, 18 },
- /* 5577 */ { MAD_F(0x06095429) /* 0.377277528 */, 18 },
- /* 5578 */ { MAD_F(0x0609b2be) /* 0.377367729 */, 18 },
- /* 5579 */ { MAD_F(0x060a1155) /* 0.377457935 */, 18 },
- /* 5580 */ { MAD_F(0x060a6fed) /* 0.377548147 */, 18 },
- /* 5581 */ { MAD_F(0x060ace86) /* 0.377638364 */, 18 },
- /* 5582 */ { MAD_F(0x060b2d21) /* 0.377728587 */, 18 },
- /* 5583 */ { MAD_F(0x060b8bbe) /* 0.377818815 */, 18 },
-
- /* 5584 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 18 },
- /* 5585 */ { MAD_F(0x060c48fb) /* 0.377999288 */, 18 },
- /* 5586 */ { MAD_F(0x060ca79c) /* 0.378089532 */, 18 },
- /* 5587 */ { MAD_F(0x060d063e) /* 0.378179781 */, 18 },
- /* 5588 */ { MAD_F(0x060d64e1) /* 0.378270036 */, 18 },
- /* 5589 */ { MAD_F(0x060dc387) /* 0.378360297 */, 18 },
- /* 5590 */ { MAD_F(0x060e222d) /* 0.378450563 */, 18 },
- /* 5591 */ { MAD_F(0x060e80d5) /* 0.378540834 */, 18 },
- /* 5592 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 18 },
- /* 5593 */ { MAD_F(0x060f3e29) /* 0.378721392 */, 18 },
- /* 5594 */ { MAD_F(0x060f9cd6) /* 0.378811680 */, 18 },
- /* 5595 */ { MAD_F(0x060ffb83) /* 0.378901972 */, 18 },
- /* 5596 */ { MAD_F(0x06105a33) /* 0.378992270 */, 18 },
- /* 5597 */ { MAD_F(0x0610b8e3) /* 0.379082574 */, 18 },
- /* 5598 */ { MAD_F(0x06111795) /* 0.379172883 */, 18 },
- /* 5599 */ { MAD_F(0x06117649) /* 0.379263197 */, 18 },
-
- /* 5600 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 18 },
- /* 5601 */ { MAD_F(0x061233b4) /* 0.379443841 */, 18 },
- /* 5602 */ { MAD_F(0x0612926c) /* 0.379534172 */, 18 },
- /* 5603 */ { MAD_F(0x0612f125) /* 0.379624507 */, 18 },
- /* 5604 */ { MAD_F(0x06134fe0) /* 0.379714848 */, 18 },
- /* 5605 */ { MAD_F(0x0613ae9c) /* 0.379805195 */, 18 },
- /* 5606 */ { MAD_F(0x06140d5a) /* 0.379895547 */, 18 },
- /* 5607 */ { MAD_F(0x06146c19) /* 0.379985904 */, 18 },
- /* 5608 */ { MAD_F(0x0614cada) /* 0.380076266 */, 18 },
- /* 5609 */ { MAD_F(0x0615299c) /* 0.380166634 */, 18 },
- /* 5610 */ { MAD_F(0x0615885f) /* 0.380257008 */, 18 },
- /* 5611 */ { MAD_F(0x0615e724) /* 0.380347386 */, 18 },
- /* 5612 */ { MAD_F(0x061645ea) /* 0.380437770 */, 18 },
- /* 5613 */ { MAD_F(0x0616a4b2) /* 0.380528160 */, 18 },
- /* 5614 */ { MAD_F(0x0617037b) /* 0.380618555 */, 18 },
- /* 5615 */ { MAD_F(0x06176246) /* 0.380708955 */, 18 },
-
- /* 5616 */ { MAD_F(0x0617c112) /* 0.380799360 */, 18 },
- /* 5617 */ { MAD_F(0x06181fdf) /* 0.380889771 */, 18 },
- /* 5618 */ { MAD_F(0x06187eae) /* 0.380980187 */, 18 },
- /* 5619 */ { MAD_F(0x0618dd7e) /* 0.381070609 */, 18 },
- /* 5620 */ { MAD_F(0x06193c50) /* 0.381161036 */, 18 },
- /* 5621 */ { MAD_F(0x06199b24) /* 0.381251468 */, 18 },
- /* 5622 */ { MAD_F(0x0619f9f8) /* 0.381341906 */, 18 },
- /* 5623 */ { MAD_F(0x061a58ce) /* 0.381432349 */, 18 },
- /* 5624 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 18 },
- /* 5625 */ { MAD_F(0x061b167f) /* 0.381613251 */, 18 },
- /* 5626 */ { MAD_F(0x061b7559) /* 0.381703711 */, 18 },
- /* 5627 */ { MAD_F(0x061bd435) /* 0.381794175 */, 18 },
- /* 5628 */ { MAD_F(0x061c3313) /* 0.381884645 */, 18 },
- /* 5629 */ { MAD_F(0x061c91f1) /* 0.381975120 */, 18 },
- /* 5630 */ { MAD_F(0x061cf0d2) /* 0.382065601 */, 18 },
- /* 5631 */ { MAD_F(0x061d4fb3) /* 0.382156087 */, 18 },
-
- /* 5632 */ { MAD_F(0x061dae96) /* 0.382246578 */, 18 },
- /* 5633 */ { MAD_F(0x061e0d7b) /* 0.382337075 */, 18 },
- /* 5634 */ { MAD_F(0x061e6c61) /* 0.382427577 */, 18 },
- /* 5635 */ { MAD_F(0x061ecb48) /* 0.382518084 */, 18 },
- /* 5636 */ { MAD_F(0x061f2a31) /* 0.382608597 */, 18 },
- /* 5637 */ { MAD_F(0x061f891b) /* 0.382699115 */, 18 },
- /* 5638 */ { MAD_F(0x061fe807) /* 0.382789638 */, 18 },
- /* 5639 */ { MAD_F(0x062046f4) /* 0.382880167 */, 18 },
- /* 5640 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 18 },
- /* 5641 */ { MAD_F(0x062104d3) /* 0.383061241 */, 18 },
- /* 5642 */ { MAD_F(0x062163c4) /* 0.383151786 */, 18 },
- /* 5643 */ { MAD_F(0x0621c2b7) /* 0.383242336 */, 18 },
- /* 5644 */ { MAD_F(0x062221ab) /* 0.383332891 */, 18 },
- /* 5645 */ { MAD_F(0x062280a1) /* 0.383423452 */, 18 },
- /* 5646 */ { MAD_F(0x0622df98) /* 0.383514018 */, 18 },
- /* 5647 */ { MAD_F(0x06233e91) /* 0.383604590 */, 18 },
-
- /* 5648 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 18 },
- /* 5649 */ { MAD_F(0x0623fc86) /* 0.383785749 */, 18 },
- /* 5650 */ { MAD_F(0x06245b83) /* 0.383876337 */, 18 },
- /* 5651 */ { MAD_F(0x0624ba82) /* 0.383966930 */, 18 },
- /* 5652 */ { MAD_F(0x06251981) /* 0.384057528 */, 18 },
- /* 5653 */ { MAD_F(0x06257883) /* 0.384148132 */, 18 },
- /* 5654 */ { MAD_F(0x0625d785) /* 0.384238741 */, 18 },
- /* 5655 */ { MAD_F(0x06263689) /* 0.384329355 */, 18 },
- /* 5656 */ { MAD_F(0x0626958f) /* 0.384419975 */, 18 },
- /* 5657 */ { MAD_F(0x0626f496) /* 0.384510600 */, 18 },
- /* 5658 */ { MAD_F(0x0627539e) /* 0.384601230 */, 18 },
- /* 5659 */ { MAD_F(0x0627b2a8) /* 0.384691866 */, 18 },
- /* 5660 */ { MAD_F(0x062811b3) /* 0.384782507 */, 18 },
- /* 5661 */ { MAD_F(0x062870c0) /* 0.384873153 */, 18 },
- /* 5662 */ { MAD_F(0x0628cfce) /* 0.384963805 */, 18 },
- /* 5663 */ { MAD_F(0x06292ede) /* 0.385054462 */, 18 },
-
- /* 5664 */ { MAD_F(0x06298def) /* 0.385145124 */, 18 },
- /* 5665 */ { MAD_F(0x0629ed01) /* 0.385235792 */, 18 },
- /* 5666 */ { MAD_F(0x062a4c15) /* 0.385326465 */, 18 },
- /* 5667 */ { MAD_F(0x062aab2a) /* 0.385417143 */, 18 },
- /* 5668 */ { MAD_F(0x062b0a41) /* 0.385507827 */, 18 },
- /* 5669 */ { MAD_F(0x062b6959) /* 0.385598516 */, 18 },
- /* 5670 */ { MAD_F(0x062bc873) /* 0.385689211 */, 18 },
- /* 5671 */ { MAD_F(0x062c278e) /* 0.385779910 */, 18 },
- /* 5672 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 18 },
- /* 5673 */ { MAD_F(0x062ce5c8) /* 0.385961326 */, 18 },
- /* 5674 */ { MAD_F(0x062d44e8) /* 0.386052041 */, 18 },
- /* 5675 */ { MAD_F(0x062da408) /* 0.386142762 */, 18 },
- /* 5676 */ { MAD_F(0x062e032a) /* 0.386233489 */, 18 },
- /* 5677 */ { MAD_F(0x062e624e) /* 0.386324221 */, 18 },
- /* 5678 */ { MAD_F(0x062ec173) /* 0.386414958 */, 18 },
- /* 5679 */ { MAD_F(0x062f209a) /* 0.386505700 */, 18 },
-
- /* 5680 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 18 },
- /* 5681 */ { MAD_F(0x062fdeeb) /* 0.386687201 */, 18 },
- /* 5682 */ { MAD_F(0x06303e16) /* 0.386777959 */, 18 },
- /* 5683 */ { MAD_F(0x06309d42) /* 0.386868723 */, 18 },
- /* 5684 */ { MAD_F(0x0630fc6f) /* 0.386959492 */, 18 },
- /* 5685 */ { MAD_F(0x06315b9e) /* 0.387050266 */, 18 },
- /* 5686 */ { MAD_F(0x0631bacf) /* 0.387141045 */, 18 },
- /* 5687 */ { MAD_F(0x06321a01) /* 0.387231830 */, 18 },
- /* 5688 */ { MAD_F(0x06327934) /* 0.387322621 */, 18 },
- /* 5689 */ { MAD_F(0x0632d869) /* 0.387413416 */, 18 },
- /* 5690 */ { MAD_F(0x0633379f) /* 0.387504217 */, 18 },
- /* 5691 */ { MAD_F(0x063396d7) /* 0.387595023 */, 18 },
- /* 5692 */ { MAD_F(0x0633f610) /* 0.387685835 */, 18 },
- /* 5693 */ { MAD_F(0x0634554a) /* 0.387776652 */, 18 },
- /* 5694 */ { MAD_F(0x0634b486) /* 0.387867474 */, 18 },
- /* 5695 */ { MAD_F(0x063513c3) /* 0.387958301 */, 18 },
-
- /* 5696 */ { MAD_F(0x06357302) /* 0.388049134 */, 18 },
- /* 5697 */ { MAD_F(0x0635d242) /* 0.388139972 */, 18 },
- /* 5698 */ { MAD_F(0x06363184) /* 0.388230816 */, 18 },
- /* 5699 */ { MAD_F(0x063690c7) /* 0.388321665 */, 18 },
- /* 5700 */ { MAD_F(0x0636f00b) /* 0.388412519 */, 18 },
- /* 5701 */ { MAD_F(0x06374f51) /* 0.388503378 */, 18 },
- /* 5702 */ { MAD_F(0x0637ae99) /* 0.388594243 */, 18 },
- /* 5703 */ { MAD_F(0x06380de1) /* 0.388685113 */, 18 },
- /* 5704 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 18 },
- /* 5705 */ { MAD_F(0x0638cc77) /* 0.388866869 */, 18 },
- /* 5706 */ { MAD_F(0x06392bc4) /* 0.388957755 */, 18 },
- /* 5707 */ { MAD_F(0x06398b12) /* 0.389048646 */, 18 },
- /* 5708 */ { MAD_F(0x0639ea62) /* 0.389139542 */, 18 },
- /* 5709 */ { MAD_F(0x063a49b4) /* 0.389230444 */, 18 },
- /* 5710 */ { MAD_F(0x063aa906) /* 0.389321352 */, 18 },
- /* 5711 */ { MAD_F(0x063b085a) /* 0.389412264 */, 18 },
-
- /* 5712 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 18 },
- /* 5713 */ { MAD_F(0x063bc707) /* 0.389594105 */, 18 },
- /* 5714 */ { MAD_F(0x063c265f) /* 0.389685033 */, 18 },
- /* 5715 */ { MAD_F(0x063c85b9) /* 0.389775967 */, 18 },
- /* 5716 */ { MAD_F(0x063ce514) /* 0.389866906 */, 18 },
- /* 5717 */ { MAD_F(0x063d4471) /* 0.389957850 */, 18 },
- /* 5718 */ { MAD_F(0x063da3cf) /* 0.390048800 */, 18 },
- /* 5719 */ { MAD_F(0x063e032f) /* 0.390139755 */, 18 },
- /* 5720 */ { MAD_F(0x063e6290) /* 0.390230715 */, 18 },
- /* 5721 */ { MAD_F(0x063ec1f2) /* 0.390321681 */, 18 },
- /* 5722 */ { MAD_F(0x063f2156) /* 0.390412651 */, 18 },
- /* 5723 */ { MAD_F(0x063f80bb) /* 0.390503628 */, 18 },
- /* 5724 */ { MAD_F(0x063fe022) /* 0.390594609 */, 18 },
- /* 5725 */ { MAD_F(0x06403f8a) /* 0.390685596 */, 18 },
- /* 5726 */ { MAD_F(0x06409ef3) /* 0.390776588 */, 18 },
- /* 5727 */ { MAD_F(0x0640fe5e) /* 0.390867585 */, 18 },
-
- /* 5728 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 18 },
- /* 5729 */ { MAD_F(0x0641bd38) /* 0.391049596 */, 18 },
- /* 5730 */ { MAD_F(0x06421ca7) /* 0.391140609 */, 18 },
- /* 5731 */ { MAD_F(0x06427c18) /* 0.391231627 */, 18 },
- /* 5732 */ { MAD_F(0x0642db8a) /* 0.391322651 */, 18 },
- /* 5733 */ { MAD_F(0x06433afd) /* 0.391413680 */, 18 },
- /* 5734 */ { MAD_F(0x06439a72) /* 0.391504714 */, 18 },
- /* 5735 */ { MAD_F(0x0643f9e9) /* 0.391595754 */, 18 },
- /* 5736 */ { MAD_F(0x06445960) /* 0.391686799 */, 18 },
- /* 5737 */ { MAD_F(0x0644b8d9) /* 0.391777849 */, 18 },
- /* 5738 */ { MAD_F(0x06451854) /* 0.391868905 */, 18 },
- /* 5739 */ { MAD_F(0x064577d0) /* 0.391959966 */, 18 },
- /* 5740 */ { MAD_F(0x0645d74d) /* 0.392051032 */, 18 },
- /* 5741 */ { MAD_F(0x064636cc) /* 0.392142103 */, 18 },
- /* 5742 */ { MAD_F(0x0646964c) /* 0.392233180 */, 18 },
- /* 5743 */ { MAD_F(0x0646f5ce) /* 0.392324262 */, 18 },
-
- /* 5744 */ { MAD_F(0x06475551) /* 0.392415349 */, 18 },
- /* 5745 */ { MAD_F(0x0647b4d5) /* 0.392506442 */, 18 },
- /* 5746 */ { MAD_F(0x0648145b) /* 0.392597540 */, 18 },
- /* 5747 */ { MAD_F(0x064873e3) /* 0.392688643 */, 18 },
- /* 5748 */ { MAD_F(0x0648d36b) /* 0.392779751 */, 18 },
- /* 5749 */ { MAD_F(0x064932f6) /* 0.392870865 */, 18 },
- /* 5750 */ { MAD_F(0x06499281) /* 0.392961984 */, 18 },
- /* 5751 */ { MAD_F(0x0649f20e) /* 0.393053108 */, 18 },
- /* 5752 */ { MAD_F(0x064a519c) /* 0.393144238 */, 18 },
- /* 5753 */ { MAD_F(0x064ab12c) /* 0.393235372 */, 18 },
- /* 5754 */ { MAD_F(0x064b10be) /* 0.393326513 */, 18 },
- /* 5755 */ { MAD_F(0x064b7050) /* 0.393417658 */, 18 },
- /* 5756 */ { MAD_F(0x064bcfe4) /* 0.393508809 */, 18 },
- /* 5757 */ { MAD_F(0x064c2f7a) /* 0.393599965 */, 18 },
- /* 5758 */ { MAD_F(0x064c8f11) /* 0.393691126 */, 18 },
- /* 5759 */ { MAD_F(0x064ceea9) /* 0.393782292 */, 18 },
-
- /* 5760 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 18 },
- /* 5761 */ { MAD_F(0x064dadde) /* 0.393964641 */, 18 },
- /* 5762 */ { MAD_F(0x064e0d7a) /* 0.394055823 */, 18 },
- /* 5763 */ { MAD_F(0x064e6d18) /* 0.394147011 */, 18 },
- /* 5764 */ { MAD_F(0x064eccb8) /* 0.394238204 */, 18 },
- /* 5765 */ { MAD_F(0x064f2c59) /* 0.394329402 */, 18 },
- /* 5766 */ { MAD_F(0x064f8bfb) /* 0.394420605 */, 18 },
- /* 5767 */ { MAD_F(0x064feb9e) /* 0.394511814 */, 18 },
- /* 5768 */ { MAD_F(0x06504b44) /* 0.394603028 */, 18 },
- /* 5769 */ { MAD_F(0x0650aaea) /* 0.394694247 */, 18 },
- /* 5770 */ { MAD_F(0x06510a92) /* 0.394785472 */, 18 },
- /* 5771 */ { MAD_F(0x06516a3b) /* 0.394876702 */, 18 },
- /* 5772 */ { MAD_F(0x0651c9e6) /* 0.394967937 */, 18 },
- /* 5773 */ { MAD_F(0x06522992) /* 0.395059177 */, 18 },
- /* 5774 */ { MAD_F(0x06528940) /* 0.395150423 */, 18 },
- /* 5775 */ { MAD_F(0x0652e8ef) /* 0.395241673 */, 18 },
-
- /* 5776 */ { MAD_F(0x0653489f) /* 0.395332930 */, 18 },
- /* 5777 */ { MAD_F(0x0653a851) /* 0.395424191 */, 18 },
- /* 5778 */ { MAD_F(0x06540804) /* 0.395515458 */, 18 },
- /* 5779 */ { MAD_F(0x065467b9) /* 0.395606730 */, 18 },
- /* 5780 */ { MAD_F(0x0654c76f) /* 0.395698007 */, 18 },
- /* 5781 */ { MAD_F(0x06552726) /* 0.395789289 */, 18 },
- /* 5782 */ { MAD_F(0x065586df) /* 0.395880577 */, 18 },
- /* 5783 */ { MAD_F(0x0655e699) /* 0.395971870 */, 18 },
- /* 5784 */ { MAD_F(0x06564655) /* 0.396063168 */, 18 },
- /* 5785 */ { MAD_F(0x0656a612) /* 0.396154472 */, 18 },
- /* 5786 */ { MAD_F(0x065705d0) /* 0.396245780 */, 18 },
- /* 5787 */ { MAD_F(0x06576590) /* 0.396337094 */, 18 },
- /* 5788 */ { MAD_F(0x0657c552) /* 0.396428414 */, 18 },
- /* 5789 */ { MAD_F(0x06582514) /* 0.396519738 */, 18 },
- /* 5790 */ { MAD_F(0x065884d9) /* 0.396611068 */, 18 },
- /* 5791 */ { MAD_F(0x0658e49e) /* 0.396702403 */, 18 },
-
- /* 5792 */ { MAD_F(0x06594465) /* 0.396793743 */, 18 },
- /* 5793 */ { MAD_F(0x0659a42e) /* 0.396885089 */, 18 },
- /* 5794 */ { MAD_F(0x065a03f7) /* 0.396976440 */, 18 },
- /* 5795 */ { MAD_F(0x065a63c3) /* 0.397067796 */, 18 },
- /* 5796 */ { MAD_F(0x065ac38f) /* 0.397159157 */, 18 },
- /* 5797 */ { MAD_F(0x065b235d) /* 0.397250524 */, 18 },
- /* 5798 */ { MAD_F(0x065b832d) /* 0.397341896 */, 18 },
- /* 5799 */ { MAD_F(0x065be2fe) /* 0.397433273 */, 18 },
- /* 5800 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 18 },
- /* 5801 */ { MAD_F(0x065ca2a3) /* 0.397616043 */, 18 },
- /* 5802 */ { MAD_F(0x065d0279) /* 0.397707436 */, 18 },
- /* 5803 */ { MAD_F(0x065d624f) /* 0.397798834 */, 18 },
- /* 5804 */ { MAD_F(0x065dc227) /* 0.397890237 */, 18 },
- /* 5805 */ { MAD_F(0x065e2200) /* 0.397981646 */, 18 },
- /* 5806 */ { MAD_F(0x065e81db) /* 0.398073059 */, 18 },
- /* 5807 */ { MAD_F(0x065ee1b7) /* 0.398164479 */, 18 },
-
- /* 5808 */ { MAD_F(0x065f4195) /* 0.398255903 */, 18 },
- /* 5809 */ { MAD_F(0x065fa174) /* 0.398347333 */, 18 },
- /* 5810 */ { MAD_F(0x06600154) /* 0.398438767 */, 18 },
- /* 5811 */ { MAD_F(0x06606136) /* 0.398530207 */, 18 },
- /* 5812 */ { MAD_F(0x0660c119) /* 0.398621653 */, 18 },
- /* 5813 */ { MAD_F(0x066120fd) /* 0.398713103 */, 18 },
- /* 5814 */ { MAD_F(0x066180e3) /* 0.398804559 */, 18 },
- /* 5815 */ { MAD_F(0x0661e0cb) /* 0.398896020 */, 18 },
- /* 5816 */ { MAD_F(0x066240b4) /* 0.398987487 */, 18 },
- /* 5817 */ { MAD_F(0x0662a09e) /* 0.399078958 */, 18 },
- /* 5818 */ { MAD_F(0x06630089) /* 0.399170435 */, 18 },
- /* 5819 */ { MAD_F(0x06636077) /* 0.399261917 */, 18 },
- /* 5820 */ { MAD_F(0x0663c065) /* 0.399353404 */, 18 },
- /* 5821 */ { MAD_F(0x06642055) /* 0.399444897 */, 18 },
- /* 5822 */ { MAD_F(0x06648046) /* 0.399536395 */, 18 },
- /* 5823 */ { MAD_F(0x0664e039) /* 0.399627898 */, 18 },
-
- /* 5824 */ { MAD_F(0x0665402d) /* 0.399719406 */, 18 },
- /* 5825 */ { MAD_F(0x0665a022) /* 0.399810919 */, 18 },
- /* 5826 */ { MAD_F(0x06660019) /* 0.399902438 */, 18 },
- /* 5827 */ { MAD_F(0x06666011) /* 0.399993962 */, 18 },
- /* 5828 */ { MAD_F(0x0666c00b) /* 0.400085491 */, 18 },
- /* 5829 */ { MAD_F(0x06672006) /* 0.400177026 */, 18 },
- /* 5830 */ { MAD_F(0x06678003) /* 0.400268565 */, 18 },
- /* 5831 */ { MAD_F(0x0667e000) /* 0.400360110 */, 18 },
- /* 5832 */ { MAD_F(0x06684000) /* 0.400451660 */, 18 },
- /* 5833 */ { MAD_F(0x0668a000) /* 0.400543216 */, 18 },
- /* 5834 */ { MAD_F(0x06690003) /* 0.400634776 */, 18 },
- /* 5835 */ { MAD_F(0x06696006) /* 0.400726342 */, 18 },
- /* 5836 */ { MAD_F(0x0669c00b) /* 0.400817913 */, 18 },
- /* 5837 */ { MAD_F(0x066a2011) /* 0.400909489 */, 18 },
- /* 5838 */ { MAD_F(0x066a8019) /* 0.401001071 */, 18 },
- /* 5839 */ { MAD_F(0x066ae022) /* 0.401092657 */, 18 },
-
- /* 5840 */ { MAD_F(0x066b402d) /* 0.401184249 */, 18 },
- /* 5841 */ { MAD_F(0x066ba039) /* 0.401275847 */, 18 },
- /* 5842 */ { MAD_F(0x066c0046) /* 0.401367449 */, 18 },
- /* 5843 */ { MAD_F(0x066c6055) /* 0.401459057 */, 18 },
- /* 5844 */ { MAD_F(0x066cc065) /* 0.401550670 */, 18 },
- /* 5845 */ { MAD_F(0x066d2076) /* 0.401642288 */, 18 },
- /* 5846 */ { MAD_F(0x066d8089) /* 0.401733911 */, 18 },
- /* 5847 */ { MAD_F(0x066de09e) /* 0.401825540 */, 18 },
- /* 5848 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 18 },
- /* 5849 */ { MAD_F(0x066ea0cb) /* 0.402008812 */, 18 },
- /* 5850 */ { MAD_F(0x066f00e3) /* 0.402100457 */, 18 },
- /* 5851 */ { MAD_F(0x066f60fd) /* 0.402192106 */, 18 },
- /* 5852 */ { MAD_F(0x066fc118) /* 0.402283761 */, 18 },
- /* 5853 */ { MAD_F(0x06702135) /* 0.402375420 */, 18 },
- /* 5854 */ { MAD_F(0x06708153) /* 0.402467086 */, 18 },
- /* 5855 */ { MAD_F(0x0670e173) /* 0.402558756 */, 18 },
-
- /* 5856 */ { MAD_F(0x06714194) /* 0.402650431 */, 18 },
- /* 5857 */ { MAD_F(0x0671a1b6) /* 0.402742112 */, 18 },
- /* 5858 */ { MAD_F(0x067201da) /* 0.402833798 */, 18 },
- /* 5859 */ { MAD_F(0x067261ff) /* 0.402925489 */, 18 },
- /* 5860 */ { MAD_F(0x0672c226) /* 0.403017186 */, 18 },
- /* 5861 */ { MAD_F(0x0673224e) /* 0.403108887 */, 18 },
- /* 5862 */ { MAD_F(0x06738277) /* 0.403200594 */, 18 },
- /* 5863 */ { MAD_F(0x0673e2a2) /* 0.403292306 */, 18 },
- /* 5864 */ { MAD_F(0x067442ce) /* 0.403384024 */, 18 },
- /* 5865 */ { MAD_F(0x0674a2fc) /* 0.403475746 */, 18 },
- /* 5866 */ { MAD_F(0x0675032b) /* 0.403567474 */, 18 },
- /* 5867 */ { MAD_F(0x0675635b) /* 0.403659207 */, 18 },
- /* 5868 */ { MAD_F(0x0675c38d) /* 0.403750945 */, 18 },
- /* 5869 */ { MAD_F(0x067623c0) /* 0.403842688 */, 18 },
- /* 5870 */ { MAD_F(0x067683f4) /* 0.403934437 */, 18 },
- /* 5871 */ { MAD_F(0x0676e42a) /* 0.404026190 */, 18 },
-
- /* 5872 */ { MAD_F(0x06774462) /* 0.404117949 */, 18 },
- /* 5873 */ { MAD_F(0x0677a49b) /* 0.404209714 */, 18 },
- /* 5874 */ { MAD_F(0x067804d5) /* 0.404301483 */, 18 },
- /* 5875 */ { MAD_F(0x06786510) /* 0.404393258 */, 18 },
- /* 5876 */ { MAD_F(0x0678c54d) /* 0.404485037 */, 18 },
- /* 5877 */ { MAD_F(0x0679258c) /* 0.404576822 */, 18 },
- /* 5878 */ { MAD_F(0x067985cb) /* 0.404668613 */, 18 },
- /* 5879 */ { MAD_F(0x0679e60c) /* 0.404760408 */, 18 },
- /* 5880 */ { MAD_F(0x067a464f) /* 0.404852209 */, 18 },
- /* 5881 */ { MAD_F(0x067aa693) /* 0.404944014 */, 18 },
- /* 5882 */ { MAD_F(0x067b06d8) /* 0.405035825 */, 18 },
- /* 5883 */ { MAD_F(0x067b671f) /* 0.405127642 */, 18 },
- /* 5884 */ { MAD_F(0x067bc767) /* 0.405219463 */, 18 },
- /* 5885 */ { MAD_F(0x067c27b1) /* 0.405311290 */, 18 },
- /* 5886 */ { MAD_F(0x067c87fc) /* 0.405403122 */, 18 },
- /* 5887 */ { MAD_F(0x067ce848) /* 0.405494959 */, 18 },
-
- /* 5888 */ { MAD_F(0x067d4896) /* 0.405586801 */, 18 },
- /* 5889 */ { MAD_F(0x067da8e5) /* 0.405678648 */, 18 },
- /* 5890 */ { MAD_F(0x067e0935) /* 0.405770501 */, 18 },
- /* 5891 */ { MAD_F(0x067e6987) /* 0.405862359 */, 18 },
- /* 5892 */ { MAD_F(0x067ec9da) /* 0.405954222 */, 18 },
- /* 5893 */ { MAD_F(0x067f2a2f) /* 0.406046090 */, 18 },
- /* 5894 */ { MAD_F(0x067f8a85) /* 0.406137963 */, 18 },
- /* 5895 */ { MAD_F(0x067feadd) /* 0.406229842 */, 18 },
- /* 5896 */ { MAD_F(0x06804b36) /* 0.406321726 */, 18 },
- /* 5897 */ { MAD_F(0x0680ab90) /* 0.406413615 */, 18 },
- /* 5898 */ { MAD_F(0x06810beb) /* 0.406505509 */, 18 },
- /* 5899 */ { MAD_F(0x06816c49) /* 0.406597408 */, 18 },
- /* 5900 */ { MAD_F(0x0681cca7) /* 0.406689313 */, 18 },
- /* 5901 */ { MAD_F(0x06822d07) /* 0.406781223 */, 18 },
- /* 5902 */ { MAD_F(0x06828d68) /* 0.406873138 */, 18 },
- /* 5903 */ { MAD_F(0x0682edcb) /* 0.406965058 */, 18 },
-
- /* 5904 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 18 },
- /* 5905 */ { MAD_F(0x0683ae94) /* 0.407148914 */, 18 },
- /* 5906 */ { MAD_F(0x06840efb) /* 0.407240850 */, 18 },
- /* 5907 */ { MAD_F(0x06846f63) /* 0.407332791 */, 18 },
- /* 5908 */ { MAD_F(0x0684cfcd) /* 0.407424737 */, 18 },
- /* 5909 */ { MAD_F(0x06853038) /* 0.407516688 */, 18 },
- /* 5910 */ { MAD_F(0x068590a4) /* 0.407608645 */, 18 },
- /* 5911 */ { MAD_F(0x0685f112) /* 0.407700606 */, 18 },
- /* 5912 */ { MAD_F(0x06865181) /* 0.407792573 */, 18 },
- /* 5913 */ { MAD_F(0x0686b1f2) /* 0.407884545 */, 18 },
- /* 5914 */ { MAD_F(0x06871264) /* 0.407976522 */, 18 },
- /* 5915 */ { MAD_F(0x068772d7) /* 0.408068505 */, 18 },
- /* 5916 */ { MAD_F(0x0687d34c) /* 0.408160492 */, 18 },
- /* 5917 */ { MAD_F(0x068833c2) /* 0.408252485 */, 18 },
- /* 5918 */ { MAD_F(0x06889439) /* 0.408344483 */, 18 },
- /* 5919 */ { MAD_F(0x0688f4b2) /* 0.408436486 */, 18 },
-
- /* 5920 */ { MAD_F(0x0689552c) /* 0.408528495 */, 18 },
- /* 5921 */ { MAD_F(0x0689b5a8) /* 0.408620508 */, 18 },
- /* 5922 */ { MAD_F(0x068a1625) /* 0.408712527 */, 18 },
- /* 5923 */ { MAD_F(0x068a76a4) /* 0.408804551 */, 18 },
- /* 5924 */ { MAD_F(0x068ad724) /* 0.408896580 */, 18 },
- /* 5925 */ { MAD_F(0x068b37a5) /* 0.408988614 */, 18 },
- /* 5926 */ { MAD_F(0x068b9827) /* 0.409080653 */, 18 },
- /* 5927 */ { MAD_F(0x068bf8ac) /* 0.409172698 */, 18 },
- /* 5928 */ { MAD_F(0x068c5931) /* 0.409264748 */, 18 },
- /* 5929 */ { MAD_F(0x068cb9b8) /* 0.409356803 */, 18 },
- /* 5930 */ { MAD_F(0x068d1a40) /* 0.409448863 */, 18 },
- /* 5931 */ { MAD_F(0x068d7aca) /* 0.409540928 */, 18 },
- /* 5932 */ { MAD_F(0x068ddb54) /* 0.409632999 */, 18 },
- /* 5933 */ { MAD_F(0x068e3be1) /* 0.409725074 */, 18 },
- /* 5934 */ { MAD_F(0x068e9c6f) /* 0.409817155 */, 18 },
- /* 5935 */ { MAD_F(0x068efcfe) /* 0.409909241 */, 18 },
-
- /* 5936 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 18 },
- /* 5937 */ { MAD_F(0x068fbe20) /* 0.410093428 */, 18 },
- /* 5938 */ { MAD_F(0x06901eb4) /* 0.410185530 */, 18 },
- /* 5939 */ { MAD_F(0x06907f48) /* 0.410277637 */, 18 },
- /* 5940 */ { MAD_F(0x0690dfde) /* 0.410369748 */, 18 },
- /* 5941 */ { MAD_F(0x06914076) /* 0.410461865 */, 18 },
- /* 5942 */ { MAD_F(0x0691a10f) /* 0.410553988 */, 18 },
- /* 5943 */ { MAD_F(0x069201a9) /* 0.410646115 */, 18 },
- /* 5944 */ { MAD_F(0x06926245) /* 0.410738247 */, 18 },
- /* 5945 */ { MAD_F(0x0692c2e2) /* 0.410830385 */, 18 },
- /* 5946 */ { MAD_F(0x06932380) /* 0.410922528 */, 18 },
- /* 5947 */ { MAD_F(0x06938420) /* 0.411014676 */, 18 },
- /* 5948 */ { MAD_F(0x0693e4c1) /* 0.411106829 */, 18 },
- /* 5949 */ { MAD_F(0x06944563) /* 0.411198987 */, 18 },
- /* 5950 */ { MAD_F(0x0694a607) /* 0.411291151 */, 18 },
- /* 5951 */ { MAD_F(0x069506ad) /* 0.411383320 */, 18 },
-
- /* 5952 */ { MAD_F(0x06956753) /* 0.411475493 */, 18 },
- /* 5953 */ { MAD_F(0x0695c7fc) /* 0.411567672 */, 18 },
- /* 5954 */ { MAD_F(0x069628a5) /* 0.411659857 */, 18 },
- /* 5955 */ { MAD_F(0x06968950) /* 0.411752046 */, 18 },
- /* 5956 */ { MAD_F(0x0696e9fc) /* 0.411844240 */, 18 },
- /* 5957 */ { MAD_F(0x06974aaa) /* 0.411936440 */, 18 },
- /* 5958 */ { MAD_F(0x0697ab59) /* 0.412028645 */, 18 },
- /* 5959 */ { MAD_F(0x06980c09) /* 0.412120855 */, 18 },
- /* 5960 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 18 },
- /* 5961 */ { MAD_F(0x0698cd6e) /* 0.412305290 */, 18 },
- /* 5962 */ { MAD_F(0x06992e23) /* 0.412397516 */, 18 },
- /* 5963 */ { MAD_F(0x06998ed9) /* 0.412489746 */, 18 },
- /* 5964 */ { MAD_F(0x0699ef90) /* 0.412581982 */, 18 },
- /* 5965 */ { MAD_F(0x069a5049) /* 0.412674223 */, 18 },
- /* 5966 */ { MAD_F(0x069ab103) /* 0.412766469 */, 18 },
- /* 5967 */ { MAD_F(0x069b11bf) /* 0.412858720 */, 18 },
-
- /* 5968 */ { MAD_F(0x069b727b) /* 0.412950976 */, 18 },
- /* 5969 */ { MAD_F(0x069bd33a) /* 0.413043238 */, 18 },
- /* 5970 */ { MAD_F(0x069c33f9) /* 0.413135505 */, 18 },
- /* 5971 */ { MAD_F(0x069c94ba) /* 0.413227776 */, 18 },
- /* 5972 */ { MAD_F(0x069cf57d) /* 0.413320053 */, 18 },
- /* 5973 */ { MAD_F(0x069d5641) /* 0.413412335 */, 18 },
- /* 5974 */ { MAD_F(0x069db706) /* 0.413504623 */, 18 },
- /* 5975 */ { MAD_F(0x069e17cc) /* 0.413596915 */, 18 },
- /* 5976 */ { MAD_F(0x069e7894) /* 0.413689213 */, 18 },
- /* 5977 */ { MAD_F(0x069ed95e) /* 0.413781515 */, 18 },
- /* 5978 */ { MAD_F(0x069f3a28) /* 0.413873823 */, 18 },
- /* 5979 */ { MAD_F(0x069f9af4) /* 0.413966136 */, 18 },
- /* 5980 */ { MAD_F(0x069ffbc2) /* 0.414058454 */, 18 },
- /* 5981 */ { MAD_F(0x06a05c91) /* 0.414150778 */, 18 },
- /* 5982 */ { MAD_F(0x06a0bd61) /* 0.414243106 */, 18 },
- /* 5983 */ { MAD_F(0x06a11e32) /* 0.414335440 */, 18 },
-
- /* 5984 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 18 },
- /* 5985 */ { MAD_F(0x06a1dfda) /* 0.414520122 */, 18 },
- /* 5986 */ { MAD_F(0x06a240b0) /* 0.414612471 */, 18 },
- /* 5987 */ { MAD_F(0x06a2a187) /* 0.414704826 */, 18 },
- /* 5988 */ { MAD_F(0x06a3025f) /* 0.414797185 */, 18 },
- /* 5989 */ { MAD_F(0x06a36339) /* 0.414889549 */, 18 },
- /* 5990 */ { MAD_F(0x06a3c414) /* 0.414981919 */, 18 },
- /* 5991 */ { MAD_F(0x06a424f1) /* 0.415074294 */, 18 },
- /* 5992 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 18 },
- /* 5993 */ { MAD_F(0x06a4e6ae) /* 0.415259059 */, 18 },
- /* 5994 */ { MAD_F(0x06a5478f) /* 0.415351449 */, 18 },
- /* 5995 */ { MAD_F(0x06a5a871) /* 0.415443844 */, 18 },
- /* 5996 */ { MAD_F(0x06a60955) /* 0.415536244 */, 18 },
- /* 5997 */ { MAD_F(0x06a66a3a) /* 0.415628650 */, 18 },
- /* 5998 */ { MAD_F(0x06a6cb20) /* 0.415721061 */, 18 },
- /* 5999 */ { MAD_F(0x06a72c08) /* 0.415813476 */, 18 },
-
- /* 6000 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 18 },
- /* 6001 */ { MAD_F(0x06a7eddb) /* 0.415998324 */, 18 },
- /* 6002 */ { MAD_F(0x06a84ec7) /* 0.416090755 */, 18 },
- /* 6003 */ { MAD_F(0x06a8afb4) /* 0.416183191 */, 18 },
- /* 6004 */ { MAD_F(0x06a910a3) /* 0.416275633 */, 18 },
- /* 6005 */ { MAD_F(0x06a97193) /* 0.416368079 */, 18 },
- /* 6006 */ { MAD_F(0x06a9d284) /* 0.416460531 */, 18 },
- /* 6007 */ { MAD_F(0x06aa3377) /* 0.416552988 */, 18 },
- /* 6008 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 18 },
- /* 6009 */ { MAD_F(0x06aaf561) /* 0.416737917 */, 18 },
- /* 6010 */ { MAD_F(0x06ab5657) /* 0.416830389 */, 18 },
- /* 6011 */ { MAD_F(0x06abb750) /* 0.416922867 */, 18 },
- /* 6012 */ { MAD_F(0x06ac1849) /* 0.417015349 */, 18 },
- /* 6013 */ { MAD_F(0x06ac7944) /* 0.417107837 */, 18 },
- /* 6014 */ { MAD_F(0x06acda41) /* 0.417200330 */, 18 },
- /* 6015 */ { MAD_F(0x06ad3b3e) /* 0.417292828 */, 18 },
-
- /* 6016 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 18 },
- /* 6017 */ { MAD_F(0x06adfd3e) /* 0.417477839 */, 18 },
- /* 6018 */ { MAD_F(0x06ae5e40) /* 0.417570352 */, 18 },
- /* 6019 */ { MAD_F(0x06aebf43) /* 0.417662871 */, 18 },
- /* 6020 */ { MAD_F(0x06af2047) /* 0.417755394 */, 18 },
- /* 6021 */ { MAD_F(0x06af814d) /* 0.417847923 */, 18 },
- /* 6022 */ { MAD_F(0x06afe255) /* 0.417940457 */, 18 },
- /* 6023 */ { MAD_F(0x06b0435e) /* 0.418032996 */, 18 },
- /* 6024 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 18 },
- /* 6025 */ { MAD_F(0x06b10573) /* 0.418218089 */, 18 },
- /* 6026 */ { MAD_F(0x06b16680) /* 0.418310643 */, 18 },
- /* 6027 */ { MAD_F(0x06b1c78e) /* 0.418403203 */, 18 },
- /* 6028 */ { MAD_F(0x06b2289e) /* 0.418495767 */, 18 },
- /* 6029 */ { MAD_F(0x06b289af) /* 0.418588337 */, 18 },
- /* 6030 */ { MAD_F(0x06b2eac1) /* 0.418680911 */, 18 },
- /* 6031 */ { MAD_F(0x06b34bd5) /* 0.418773491 */, 18 },
-
- /* 6032 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 18 },
- /* 6033 */ { MAD_F(0x06b40e00) /* 0.418958666 */, 18 },
- /* 6034 */ { MAD_F(0x06b46f18) /* 0.419051262 */, 18 },
- /* 6035 */ { MAD_F(0x06b4d031) /* 0.419143862 */, 18 },
- /* 6036 */ { MAD_F(0x06b5314c) /* 0.419236467 */, 18 },
- /* 6037 */ { MAD_F(0x06b59268) /* 0.419329078 */, 18 },
- /* 6038 */ { MAD_F(0x06b5f385) /* 0.419421694 */, 18 },
- /* 6039 */ { MAD_F(0x06b654a4) /* 0.419514314 */, 18 },
- /* 6040 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 18 },
- /* 6041 */ { MAD_F(0x06b716e6) /* 0.419699571 */, 18 },
- /* 6042 */ { MAD_F(0x06b77808) /* 0.419792208 */, 18 },
- /* 6043 */ { MAD_F(0x06b7d92d) /* 0.419884849 */, 18 },
- /* 6044 */ { MAD_F(0x06b83a52) /* 0.419977495 */, 18 },
- /* 6045 */ { MAD_F(0x06b89b79) /* 0.420070147 */, 18 },
- /* 6046 */ { MAD_F(0x06b8fca1) /* 0.420162803 */, 18 },
- /* 6047 */ { MAD_F(0x06b95dcb) /* 0.420255465 */, 18 },
-
- /* 6048 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 18 },
- /* 6049 */ { MAD_F(0x06ba2023) /* 0.420440803 */, 18 },
- /* 6050 */ { MAD_F(0x06ba8150) /* 0.420533481 */, 18 },
- /* 6051 */ { MAD_F(0x06bae280) /* 0.420626163 */, 18 },
- /* 6052 */ { MAD_F(0x06bb43b0) /* 0.420718850 */, 18 },
- /* 6053 */ { MAD_F(0x06bba4e2) /* 0.420811542 */, 18 },
- /* 6054 */ { MAD_F(0x06bc0615) /* 0.420904240 */, 18 },
- /* 6055 */ { MAD_F(0x06bc674a) /* 0.420996942 */, 18 },
- /* 6056 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 18 },
- /* 6057 */ { MAD_F(0x06bd29b7) /* 0.421182362 */, 18 },
- /* 6058 */ { MAD_F(0x06bd8af0) /* 0.421275080 */, 18 },
- /* 6059 */ { MAD_F(0x06bdec2a) /* 0.421367803 */, 18 },
- /* 6060 */ { MAD_F(0x06be4d66) /* 0.421460531 */, 18 },
- /* 6061 */ { MAD_F(0x06beaea3) /* 0.421553264 */, 18 },
- /* 6062 */ { MAD_F(0x06bf0fe1) /* 0.421646003 */, 18 },
- /* 6063 */ { MAD_F(0x06bf7120) /* 0.421738746 */, 18 },
-
- /* 6064 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 18 },
- /* 6065 */ { MAD_F(0x06c033a4) /* 0.421924248 */, 18 },
- /* 6066 */ { MAD_F(0x06c094e7) /* 0.422017007 */, 18 },
- /* 6067 */ { MAD_F(0x06c0f62c) /* 0.422109770 */, 18 },
- /* 6068 */ { MAD_F(0x06c15773) /* 0.422202539 */, 18 },
- /* 6069 */ { MAD_F(0x06c1b8bb) /* 0.422295313 */, 18 },
- /* 6070 */ { MAD_F(0x06c21a04) /* 0.422388092 */, 18 },
- /* 6071 */ { MAD_F(0x06c27b4e) /* 0.422480876 */, 18 },
- /* 6072 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 18 },
- /* 6073 */ { MAD_F(0x06c33de8) /* 0.422666460 */, 18 },
- /* 6074 */ { MAD_F(0x06c39f36) /* 0.422759259 */, 18 },
- /* 6075 */ { MAD_F(0x06c40086) /* 0.422852064 */, 18 },
- /* 6076 */ { MAD_F(0x06c461d8) /* 0.422944873 */, 18 },
- /* 6077 */ { MAD_F(0x06c4c32a) /* 0.423037688 */, 18 },
- /* 6078 */ { MAD_F(0x06c5247f) /* 0.423130508 */, 18 },
- /* 6079 */ { MAD_F(0x06c585d4) /* 0.423223333 */, 18 },
-
- /* 6080 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 18 },
- /* 6081 */ { MAD_F(0x06c64883) /* 0.423408997 */, 18 },
- /* 6082 */ { MAD_F(0x06c6a9dd) /* 0.423501838 */, 18 },
- /* 6083 */ { MAD_F(0x06c70b38) /* 0.423594683 */, 18 },
- /* 6084 */ { MAD_F(0x06c76c94) /* 0.423687533 */, 18 },
- /* 6085 */ { MAD_F(0x06c7cdf2) /* 0.423780389 */, 18 },
- /* 6086 */ { MAD_F(0x06c82f51) /* 0.423873249 */, 18 },
- /* 6087 */ { MAD_F(0x06c890b1) /* 0.423966115 */, 18 },
- /* 6088 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 18 },
- /* 6089 */ { MAD_F(0x06c95376) /* 0.424151861 */, 18 },
- /* 6090 */ { MAD_F(0x06c9b4da) /* 0.424244742 */, 18 },
- /* 6091 */ { MAD_F(0x06ca1640) /* 0.424337628 */, 18 },
- /* 6092 */ { MAD_F(0x06ca77a8) /* 0.424430519 */, 18 },
- /* 6093 */ { MAD_F(0x06cad910) /* 0.424523415 */, 18 },
- /* 6094 */ { MAD_F(0x06cb3a7a) /* 0.424616316 */, 18 },
- /* 6095 */ { MAD_F(0x06cb9be5) /* 0.424709222 */, 18 },
-
- /* 6096 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 18 },
- /* 6097 */ { MAD_F(0x06cc5ec0) /* 0.424895050 */, 18 },
- /* 6098 */ { MAD_F(0x06ccc030) /* 0.424987971 */, 18 },
- /* 6099 */ { MAD_F(0x06cd21a0) /* 0.425080898 */, 18 },
- /* 6100 */ { MAD_F(0x06cd8313) /* 0.425173829 */, 18 },
- /* 6101 */ { MAD_F(0x06cde486) /* 0.425266766 */, 18 },
- /* 6102 */ { MAD_F(0x06ce45fb) /* 0.425359708 */, 18 },
- /* 6103 */ { MAD_F(0x06cea771) /* 0.425452655 */, 18 },
- /* 6104 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 18 },
- /* 6105 */ { MAD_F(0x06cf6a62) /* 0.425638564 */, 18 },
- /* 6106 */ { MAD_F(0x06cfcbdc) /* 0.425731526 */, 18 },
- /* 6107 */ { MAD_F(0x06d02d58) /* 0.425824493 */, 18 },
- /* 6108 */ { MAD_F(0x06d08ed5) /* 0.425917465 */, 18 },
- /* 6109 */ { MAD_F(0x06d0f053) /* 0.426010443 */, 18 },
- /* 6110 */ { MAD_F(0x06d151d3) /* 0.426103425 */, 18 },
- /* 6111 */ { MAD_F(0x06d1b354) /* 0.426196412 */, 18 },
-
- /* 6112 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 18 },
- /* 6113 */ { MAD_F(0x06d2765a) /* 0.426382403 */, 18 },
- /* 6114 */ { MAD_F(0x06d2d7e0) /* 0.426475405 */, 18 },
- /* 6115 */ { MAD_F(0x06d33966) /* 0.426568413 */, 18 },
- /* 6116 */ { MAD_F(0x06d39aee) /* 0.426661426 */, 18 },
- /* 6117 */ { MAD_F(0x06d3fc77) /* 0.426754444 */, 18 },
- /* 6118 */ { MAD_F(0x06d45e02) /* 0.426847467 */, 18 },
- /* 6119 */ { MAD_F(0x06d4bf8e) /* 0.426940495 */, 18 },
- /* 6120 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 18 },
- /* 6121 */ { MAD_F(0x06d582aa) /* 0.427126566 */, 18 },
- /* 6122 */ { MAD_F(0x06d5e43a) /* 0.427219609 */, 18 },
- /* 6123 */ { MAD_F(0x06d645cc) /* 0.427312657 */, 18 },
- /* 6124 */ { MAD_F(0x06d6a75f) /* 0.427405711 */, 18 },
- /* 6125 */ { MAD_F(0x06d708f3) /* 0.427498769 */, 18 },
- /* 6126 */ { MAD_F(0x06d76a88) /* 0.427591833 */, 18 },
- /* 6127 */ { MAD_F(0x06d7cc1f) /* 0.427684901 */, 18 },
-
- /* 6128 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 18 },
- /* 6129 */ { MAD_F(0x06d88f51) /* 0.427871054 */, 18 },
- /* 6130 */ { MAD_F(0x06d8f0ec) /* 0.427964137 */, 18 },
- /* 6131 */ { MAD_F(0x06d95288) /* 0.428057226 */, 18 },
- /* 6132 */ { MAD_F(0x06d9b426) /* 0.428150320 */, 18 },
- /* 6133 */ { MAD_F(0x06da15c5) /* 0.428243419 */, 18 },
- /* 6134 */ { MAD_F(0x06da7766) /* 0.428336523 */, 18 },
- /* 6135 */ { MAD_F(0x06dad907) /* 0.428429632 */, 18 },
- /* 6136 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 18 },
- /* 6137 */ { MAD_F(0x06db9c4f) /* 0.428615865 */, 18 },
- /* 6138 */ { MAD_F(0x06dbfdf5) /* 0.428708989 */, 18 },
- /* 6139 */ { MAD_F(0x06dc5f9c) /* 0.428802119 */, 18 },
- /* 6140 */ { MAD_F(0x06dcc145) /* 0.428895253 */, 18 },
- /* 6141 */ { MAD_F(0x06dd22ee) /* 0.428988392 */, 18 },
- /* 6142 */ { MAD_F(0x06dd849a) /* 0.429081537 */, 18 },
- /* 6143 */ { MAD_F(0x06dde646) /* 0.429174686 */, 18 },
-
- /* 6144 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 18 },
- /* 6145 */ { MAD_F(0x06dea9a4) /* 0.429361001 */, 18 },
- /* 6146 */ { MAD_F(0x06df0b54) /* 0.429454165 */, 18 },
- /* 6147 */ { MAD_F(0x06df6d06) /* 0.429547335 */, 18 },
- /* 6148 */ { MAD_F(0x06dfceba) /* 0.429640510 */, 18 },
- /* 6149 */ { MAD_F(0x06e0306f) /* 0.429733690 */, 18 },
- /* 6150 */ { MAD_F(0x06e09225) /* 0.429826874 */, 18 },
- /* 6151 */ { MAD_F(0x06e0f3dc) /* 0.429920064 */, 18 },
- /* 6152 */ { MAD_F(0x06e15595) /* 0.430013259 */, 18 },
- /* 6153 */ { MAD_F(0x06e1b74f) /* 0.430106459 */, 18 },
- /* 6154 */ { MAD_F(0x06e2190b) /* 0.430199664 */, 18 },
- /* 6155 */ { MAD_F(0x06e27ac8) /* 0.430292875 */, 18 },
- /* 6156 */ { MAD_F(0x06e2dc86) /* 0.430386090 */, 18 },
- /* 6157 */ { MAD_F(0x06e33e46) /* 0.430479310 */, 18 },
- /* 6158 */ { MAD_F(0x06e3a007) /* 0.430572535 */, 18 },
- /* 6159 */ { MAD_F(0x06e401c9) /* 0.430665765 */, 18 },
-
- /* 6160 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 18 },
- /* 6161 */ { MAD_F(0x06e4c552) /* 0.430852241 */, 18 },
- /* 6162 */ { MAD_F(0x06e52718) /* 0.430945487 */, 18 },
- /* 6163 */ { MAD_F(0x06e588e0) /* 0.431038737 */, 18 },
- /* 6164 */ { MAD_F(0x06e5eaa9) /* 0.431131993 */, 18 },
- /* 6165 */ { MAD_F(0x06e64c73) /* 0.431225253 */, 18 },
- /* 6166 */ { MAD_F(0x06e6ae3f) /* 0.431318519 */, 18 },
- /* 6167 */ { MAD_F(0x06e7100c) /* 0.431411790 */, 18 },
- /* 6168 */ { MAD_F(0x06e771db) /* 0.431505065 */, 18 },
- /* 6169 */ { MAD_F(0x06e7d3ab) /* 0.431598346 */, 18 },
- /* 6170 */ { MAD_F(0x06e8357c) /* 0.431691632 */, 18 },
- /* 6171 */ { MAD_F(0x06e8974e) /* 0.431784923 */, 18 },
- /* 6172 */ { MAD_F(0x06e8f922) /* 0.431878218 */, 18 },
- /* 6173 */ { MAD_F(0x06e95af8) /* 0.431971519 */, 18 },
- /* 6174 */ { MAD_F(0x06e9bcce) /* 0.432064825 */, 18 },
- /* 6175 */ { MAD_F(0x06ea1ea6) /* 0.432158136 */, 18 },
-
- /* 6176 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 18 },
- /* 6177 */ { MAD_F(0x06eae25a) /* 0.432344773 */, 18 },
- /* 6178 */ { MAD_F(0x06eb4436) /* 0.432438099 */, 18 },
- /* 6179 */ { MAD_F(0x06eba614) /* 0.432531431 */, 18 },
- /* 6180 */ { MAD_F(0x06ec07f2) /* 0.432624767 */, 18 },
- /* 6181 */ { MAD_F(0x06ec69d2) /* 0.432718108 */, 18 },
- /* 6182 */ { MAD_F(0x06eccbb4) /* 0.432811454 */, 18 },
- /* 6183 */ { MAD_F(0x06ed2d97) /* 0.432904805 */, 18 },
- /* 6184 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 18 },
- /* 6185 */ { MAD_F(0x06edf160) /* 0.433091523 */, 18 },
- /* 6186 */ { MAD_F(0x06ee5347) /* 0.433184889 */, 18 },
- /* 6187 */ { MAD_F(0x06eeb52f) /* 0.433278261 */, 18 },
- /* 6188 */ { MAD_F(0x06ef1719) /* 0.433371637 */, 18 },
- /* 6189 */ { MAD_F(0x06ef7904) /* 0.433465019 */, 18 },
- /* 6190 */ { MAD_F(0x06efdaf0) /* 0.433558405 */, 18 },
- /* 6191 */ { MAD_F(0x06f03cde) /* 0.433651797 */, 18 },
-
- /* 6192 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 18 },
- /* 6193 */ { MAD_F(0x06f100bd) /* 0.433838595 */, 18 },
- /* 6194 */ { MAD_F(0x06f162ae) /* 0.433932001 */, 18 },
- /* 6195 */ { MAD_F(0x06f1c4a1) /* 0.434025413 */, 18 },
- /* 6196 */ { MAD_F(0x06f22696) /* 0.434118830 */, 18 },
- /* 6197 */ { MAD_F(0x06f2888b) /* 0.434212251 */, 18 },
- /* 6198 */ { MAD_F(0x06f2ea82) /* 0.434305678 */, 18 },
- /* 6199 */ { MAD_F(0x06f34c7b) /* 0.434399110 */, 18 },
- /* 6200 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 18 },
- /* 6201 */ { MAD_F(0x06f41070) /* 0.434585988 */, 18 },
- /* 6202 */ { MAD_F(0x06f4726c) /* 0.434679435 */, 18 },
- /* 6203 */ { MAD_F(0x06f4d46a) /* 0.434772887 */, 18 },
- /* 6204 */ { MAD_F(0x06f53669) /* 0.434866344 */, 18 },
- /* 6205 */ { MAD_F(0x06f59869) /* 0.434959806 */, 18 },
- /* 6206 */ { MAD_F(0x06f5fa6b) /* 0.435053272 */, 18 },
- /* 6207 */ { MAD_F(0x06f65c6e) /* 0.435146744 */, 18 },
-
- /* 6208 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 18 },
- /* 6209 */ { MAD_F(0x06f72079) /* 0.435333703 */, 18 },
- /* 6210 */ { MAD_F(0x06f78280) /* 0.435427190 */, 18 },
- /* 6211 */ { MAD_F(0x06f7e489) /* 0.435520682 */, 18 },
- /* 6212 */ { MAD_F(0x06f84693) /* 0.435614179 */, 18 },
- /* 6213 */ { MAD_F(0x06f8a89e) /* 0.435707681 */, 18 },
- /* 6214 */ { MAD_F(0x06f90aaa) /* 0.435801188 */, 18 },
- /* 6215 */ { MAD_F(0x06f96cb8) /* 0.435894700 */, 18 },
- /* 6216 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 18 },
- /* 6217 */ { MAD_F(0x06fa30d8) /* 0.436081739 */, 18 },
- /* 6218 */ { MAD_F(0x06fa92ea) /* 0.436175266 */, 18 },
- /* 6219 */ { MAD_F(0x06faf4fe) /* 0.436268799 */, 18 },
- /* 6220 */ { MAD_F(0x06fb5712) /* 0.436362336 */, 18 },
- /* 6221 */ { MAD_F(0x06fbb928) /* 0.436455878 */, 18 },
- /* 6222 */ { MAD_F(0x06fc1b40) /* 0.436549425 */, 18 },
- /* 6223 */ { MAD_F(0x06fc7d58) /* 0.436642977 */, 18 },
-
- /* 6224 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 18 },
- /* 6225 */ { MAD_F(0x06fd418e) /* 0.436830096 */, 18 },
- /* 6226 */ { MAD_F(0x06fda3ab) /* 0.436923664 */, 18 },
- /* 6227 */ { MAD_F(0x06fe05c9) /* 0.437017236 */, 18 },
- /* 6228 */ { MAD_F(0x06fe67e8) /* 0.437110813 */, 18 },
- /* 6229 */ { MAD_F(0x06feca09) /* 0.437204395 */, 18 },
- /* 6230 */ { MAD_F(0x06ff2c2b) /* 0.437297982 */, 18 },
- /* 6231 */ { MAD_F(0x06ff8e4f) /* 0.437391575 */, 18 },
- /* 6232 */ { MAD_F(0x06fff073) /* 0.437485172 */, 18 },
- /* 6233 */ { MAD_F(0x0700529a) /* 0.437578774 */, 18 },
- /* 6234 */ { MAD_F(0x0700b4c1) /* 0.437672381 */, 18 },
- /* 6235 */ { MAD_F(0x070116ea) /* 0.437765994 */, 18 },
- /* 6236 */ { MAD_F(0x07017914) /* 0.437859611 */, 18 },
- /* 6237 */ { MAD_F(0x0701db40) /* 0.437953233 */, 18 },
- /* 6238 */ { MAD_F(0x07023d6c) /* 0.438046860 */, 18 },
- /* 6239 */ { MAD_F(0x07029f9b) /* 0.438140493 */, 18 },
-
- /* 6240 */ { MAD_F(0x070301ca) /* 0.438234130 */, 18 },
- /* 6241 */ { MAD_F(0x070363fb) /* 0.438327772 */, 18 },
- /* 6242 */ { MAD_F(0x0703c62d) /* 0.438421419 */, 18 },
- /* 6243 */ { MAD_F(0x07042861) /* 0.438515072 */, 18 },
- /* 6244 */ { MAD_F(0x07048a96) /* 0.438608729 */, 18 },
- /* 6245 */ { MAD_F(0x0704eccc) /* 0.438702391 */, 18 },
- /* 6246 */ { MAD_F(0x07054f04) /* 0.438796059 */, 18 },
- /* 6247 */ { MAD_F(0x0705b13d) /* 0.438889731 */, 18 },
- /* 6248 */ { MAD_F(0x07061377) /* 0.438983408 */, 18 },
- /* 6249 */ { MAD_F(0x070675b3) /* 0.439077090 */, 18 },
- /* 6250 */ { MAD_F(0x0706d7f0) /* 0.439170778 */, 18 },
- /* 6251 */ { MAD_F(0x07073a2e) /* 0.439264470 */, 18 },
- /* 6252 */ { MAD_F(0x07079c6e) /* 0.439358167 */, 18 },
- /* 6253 */ { MAD_F(0x0707feaf) /* 0.439451869 */, 18 },
- /* 6254 */ { MAD_F(0x070860f1) /* 0.439545577 */, 18 },
- /* 6255 */ { MAD_F(0x0708c335) /* 0.439639289 */, 18 },
-
- /* 6256 */ { MAD_F(0x0709257a) /* 0.439733006 */, 18 },
- /* 6257 */ { MAD_F(0x070987c0) /* 0.439826728 */, 18 },
- /* 6258 */ { MAD_F(0x0709ea08) /* 0.439920456 */, 18 },
- /* 6259 */ { MAD_F(0x070a4c51) /* 0.440014188 */, 18 },
- /* 6260 */ { MAD_F(0x070aae9b) /* 0.440107925 */, 18 },
- /* 6261 */ { MAD_F(0x070b10e7) /* 0.440201667 */, 18 },
- /* 6262 */ { MAD_F(0x070b7334) /* 0.440295414 */, 18 },
- /* 6263 */ { MAD_F(0x070bd583) /* 0.440389167 */, 18 },
- /* 6264 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 18 },
- /* 6265 */ { MAD_F(0x070c9a23) /* 0.440576686 */, 18 },
- /* 6266 */ { MAD_F(0x070cfc76) /* 0.440670453 */, 18 },
- /* 6267 */ { MAD_F(0x070d5eca) /* 0.440764225 */, 18 },
- /* 6268 */ { MAD_F(0x070dc11f) /* 0.440858002 */, 18 },
- /* 6269 */ { MAD_F(0x070e2375) /* 0.440951784 */, 18 },
- /* 6270 */ { MAD_F(0x070e85cd) /* 0.441045572 */, 18 },
- /* 6271 */ { MAD_F(0x070ee826) /* 0.441139364 */, 18 },
-
- /* 6272 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 18 },
- /* 6273 */ { MAD_F(0x070facdc) /* 0.441326963 */, 18 },
- /* 6274 */ { MAD_F(0x07100f39) /* 0.441420770 */, 18 },
- /* 6275 */ { MAD_F(0x07107198) /* 0.441514582 */, 18 },
- /* 6276 */ { MAD_F(0x0710d3f8) /* 0.441608399 */, 18 },
- /* 6277 */ { MAD_F(0x07113659) /* 0.441702221 */, 18 },
- /* 6278 */ { MAD_F(0x071198bb) /* 0.441796048 */, 18 },
- /* 6279 */ { MAD_F(0x0711fb1f) /* 0.441889880 */, 18 },
- /* 6280 */ { MAD_F(0x07125d84) /* 0.441983717 */, 18 },
- /* 6281 */ { MAD_F(0x0712bfeb) /* 0.442077559 */, 18 },
- /* 6282 */ { MAD_F(0x07132253) /* 0.442171406 */, 18 },
- /* 6283 */ { MAD_F(0x071384bc) /* 0.442265257 */, 18 },
- /* 6284 */ { MAD_F(0x0713e726) /* 0.442359114 */, 18 },
- /* 6285 */ { MAD_F(0x07144992) /* 0.442452976 */, 18 },
- /* 6286 */ { MAD_F(0x0714abff) /* 0.442546843 */, 18 },
- /* 6287 */ { MAD_F(0x07150e6e) /* 0.442640715 */, 18 },
-
- /* 6288 */ { MAD_F(0x071570de) /* 0.442734592 */, 18 },
- /* 6289 */ { MAD_F(0x0715d34f) /* 0.442828473 */, 18 },
- /* 6290 */ { MAD_F(0x071635c1) /* 0.442922360 */, 18 },
- /* 6291 */ { MAD_F(0x07169835) /* 0.443016252 */, 18 },
- /* 6292 */ { MAD_F(0x0716faaa) /* 0.443110148 */, 18 },
- /* 6293 */ { MAD_F(0x07175d21) /* 0.443204050 */, 18 },
- /* 6294 */ { MAD_F(0x0717bf99) /* 0.443297957 */, 18 },
- /* 6295 */ { MAD_F(0x07182212) /* 0.443391868 */, 18 },
- /* 6296 */ { MAD_F(0x0718848d) /* 0.443485785 */, 18 },
- /* 6297 */ { MAD_F(0x0718e709) /* 0.443579706 */, 18 },
- /* 6298 */ { MAD_F(0x07194986) /* 0.443673633 */, 18 },
- /* 6299 */ { MAD_F(0x0719ac04) /* 0.443767564 */, 18 },
- /* 6300 */ { MAD_F(0x071a0e84) /* 0.443861501 */, 18 },
- /* 6301 */ { MAD_F(0x071a7105) /* 0.443955442 */, 18 },
- /* 6302 */ { MAD_F(0x071ad388) /* 0.444049389 */, 18 },
- /* 6303 */ { MAD_F(0x071b360c) /* 0.444143340 */, 18 },
-
- /* 6304 */ { MAD_F(0x071b9891) /* 0.444237296 */, 18 },
- /* 6305 */ { MAD_F(0x071bfb18) /* 0.444331258 */, 18 },
- /* 6306 */ { MAD_F(0x071c5d9f) /* 0.444425224 */, 18 },
- /* 6307 */ { MAD_F(0x071cc029) /* 0.444519195 */, 18 },
- /* 6308 */ { MAD_F(0x071d22b3) /* 0.444613171 */, 18 },
- /* 6309 */ { MAD_F(0x071d853f) /* 0.444707153 */, 18 },
- /* 6310 */ { MAD_F(0x071de7cc) /* 0.444801139 */, 18 },
- /* 6311 */ { MAD_F(0x071e4a5b) /* 0.444895130 */, 18 },
- /* 6312 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 18 },
- /* 6313 */ { MAD_F(0x071f0f7c) /* 0.445083127 */, 18 },
- /* 6314 */ { MAD_F(0x071f720e) /* 0.445177133 */, 18 },
- /* 6315 */ { MAD_F(0x071fd4a2) /* 0.445271144 */, 18 },
- /* 6316 */ { MAD_F(0x07203737) /* 0.445365160 */, 18 },
- /* 6317 */ { MAD_F(0x072099ce) /* 0.445459181 */, 18 },
- /* 6318 */ { MAD_F(0x0720fc66) /* 0.445553206 */, 18 },
- /* 6319 */ { MAD_F(0x07215eff) /* 0.445647237 */, 18 },
-
- /* 6320 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 18 },
- /* 6321 */ { MAD_F(0x07222436) /* 0.445835314 */, 18 },
- /* 6322 */ { MAD_F(0x072286d3) /* 0.445929359 */, 18 },
- /* 6323 */ { MAD_F(0x0722e971) /* 0.446023410 */, 18 },
- /* 6324 */ { MAD_F(0x07234c11) /* 0.446117466 */, 18 },
- /* 6325 */ { MAD_F(0x0723aeb2) /* 0.446211526 */, 18 },
- /* 6326 */ { MAD_F(0x07241155) /* 0.446305592 */, 18 },
- /* 6327 */ { MAD_F(0x072473f9) /* 0.446399662 */, 18 },
- /* 6328 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 18 },
- /* 6329 */ { MAD_F(0x07253944) /* 0.446587818 */, 18 },
- /* 6330 */ { MAD_F(0x07259bec) /* 0.446681903 */, 18 },
- /* 6331 */ { MAD_F(0x0725fe95) /* 0.446775994 */, 18 },
- /* 6332 */ { MAD_F(0x07266140) /* 0.446870089 */, 18 },
- /* 6333 */ { MAD_F(0x0726c3ec) /* 0.446964189 */, 18 },
- /* 6334 */ { MAD_F(0x07272699) /* 0.447058294 */, 18 },
- /* 6335 */ { MAD_F(0x07278947) /* 0.447152404 */, 18 },
-
- /* 6336 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 18 },
- /* 6337 */ { MAD_F(0x07284ea8) /* 0.447340639 */, 18 },
- /* 6338 */ { MAD_F(0x0728b15b) /* 0.447434764 */, 18 },
- /* 6339 */ { MAD_F(0x0729140f) /* 0.447528894 */, 18 },
- /* 6340 */ { MAD_F(0x072976c4) /* 0.447623029 */, 18 },
- /* 6341 */ { MAD_F(0x0729d97a) /* 0.447717169 */, 18 },
- /* 6342 */ { MAD_F(0x072a3c32) /* 0.447811314 */, 18 },
- /* 6343 */ { MAD_F(0x072a9eeb) /* 0.447905463 */, 18 },
- /* 6344 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 18 },
- /* 6345 */ { MAD_F(0x072b6461) /* 0.448093778 */, 18 },
- /* 6346 */ { MAD_F(0x072bc71e) /* 0.448187942 */, 18 },
- /* 6347 */ { MAD_F(0x072c29dd) /* 0.448282112 */, 18 },
- /* 6348 */ { MAD_F(0x072c8c9d) /* 0.448376286 */, 18 },
- /* 6349 */ { MAD_F(0x072cef5e) /* 0.448470466 */, 18 },
- /* 6350 */ { MAD_F(0x072d5220) /* 0.448564650 */, 18 },
- /* 6351 */ { MAD_F(0x072db4e4) /* 0.448658839 */, 18 },
-
- /* 6352 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 18 },
- /* 6353 */ { MAD_F(0x072e7a6f) /* 0.448847233 */, 18 },
- /* 6354 */ { MAD_F(0x072edd37) /* 0.448941437 */, 18 },
- /* 6355 */ { MAD_F(0x072f4000) /* 0.449035646 */, 18 },
- /* 6356 */ { MAD_F(0x072fa2ca) /* 0.449129860 */, 18 },
- /* 6357 */ { MAD_F(0x07300596) /* 0.449224079 */, 18 },
- /* 6358 */ { MAD_F(0x07306863) /* 0.449318303 */, 18 },
- /* 6359 */ { MAD_F(0x0730cb32) /* 0.449412531 */, 18 },
- /* 6360 */ { MAD_F(0x07312e01) /* 0.449506765 */, 18 },
- /* 6361 */ { MAD_F(0x073190d2) /* 0.449601004 */, 18 },
- /* 6362 */ { MAD_F(0x0731f3a5) /* 0.449695247 */, 18 },
- /* 6363 */ { MAD_F(0x07325678) /* 0.449789496 */, 18 },
- /* 6364 */ { MAD_F(0x0732b94d) /* 0.449883749 */, 18 },
- /* 6365 */ { MAD_F(0x07331c23) /* 0.449978008 */, 18 },
- /* 6366 */ { MAD_F(0x07337efb) /* 0.450072271 */, 18 },
- /* 6367 */ { MAD_F(0x0733e1d4) /* 0.450166540 */, 18 },
-
- /* 6368 */ { MAD_F(0x073444ae) /* 0.450260813 */, 18 },
- /* 6369 */ { MAD_F(0x0734a78a) /* 0.450355091 */, 18 },
- /* 6370 */ { MAD_F(0x07350a67) /* 0.450449374 */, 18 },
- /* 6371 */ { MAD_F(0x07356d45) /* 0.450543662 */, 18 },
- /* 6372 */ { MAD_F(0x0735d025) /* 0.450637955 */, 18 },
- /* 6373 */ { MAD_F(0x07363306) /* 0.450732253 */, 18 },
- /* 6374 */ { MAD_F(0x073695e8) /* 0.450826556 */, 18 },
- /* 6375 */ { MAD_F(0x0736f8cb) /* 0.450920864 */, 18 },
- /* 6376 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 18 },
- /* 6377 */ { MAD_F(0x0737be96) /* 0.451109494 */, 18 },
- /* 6378 */ { MAD_F(0x0738217e) /* 0.451203817 */, 18 },
- /* 6379 */ { MAD_F(0x07388467) /* 0.451298144 */, 18 },
- /* 6380 */ { MAD_F(0x0738e751) /* 0.451392477 */, 18 },
- /* 6381 */ { MAD_F(0x07394a3d) /* 0.451486814 */, 18 },
- /* 6382 */ { MAD_F(0x0739ad29) /* 0.451581156 */, 18 },
- /* 6383 */ { MAD_F(0x073a1017) /* 0.451675503 */, 18 },
-
- /* 6384 */ { MAD_F(0x073a7307) /* 0.451769856 */, 18 },
- /* 6385 */ { MAD_F(0x073ad5f8) /* 0.451864213 */, 18 },
- /* 6386 */ { MAD_F(0x073b38ea) /* 0.451958575 */, 18 },
- /* 6387 */ { MAD_F(0x073b9bdd) /* 0.452052942 */, 18 },
- /* 6388 */ { MAD_F(0x073bfed2) /* 0.452147313 */, 18 },
- /* 6389 */ { MAD_F(0x073c61c8) /* 0.452241690 */, 18 },
- /* 6390 */ { MAD_F(0x073cc4bf) /* 0.452336072 */, 18 },
- /* 6391 */ { MAD_F(0x073d27b8) /* 0.452430458 */, 18 },
- /* 6392 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 18 },
- /* 6393 */ { MAD_F(0x073dedae) /* 0.452619246 */, 18 },
- /* 6394 */ { MAD_F(0x073e50aa) /* 0.452713648 */, 18 },
- /* 6395 */ { MAD_F(0x073eb3a8) /* 0.452808054 */, 18 },
- /* 6396 */ { MAD_F(0x073f16a8) /* 0.452902465 */, 18 },
- /* 6397 */ { MAD_F(0x073f79a8) /* 0.452996882 */, 18 },
- /* 6398 */ { MAD_F(0x073fdcaa) /* 0.453091303 */, 18 },
- /* 6399 */ { MAD_F(0x07403fad) /* 0.453185729 */, 18 },
-
- /* 6400 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 18 },
- /* 6401 */ { MAD_F(0x074105b8) /* 0.453374595 */, 18 },
- /* 6402 */ { MAD_F(0x074168bf) /* 0.453469036 */, 18 },
- /* 6403 */ { MAD_F(0x0741cbc8) /* 0.453563482 */, 18 },
- /* 6404 */ { MAD_F(0x07422ed2) /* 0.453657932 */, 18 },
- /* 6405 */ { MAD_F(0x074291dd) /* 0.453752388 */, 18 },
- /* 6406 */ { MAD_F(0x0742f4e9) /* 0.453846848 */, 18 },
- /* 6407 */ { MAD_F(0x074357f7) /* 0.453941314 */, 18 },
- /* 6408 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 18 },
- /* 6409 */ { MAD_F(0x07441e17) /* 0.454130259 */, 18 },
- /* 6410 */ { MAD_F(0x07448129) /* 0.454224739 */, 18 },
- /* 6411 */ { MAD_F(0x0744e43c) /* 0.454319224 */, 18 },
- /* 6412 */ { MAD_F(0x07454750) /* 0.454413714 */, 18 },
- /* 6413 */ { MAD_F(0x0745aa66) /* 0.454508209 */, 18 },
- /* 6414 */ { MAD_F(0x07460d7d) /* 0.454602708 */, 18 },
- /* 6415 */ { MAD_F(0x07467095) /* 0.454697213 */, 18 },
-
- /* 6416 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 18 },
- /* 6417 */ { MAD_F(0x074736ca) /* 0.454886237 */, 18 },
- /* 6418 */ { MAD_F(0x074799e7) /* 0.454980756 */, 18 },
- /* 6419 */ { MAD_F(0x0747fd04) /* 0.455075281 */, 18 },
- /* 6420 */ { MAD_F(0x07486023) /* 0.455169810 */, 18 },
- /* 6421 */ { MAD_F(0x0748c344) /* 0.455264344 */, 18 },
- /* 6422 */ { MAD_F(0x07492665) /* 0.455358883 */, 18 },
- /* 6423 */ { MAD_F(0x07498988) /* 0.455453427 */, 18 },
- /* 6424 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 18 },
- /* 6425 */ { MAD_F(0x074a4fd2) /* 0.455642529 */, 18 },
- /* 6426 */ { MAD_F(0x074ab2f9) /* 0.455737088 */, 18 },
- /* 6427 */ { MAD_F(0x074b1621) /* 0.455831652 */, 18 },
- /* 6428 */ { MAD_F(0x074b794b) /* 0.455926220 */, 18 },
- /* 6429 */ { MAD_F(0x074bdc75) /* 0.456020793 */, 18 },
- /* 6430 */ { MAD_F(0x074c3fa1) /* 0.456115372 */, 18 },
- /* 6431 */ { MAD_F(0x074ca2cf) /* 0.456209955 */, 18 },
-
- /* 6432 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 18 },
- /* 6433 */ { MAD_F(0x074d692e) /* 0.456399136 */, 18 },
- /* 6434 */ { MAD_F(0x074dcc5f) /* 0.456493733 */, 18 },
- /* 6435 */ { MAD_F(0x074e2f92) /* 0.456588336 */, 18 },
- /* 6436 */ { MAD_F(0x074e92c6) /* 0.456682944 */, 18 },
- /* 6437 */ { MAD_F(0x074ef5fb) /* 0.456777556 */, 18 },
- /* 6438 */ { MAD_F(0x074f5932) /* 0.456872174 */, 18 },
- /* 6439 */ { MAD_F(0x074fbc6a) /* 0.456966796 */, 18 },
- /* 6440 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 18 },
- /* 6441 */ { MAD_F(0x075082de) /* 0.457156056 */, 18 },
- /* 6442 */ { MAD_F(0x0750e61a) /* 0.457250693 */, 18 },
- /* 6443 */ { MAD_F(0x07514957) /* 0.457345335 */, 18 },
- /* 6444 */ { MAD_F(0x0751ac96) /* 0.457439981 */, 18 },
- /* 6445 */ { MAD_F(0x07520fd6) /* 0.457534633 */, 18 },
- /* 6446 */ { MAD_F(0x07527317) /* 0.457629290 */, 18 },
- /* 6447 */ { MAD_F(0x0752d659) /* 0.457723951 */, 18 },
-
- /* 6448 */ { MAD_F(0x0753399d) /* 0.457818618 */, 18 },
- /* 6449 */ { MAD_F(0x07539ce2) /* 0.457913289 */, 18 },
- /* 6450 */ { MAD_F(0x07540029) /* 0.458007965 */, 18 },
- /* 6451 */ { MAD_F(0x07546371) /* 0.458102646 */, 18 },
- /* 6452 */ { MAD_F(0x0754c6ba) /* 0.458197332 */, 18 },
- /* 6453 */ { MAD_F(0x07552a04) /* 0.458292023 */, 18 },
- /* 6454 */ { MAD_F(0x07558d50) /* 0.458386719 */, 18 },
- /* 6455 */ { MAD_F(0x0755f09d) /* 0.458481420 */, 18 },
- /* 6456 */ { MAD_F(0x075653eb) /* 0.458576125 */, 18 },
- /* 6457 */ { MAD_F(0x0756b73b) /* 0.458670836 */, 18 },
- /* 6458 */ { MAD_F(0x07571a8c) /* 0.458765551 */, 18 },
- /* 6459 */ { MAD_F(0x07577dde) /* 0.458860271 */, 18 },
- /* 6460 */ { MAD_F(0x0757e131) /* 0.458954996 */, 18 },
- /* 6461 */ { MAD_F(0x07584486) /* 0.459049726 */, 18 },
- /* 6462 */ { MAD_F(0x0758a7dd) /* 0.459144461 */, 18 },
- /* 6463 */ { MAD_F(0x07590b34) /* 0.459239201 */, 18 },
-
- /* 6464 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 18 },
- /* 6465 */ { MAD_F(0x0759d1e7) /* 0.459428695 */, 18 },
- /* 6466 */ { MAD_F(0x075a3542) /* 0.459523450 */, 18 },
- /* 6467 */ { MAD_F(0x075a989f) /* 0.459618209 */, 18 },
- /* 6468 */ { MAD_F(0x075afbfd) /* 0.459712973 */, 18 },
- /* 6469 */ { MAD_F(0x075b5f5d) /* 0.459807742 */, 18 },
- /* 6470 */ { MAD_F(0x075bc2bd) /* 0.459902516 */, 18 },
- /* 6471 */ { MAD_F(0x075c261f) /* 0.459997295 */, 18 },
- /* 6472 */ { MAD_F(0x075c8983) /* 0.460092079 */, 18 },
- /* 6473 */ { MAD_F(0x075cece7) /* 0.460186867 */, 18 },
- /* 6474 */ { MAD_F(0x075d504d) /* 0.460281661 */, 18 },
- /* 6475 */ { MAD_F(0x075db3b5) /* 0.460376459 */, 18 },
- /* 6476 */ { MAD_F(0x075e171d) /* 0.460471262 */, 18 },
- /* 6477 */ { MAD_F(0x075e7a87) /* 0.460566071 */, 18 },
- /* 6478 */ { MAD_F(0x075eddf2) /* 0.460660884 */, 18 },
- /* 6479 */ { MAD_F(0x075f415f) /* 0.460755701 */, 18 },
-
- /* 6480 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 18 },
- /* 6481 */ { MAD_F(0x0760083b) /* 0.460945352 */, 18 },
- /* 6482 */ { MAD_F(0x07606bac) /* 0.461040184 */, 18 },
- /* 6483 */ { MAD_F(0x0760cf1e) /* 0.461135022 */, 18 },
- /* 6484 */ { MAD_F(0x07613291) /* 0.461229864 */, 18 },
- /* 6485 */ { MAD_F(0x07619605) /* 0.461324711 */, 18 },
- /* 6486 */ { MAD_F(0x0761f97b) /* 0.461419563 */, 18 },
- /* 6487 */ { MAD_F(0x07625cf2) /* 0.461514420 */, 18 },
- /* 6488 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 18 },
- /* 6489 */ { MAD_F(0x076323e3) /* 0.461704149 */, 18 },
- /* 6490 */ { MAD_F(0x0763875e) /* 0.461799020 */, 18 },
- /* 6491 */ { MAD_F(0x0763eadb) /* 0.461893897 */, 18 },
- /* 6492 */ { MAD_F(0x07644e58) /* 0.461988778 */, 18 },
- /* 6493 */ { MAD_F(0x0764b1d7) /* 0.462083664 */, 18 },
- /* 6494 */ { MAD_F(0x07651557) /* 0.462178555 */, 18 },
- /* 6495 */ { MAD_F(0x076578d8) /* 0.462273451 */, 18 },
-
- /* 6496 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 18 },
- /* 6497 */ { MAD_F(0x07663fdf) /* 0.462463257 */, 18 },
- /* 6498 */ { MAD_F(0x0766a364) /* 0.462558168 */, 18 },
- /* 6499 */ { MAD_F(0x076706eb) /* 0.462653083 */, 18 },
- /* 6500 */ { MAD_F(0x07676a73) /* 0.462748003 */, 18 },
- /* 6501 */ { MAD_F(0x0767cdfc) /* 0.462842928 */, 18 },
- /* 6502 */ { MAD_F(0x07683187) /* 0.462937858 */, 18 },
- /* 6503 */ { MAD_F(0x07689513) /* 0.463032793 */, 18 },
- /* 6504 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 18 },
- /* 6505 */ { MAD_F(0x07695c2e) /* 0.463222678 */, 18 },
- /* 6506 */ { MAD_F(0x0769bfbe) /* 0.463317627 */, 18 },
- /* 6507 */ { MAD_F(0x076a234f) /* 0.463412581 */, 18 },
- /* 6508 */ { MAD_F(0x076a86e2) /* 0.463507540 */, 18 },
- /* 6509 */ { MAD_F(0x076aea75) /* 0.463602504 */, 18 },
- /* 6510 */ { MAD_F(0x076b4e0a) /* 0.463697473 */, 18 },
- /* 6511 */ { MAD_F(0x076bb1a1) /* 0.463792447 */, 18 },
-
- /* 6512 */ { MAD_F(0x076c1538) /* 0.463887426 */, 18 },
- /* 6513 */ { MAD_F(0x076c78d1) /* 0.463982409 */, 18 },
- /* 6514 */ { MAD_F(0x076cdc6c) /* 0.464077398 */, 18 },
- /* 6515 */ { MAD_F(0x076d4007) /* 0.464172391 */, 18 },
- /* 6516 */ { MAD_F(0x076da3a4) /* 0.464267389 */, 18 },
- /* 6517 */ { MAD_F(0x076e0742) /* 0.464362392 */, 18 },
- /* 6518 */ { MAD_F(0x076e6ae2) /* 0.464457399 */, 18 },
- /* 6519 */ { MAD_F(0x076ece82) /* 0.464552412 */, 18 },
- /* 6520 */ { MAD_F(0x076f3224) /* 0.464647430 */, 18 },
- /* 6521 */ { MAD_F(0x076f95c8) /* 0.464742452 */, 18 },
- /* 6522 */ { MAD_F(0x076ff96c) /* 0.464837479 */, 18 },
- /* 6523 */ { MAD_F(0x07705d12) /* 0.464932511 */, 18 },
- /* 6524 */ { MAD_F(0x0770c0ba) /* 0.465027548 */, 18 },
- /* 6525 */ { MAD_F(0x07712462) /* 0.465122590 */, 18 },
- /* 6526 */ { MAD_F(0x0771880c) /* 0.465217637 */, 18 },
- /* 6527 */ { MAD_F(0x0771ebb7) /* 0.465312688 */, 18 },
-
- /* 6528 */ { MAD_F(0x07724f64) /* 0.465407744 */, 18 },
- /* 6529 */ { MAD_F(0x0772b312) /* 0.465502806 */, 18 },
- /* 6530 */ { MAD_F(0x077316c1) /* 0.465597872 */, 18 },
- /* 6531 */ { MAD_F(0x07737a71) /* 0.465692943 */, 18 },
- /* 6532 */ { MAD_F(0x0773de23) /* 0.465788018 */, 18 },
- /* 6533 */ { MAD_F(0x077441d6) /* 0.465883099 */, 18 },
- /* 6534 */ { MAD_F(0x0774a58a) /* 0.465978184 */, 18 },
- /* 6535 */ { MAD_F(0x07750940) /* 0.466073275 */, 18 },
- /* 6536 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 18 },
- /* 6537 */ { MAD_F(0x0775d0af) /* 0.466263470 */, 18 },
- /* 6538 */ { MAD_F(0x07763468) /* 0.466358575 */, 18 },
- /* 6539 */ { MAD_F(0x07769823) /* 0.466453684 */, 18 },
- /* 6540 */ { MAD_F(0x0776fbdf) /* 0.466548799 */, 18 },
- /* 6541 */ { MAD_F(0x07775f9d) /* 0.466643918 */, 18 },
- /* 6542 */ { MAD_F(0x0777c35c) /* 0.466739043 */, 18 },
- /* 6543 */ { MAD_F(0x0778271c) /* 0.466834172 */, 18 },
-
- /* 6544 */ { MAD_F(0x07788add) /* 0.466929306 */, 18 },
- /* 6545 */ { MAD_F(0x0778ee9f) /* 0.467024445 */, 18 },
- /* 6546 */ { MAD_F(0x07795263) /* 0.467119588 */, 18 },
- /* 6547 */ { MAD_F(0x0779b629) /* 0.467214737 */, 18 },
- /* 6548 */ { MAD_F(0x077a19ef) /* 0.467309890 */, 18 },
- /* 6549 */ { MAD_F(0x077a7db7) /* 0.467405048 */, 18 },
- /* 6550 */ { MAD_F(0x077ae180) /* 0.467500211 */, 18 },
- /* 6551 */ { MAD_F(0x077b454b) /* 0.467595379 */, 18 },
- /* 6552 */ { MAD_F(0x077ba916) /* 0.467690552 */, 18 },
- /* 6553 */ { MAD_F(0x077c0ce3) /* 0.467785729 */, 18 },
- /* 6554 */ { MAD_F(0x077c70b2) /* 0.467880912 */, 18 },
- /* 6555 */ { MAD_F(0x077cd481) /* 0.467976099 */, 18 },
- /* 6556 */ { MAD_F(0x077d3852) /* 0.468071291 */, 18 },
- /* 6557 */ { MAD_F(0x077d9c24) /* 0.468166488 */, 18 },
- /* 6558 */ { MAD_F(0x077dfff8) /* 0.468261690 */, 18 },
- /* 6559 */ { MAD_F(0x077e63cd) /* 0.468356896 */, 18 },
-
- /* 6560 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 18 },
- /* 6561 */ { MAD_F(0x077f2b7a) /* 0.468547324 */, 18 },
- /* 6562 */ { MAD_F(0x077f8f53) /* 0.468642545 */, 18 },
- /* 6563 */ { MAD_F(0x077ff32d) /* 0.468737771 */, 18 },
- /* 6564 */ { MAD_F(0x07805708) /* 0.468833002 */, 18 },
- /* 6565 */ { MAD_F(0x0780bae5) /* 0.468928237 */, 18 },
- /* 6566 */ { MAD_F(0x07811ec3) /* 0.469023478 */, 18 },
- /* 6567 */ { MAD_F(0x078182a2) /* 0.469118723 */, 18 },
- /* 6568 */ { MAD_F(0x0781e683) /* 0.469213973 */, 18 },
- /* 6569 */ { MAD_F(0x07824a64) /* 0.469309228 */, 18 },
- /* 6570 */ { MAD_F(0x0782ae47) /* 0.469404488 */, 18 },
- /* 6571 */ { MAD_F(0x0783122c) /* 0.469499752 */, 18 },
- /* 6572 */ { MAD_F(0x07837612) /* 0.469595022 */, 18 },
- /* 6573 */ { MAD_F(0x0783d9f9) /* 0.469690296 */, 18 },
- /* 6574 */ { MAD_F(0x07843de1) /* 0.469785575 */, 18 },
- /* 6575 */ { MAD_F(0x0784a1ca) /* 0.469880859 */, 18 },
-
- /* 6576 */ { MAD_F(0x078505b5) /* 0.469976148 */, 18 },
- /* 6577 */ { MAD_F(0x078569a2) /* 0.470071442 */, 18 },
- /* 6578 */ { MAD_F(0x0785cd8f) /* 0.470166740 */, 18 },
- /* 6579 */ { MAD_F(0x0786317e) /* 0.470262043 */, 18 },
- /* 6580 */ { MAD_F(0x0786956e) /* 0.470357351 */, 18 },
- /* 6581 */ { MAD_F(0x0786f95f) /* 0.470452664 */, 18 },
- /* 6582 */ { MAD_F(0x07875d52) /* 0.470547982 */, 18 },
- /* 6583 */ { MAD_F(0x0787c146) /* 0.470643305 */, 18 },
- /* 6584 */ { MAD_F(0x0788253b) /* 0.470738632 */, 18 },
- /* 6585 */ { MAD_F(0x07888932) /* 0.470833964 */, 18 },
- /* 6586 */ { MAD_F(0x0788ed2a) /* 0.470929301 */, 18 },
- /* 6587 */ { MAD_F(0x07895123) /* 0.471024643 */, 18 },
- /* 6588 */ { MAD_F(0x0789b51d) /* 0.471119990 */, 18 },
- /* 6589 */ { MAD_F(0x078a1919) /* 0.471215341 */, 18 },
- /* 6590 */ { MAD_F(0x078a7d16) /* 0.471310698 */, 18 },
- /* 6591 */ { MAD_F(0x078ae114) /* 0.471406059 */, 18 },
-
- /* 6592 */ { MAD_F(0x078b4514) /* 0.471501425 */, 18 },
- /* 6593 */ { MAD_F(0x078ba915) /* 0.471596796 */, 18 },
- /* 6594 */ { MAD_F(0x078c0d17) /* 0.471692171 */, 18 },
- /* 6595 */ { MAD_F(0x078c711a) /* 0.471787552 */, 18 },
- /* 6596 */ { MAD_F(0x078cd51f) /* 0.471882937 */, 18 },
- /* 6597 */ { MAD_F(0x078d3925) /* 0.471978327 */, 18 },
- /* 6598 */ { MAD_F(0x078d9d2d) /* 0.472073722 */, 18 },
- /* 6599 */ { MAD_F(0x078e0135) /* 0.472169122 */, 18 },
- /* 6600 */ { MAD_F(0x078e653f) /* 0.472264527 */, 18 },
- /* 6601 */ { MAD_F(0x078ec94b) /* 0.472359936 */, 18 },
- /* 6602 */ { MAD_F(0x078f2d57) /* 0.472455350 */, 18 },
- /* 6603 */ { MAD_F(0x078f9165) /* 0.472550769 */, 18 },
- /* 6604 */ { MAD_F(0x078ff574) /* 0.472646193 */, 18 },
- /* 6605 */ { MAD_F(0x07905985) /* 0.472741622 */, 18 },
- /* 6606 */ { MAD_F(0x0790bd96) /* 0.472837055 */, 18 },
- /* 6607 */ { MAD_F(0x079121a9) /* 0.472932493 */, 18 },
-
- /* 6608 */ { MAD_F(0x079185be) /* 0.473027937 */, 18 },
- /* 6609 */ { MAD_F(0x0791e9d3) /* 0.473123384 */, 18 },
- /* 6610 */ { MAD_F(0x07924dea) /* 0.473218837 */, 18 },
- /* 6611 */ { MAD_F(0x0792b202) /* 0.473314295 */, 18 },
- /* 6612 */ { MAD_F(0x0793161c) /* 0.473409757 */, 18 },
- /* 6613 */ { MAD_F(0x07937a37) /* 0.473505224 */, 18 },
- /* 6614 */ { MAD_F(0x0793de53) /* 0.473600696 */, 18 },
- /* 6615 */ { MAD_F(0x07944270) /* 0.473696173 */, 18 },
- /* 6616 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 18 },
- /* 6617 */ { MAD_F(0x07950aaf) /* 0.473887141 */, 18 },
- /* 6618 */ { MAD_F(0x07956ed0) /* 0.473982632 */, 18 },
- /* 6619 */ { MAD_F(0x0795d2f2) /* 0.474078128 */, 18 },
- /* 6620 */ { MAD_F(0x07963716) /* 0.474173629 */, 18 },
- /* 6621 */ { MAD_F(0x07969b3b) /* 0.474269135 */, 18 },
- /* 6622 */ { MAD_F(0x0796ff62) /* 0.474364645 */, 18 },
- /* 6623 */ { MAD_F(0x07976389) /* 0.474460161 */, 18 },
-
- /* 6624 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 18 },
- /* 6625 */ { MAD_F(0x07982bdd) /* 0.474651205 */, 18 },
- /* 6626 */ { MAD_F(0x07989008) /* 0.474746735 */, 18 },
- /* 6627 */ { MAD_F(0x0798f435) /* 0.474842270 */, 18 },
- /* 6628 */ { MAD_F(0x07995863) /* 0.474937809 */, 18 },
- /* 6629 */ { MAD_F(0x0799bc92) /* 0.475033353 */, 18 },
- /* 6630 */ { MAD_F(0x079a20c3) /* 0.475128902 */, 18 },
- /* 6631 */ { MAD_F(0x079a84f5) /* 0.475224456 */, 18 },
- /* 6632 */ { MAD_F(0x079ae929) /* 0.475320014 */, 18 },
- /* 6633 */ { MAD_F(0x079b4d5d) /* 0.475415578 */, 18 },
- /* 6634 */ { MAD_F(0x079bb193) /* 0.475511146 */, 18 },
- /* 6635 */ { MAD_F(0x079c15ca) /* 0.475606719 */, 18 },
- /* 6636 */ { MAD_F(0x079c7a03) /* 0.475702296 */, 18 },
- /* 6637 */ { MAD_F(0x079cde3c) /* 0.475797879 */, 18 },
- /* 6638 */ { MAD_F(0x079d4277) /* 0.475893466 */, 18 },
- /* 6639 */ { MAD_F(0x079da6b4) /* 0.475989058 */, 18 },
-
- /* 6640 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 18 },
- /* 6641 */ { MAD_F(0x079e6f30) /* 0.476180257 */, 18 },
- /* 6642 */ { MAD_F(0x079ed370) /* 0.476275863 */, 18 },
- /* 6643 */ { MAD_F(0x079f37b2) /* 0.476371475 */, 18 },
- /* 6644 */ { MAD_F(0x079f9bf5) /* 0.476467091 */, 18 },
- /* 6645 */ { MAD_F(0x07a00039) /* 0.476562712 */, 18 },
- /* 6646 */ { MAD_F(0x07a0647e) /* 0.476658338 */, 18 },
- /* 6647 */ { MAD_F(0x07a0c8c5) /* 0.476753968 */, 18 },
- /* 6648 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 18 },
- /* 6649 */ { MAD_F(0x07a19156) /* 0.476945243 */, 18 },
- /* 6650 */ { MAD_F(0x07a1f5a0) /* 0.477040888 */, 18 },
- /* 6651 */ { MAD_F(0x07a259ec) /* 0.477136538 */, 18 },
- /* 6652 */ { MAD_F(0x07a2be39) /* 0.477232193 */, 18 },
- /* 6653 */ { MAD_F(0x07a32287) /* 0.477327852 */, 18 },
- /* 6654 */ { MAD_F(0x07a386d7) /* 0.477423516 */, 18 },
- /* 6655 */ { MAD_F(0x07a3eb28) /* 0.477519185 */, 18 },
-
- /* 6656 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 18 },
- /* 6657 */ { MAD_F(0x07a4b3ce) /* 0.477710537 */, 18 },
- /* 6658 */ { MAD_F(0x07a51822) /* 0.477806220 */, 18 },
- /* 6659 */ { MAD_F(0x07a57c78) /* 0.477901908 */, 18 },
- /* 6660 */ { MAD_F(0x07a5e0d0) /* 0.477997601 */, 18 },
- /* 6661 */ { MAD_F(0x07a64528) /* 0.478093299 */, 18 },
- /* 6662 */ { MAD_F(0x07a6a982) /* 0.478189001 */, 18 },
- /* 6663 */ { MAD_F(0x07a70ddd) /* 0.478284708 */, 18 },
- /* 6664 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 18 },
- /* 6665 */ { MAD_F(0x07a7d698) /* 0.478476137 */, 18 },
- /* 6666 */ { MAD_F(0x07a83af7) /* 0.478571858 */, 18 },
- /* 6667 */ { MAD_F(0x07a89f57) /* 0.478667585 */, 18 },
- /* 6668 */ { MAD_F(0x07a903b9) /* 0.478763316 */, 18 },
- /* 6669 */ { MAD_F(0x07a9681c) /* 0.478859052 */, 18 },
- /* 6670 */ { MAD_F(0x07a9cc80) /* 0.478954793 */, 18 },
- /* 6671 */ { MAD_F(0x07aa30e5) /* 0.479050538 */, 18 },
-
- /* 6672 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 18 },
- /* 6673 */ { MAD_F(0x07aaf9b4) /* 0.479242043 */, 18 },
- /* 6674 */ { MAD_F(0x07ab5e1e) /* 0.479337803 */, 18 },
- /* 6675 */ { MAD_F(0x07abc288) /* 0.479433568 */, 18 },
- /* 6676 */ { MAD_F(0x07ac26f4) /* 0.479529337 */, 18 },
- /* 6677 */ { MAD_F(0x07ac8b61) /* 0.479625111 */, 18 },
- /* 6678 */ { MAD_F(0x07acefd0) /* 0.479720890 */, 18 },
- /* 6679 */ { MAD_F(0x07ad543f) /* 0.479816674 */, 18 },
- /* 6680 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 18 },
- /* 6681 */ { MAD_F(0x07ae1d23) /* 0.480008256 */, 18 },
- /* 6682 */ { MAD_F(0x07ae8196) /* 0.480104054 */, 18 },
- /* 6683 */ { MAD_F(0x07aee60b) /* 0.480199857 */, 18 },
- /* 6684 */ { MAD_F(0x07af4a81) /* 0.480295664 */, 18 },
- /* 6685 */ { MAD_F(0x07afaef9) /* 0.480391477 */, 18 },
- /* 6686 */ { MAD_F(0x07b01372) /* 0.480487294 */, 18 },
- /* 6687 */ { MAD_F(0x07b077ec) /* 0.480583116 */, 18 },
-
- /* 6688 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 18 },
- /* 6689 */ { MAD_F(0x07b140e4) /* 0.480774774 */, 18 },
- /* 6690 */ { MAD_F(0x07b1a561) /* 0.480870611 */, 18 },
- /* 6691 */ { MAD_F(0x07b209e1) /* 0.480966452 */, 18 },
- /* 6692 */ { MAD_F(0x07b26e61) /* 0.481062298 */, 18 },
- /* 6693 */ { MAD_F(0x07b2d2e3) /* 0.481158148 */, 18 },
- /* 6694 */ { MAD_F(0x07b33766) /* 0.481254004 */, 18 },
- /* 6695 */ { MAD_F(0x07b39bea) /* 0.481349864 */, 18 },
- /* 6696 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 18 },
- /* 6697 */ { MAD_F(0x07b464f6) /* 0.481541598 */, 18 },
- /* 6698 */ { MAD_F(0x07b4c97e) /* 0.481637473 */, 18 },
- /* 6699 */ { MAD_F(0x07b52e08) /* 0.481733352 */, 18 },
- /* 6700 */ { MAD_F(0x07b59292) /* 0.481829236 */, 18 },
- /* 6701 */ { MAD_F(0x07b5f71e) /* 0.481925125 */, 18 },
- /* 6702 */ { MAD_F(0x07b65bac) /* 0.482021019 */, 18 },
- /* 6703 */ { MAD_F(0x07b6c03a) /* 0.482116917 */, 18 },
-
- /* 6704 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 18 },
- /* 6705 */ { MAD_F(0x07b7895b) /* 0.482308728 */, 18 },
- /* 6706 */ { MAD_F(0x07b7eded) /* 0.482404640 */, 18 },
- /* 6707 */ { MAD_F(0x07b85281) /* 0.482500558 */, 18 },
- /* 6708 */ { MAD_F(0x07b8b716) /* 0.482596480 */, 18 },
- /* 6709 */ { MAD_F(0x07b91bac) /* 0.482692407 */, 18 },
- /* 6710 */ { MAD_F(0x07b98044) /* 0.482788339 */, 18 },
- /* 6711 */ { MAD_F(0x07b9e4dc) /* 0.482884275 */, 18 },
- /* 6712 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 18 },
- /* 6713 */ { MAD_F(0x07baae12) /* 0.483076162 */, 18 },
- /* 6714 */ { MAD_F(0x07bb12ae) /* 0.483172113 */, 18 },
- /* 6715 */ { MAD_F(0x07bb774c) /* 0.483268069 */, 18 },
- /* 6716 */ { MAD_F(0x07bbdbeb) /* 0.483364029 */, 18 },
- /* 6717 */ { MAD_F(0x07bc408c) /* 0.483459994 */, 18 },
- /* 6718 */ { MAD_F(0x07bca52d) /* 0.483555964 */, 18 },
- /* 6719 */ { MAD_F(0x07bd09d0) /* 0.483651939 */, 18 },
-
- /* 6720 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 18 },
- /* 6721 */ { MAD_F(0x07bdd31a) /* 0.483843902 */, 18 },
- /* 6722 */ { MAD_F(0x07be37c1) /* 0.483939891 */, 18 },
- /* 6723 */ { MAD_F(0x07be9c69) /* 0.484035885 */, 18 },
- /* 6724 */ { MAD_F(0x07bf0113) /* 0.484131883 */, 18 },
- /* 6725 */ { MAD_F(0x07bf65bd) /* 0.484227886 */, 18 },
- /* 6726 */ { MAD_F(0x07bfca69) /* 0.484323894 */, 18 },
- /* 6727 */ { MAD_F(0x07c02f16) /* 0.484419907 */, 18 },
- /* 6728 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 18 },
- /* 6729 */ { MAD_F(0x07c0f875) /* 0.484611946 */, 18 },
- /* 6730 */ { MAD_F(0x07c15d26) /* 0.484707973 */, 18 },
- /* 6731 */ { MAD_F(0x07c1c1d8) /* 0.484804005 */, 18 },
- /* 6732 */ { MAD_F(0x07c2268b) /* 0.484900041 */, 18 },
- /* 6733 */ { MAD_F(0x07c28b40) /* 0.484996083 */, 18 },
- /* 6734 */ { MAD_F(0x07c2eff6) /* 0.485092128 */, 18 },
- /* 6735 */ { MAD_F(0x07c354ae) /* 0.485188179 */, 18 },
-
- /* 6736 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 18 },
- /* 6737 */ { MAD_F(0x07c41e21) /* 0.485380295 */, 18 },
- /* 6738 */ { MAD_F(0x07c482dc) /* 0.485476360 */, 18 },
- /* 6739 */ { MAD_F(0x07c4e798) /* 0.485572430 */, 18 },
- /* 6740 */ { MAD_F(0x07c54c56) /* 0.485668504 */, 18 },
- /* 6741 */ { MAD_F(0x07c5b115) /* 0.485764583 */, 18 },
- /* 6742 */ { MAD_F(0x07c615d6) /* 0.485860667 */, 18 },
- /* 6743 */ { MAD_F(0x07c67a97) /* 0.485956756 */, 18 },
- /* 6744 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 18 },
- /* 6745 */ { MAD_F(0x07c7441e) /* 0.486148948 */, 18 },
- /* 6746 */ { MAD_F(0x07c7a8e4) /* 0.486245051 */, 18 },
- /* 6747 */ { MAD_F(0x07c80daa) /* 0.486341158 */, 18 },
- /* 6748 */ { MAD_F(0x07c87272) /* 0.486437271 */, 18 },
- /* 6749 */ { MAD_F(0x07c8d73c) /* 0.486533388 */, 18 },
- /* 6750 */ { MAD_F(0x07c93c06) /* 0.486629510 */, 18 },
- /* 6751 */ { MAD_F(0x07c9a0d2) /* 0.486725637 */, 18 },
-
- /* 6752 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 18 },
- /* 6753 */ { MAD_F(0x07ca6a6d) /* 0.486917905 */, 18 },
- /* 6754 */ { MAD_F(0x07cacf3d) /* 0.487014045 */, 18 },
- /* 6755 */ { MAD_F(0x07cb340e) /* 0.487110191 */, 18 },
- /* 6756 */ { MAD_F(0x07cb98e0) /* 0.487206342 */, 18 },
- /* 6757 */ { MAD_F(0x07cbfdb4) /* 0.487302497 */, 18 },
- /* 6758 */ { MAD_F(0x07cc6288) /* 0.487398657 */, 18 },
- /* 6759 */ { MAD_F(0x07ccc75e) /* 0.487494821 */, 18 },
- /* 6760 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 18 },
- /* 6761 */ { MAD_F(0x07cd910e) /* 0.487687165 */, 18 },
- /* 6762 */ { MAD_F(0x07cdf5e8) /* 0.487783344 */, 18 },
- /* 6763 */ { MAD_F(0x07ce5ac3) /* 0.487879528 */, 18 },
- /* 6764 */ { MAD_F(0x07cebfa0) /* 0.487975716 */, 18 },
- /* 6765 */ { MAD_F(0x07cf247d) /* 0.488071909 */, 18 },
- /* 6766 */ { MAD_F(0x07cf895c) /* 0.488168107 */, 18 },
- /* 6767 */ { MAD_F(0x07cfee3c) /* 0.488264310 */, 18 },
-
- /* 6768 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 18 },
- /* 6769 */ { MAD_F(0x07d0b801) /* 0.488456729 */, 18 },
- /* 6770 */ { MAD_F(0x07d11ce5) /* 0.488552946 */, 18 },
- /* 6771 */ { MAD_F(0x07d181ca) /* 0.488649167 */, 18 },
- /* 6772 */ { MAD_F(0x07d1e6b0) /* 0.488745394 */, 18 },
- /* 6773 */ { MAD_F(0x07d24b98) /* 0.488841625 */, 18 },
- /* 6774 */ { MAD_F(0x07d2b081) /* 0.488937860 */, 18 },
- /* 6775 */ { MAD_F(0x07d3156c) /* 0.489034101 */, 18 },
- /* 6776 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 18 },
- /* 6777 */ { MAD_F(0x07d3df44) /* 0.489226596 */, 18 },
- /* 6778 */ { MAD_F(0x07d44432) /* 0.489322851 */, 18 },
- /* 6779 */ { MAD_F(0x07d4a922) /* 0.489419110 */, 18 },
- /* 6780 */ { MAD_F(0x07d50e13) /* 0.489515375 */, 18 },
- /* 6781 */ { MAD_F(0x07d57305) /* 0.489611643 */, 18 },
- /* 6782 */ { MAD_F(0x07d5d7f8) /* 0.489707917 */, 18 },
- /* 6783 */ { MAD_F(0x07d63cec) /* 0.489804195 */, 18 },
-
- /* 6784 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 18 },
- /* 6785 */ { MAD_F(0x07d706d9) /* 0.489996766 */, 18 },
- /* 6786 */ { MAD_F(0x07d76bd2) /* 0.490093059 */, 18 },
- /* 6787 */ { MAD_F(0x07d7d0cb) /* 0.490189356 */, 18 },
- /* 6788 */ { MAD_F(0x07d835c6) /* 0.490285658 */, 18 },
- /* 6789 */ { MAD_F(0x07d89ac2) /* 0.490381965 */, 18 },
- /* 6790 */ { MAD_F(0x07d8ffc0) /* 0.490478277 */, 18 },
- /* 6791 */ { MAD_F(0x07d964be) /* 0.490574593 */, 18 },
- /* 6792 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 18 },
- /* 6793 */ { MAD_F(0x07da2ebf) /* 0.490767239 */, 18 },
- /* 6794 */ { MAD_F(0x07da93c2) /* 0.490863570 */, 18 },
- /* 6795 */ { MAD_F(0x07daf8c6) /* 0.490959905 */, 18 },
- /* 6796 */ { MAD_F(0x07db5dcb) /* 0.491056245 */, 18 },
- /* 6797 */ { MAD_F(0x07dbc2d1) /* 0.491152589 */, 18 },
- /* 6798 */ { MAD_F(0x07dc27d9) /* 0.491248939 */, 18 },
- /* 6799 */ { MAD_F(0x07dc8ce1) /* 0.491345293 */, 18 },
-
- /* 6800 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 18 },
- /* 6801 */ { MAD_F(0x07dd56f7) /* 0.491538015 */, 18 },
- /* 6802 */ { MAD_F(0x07ddbc04) /* 0.491634383 */, 18 },
- /* 6803 */ { MAD_F(0x07de2111) /* 0.491730756 */, 18 },
- /* 6804 */ { MAD_F(0x07de8621) /* 0.491827134 */, 18 },
- /* 6805 */ { MAD_F(0x07deeb31) /* 0.491923516 */, 18 },
- /* 6806 */ { MAD_F(0x07df5043) /* 0.492019903 */, 18 },
- /* 6807 */ { MAD_F(0x07dfb556) /* 0.492116295 */, 18 },
- /* 6808 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 18 },
- /* 6809 */ { MAD_F(0x07e07f80) /* 0.492309093 */, 18 },
- /* 6810 */ { MAD_F(0x07e0e496) /* 0.492405499 */, 18 },
- /* 6811 */ { MAD_F(0x07e149ae) /* 0.492501909 */, 18 },
- /* 6812 */ { MAD_F(0x07e1aec8) /* 0.492598325 */, 18 },
- /* 6813 */ { MAD_F(0x07e213e2) /* 0.492694745 */, 18 },
- /* 6814 */ { MAD_F(0x07e278fe) /* 0.492791170 */, 18 },
- /* 6815 */ { MAD_F(0x07e2de1b) /* 0.492887599 */, 18 },
-
- /* 6816 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 18 },
- /* 6817 */ { MAD_F(0x07e3a859) /* 0.493080472 */, 18 },
- /* 6818 */ { MAD_F(0x07e40d7a) /* 0.493176916 */, 18 },
- /* 6819 */ { MAD_F(0x07e4729c) /* 0.493273365 */, 18 },
- /* 6820 */ { MAD_F(0x07e4d7c0) /* 0.493369818 */, 18 },
- /* 6821 */ { MAD_F(0x07e53ce4) /* 0.493466275 */, 18 },
- /* 6822 */ { MAD_F(0x07e5a20a) /* 0.493562738 */, 18 },
- /* 6823 */ { MAD_F(0x07e60732) /* 0.493659205 */, 18 },
- /* 6824 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 18 },
- /* 6825 */ { MAD_F(0x07e6d184) /* 0.493852154 */, 18 },
- /* 6826 */ { MAD_F(0x07e736af) /* 0.493948635 */, 18 },
- /* 6827 */ { MAD_F(0x07e79bdb) /* 0.494045122 */, 18 },
- /* 6828 */ { MAD_F(0x07e80109) /* 0.494141612 */, 18 },
- /* 6829 */ { MAD_F(0x07e86638) /* 0.494238108 */, 18 },
- /* 6830 */ { MAD_F(0x07e8cb68) /* 0.494334608 */, 18 },
- /* 6831 */ { MAD_F(0x07e93099) /* 0.494431113 */, 18 },
-
- /* 6832 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 18 },
- /* 6833 */ { MAD_F(0x07e9fb00) /* 0.494624137 */, 18 },
- /* 6834 */ { MAD_F(0x07ea6035) /* 0.494720656 */, 18 },
- /* 6835 */ { MAD_F(0x07eac56b) /* 0.494817180 */, 18 },
- /* 6836 */ { MAD_F(0x07eb2aa3) /* 0.494913709 */, 18 },
- /* 6837 */ { MAD_F(0x07eb8fdc) /* 0.495010242 */, 18 },
- /* 6838 */ { MAD_F(0x07ebf516) /* 0.495106780 */, 18 },
- /* 6839 */ { MAD_F(0x07ec5a51) /* 0.495203322 */, 18 },
- /* 6840 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 18 },
- /* 6841 */ { MAD_F(0x07ed24cc) /* 0.495396422 */, 18 },
- /* 6842 */ { MAD_F(0x07ed8a0b) /* 0.495492978 */, 18 },
- /* 6843 */ { MAD_F(0x07edef4c) /* 0.495589540 */, 18 },
- /* 6844 */ { MAD_F(0x07ee548e) /* 0.495686106 */, 18 },
- /* 6845 */ { MAD_F(0x07eeb9d1) /* 0.495782677 */, 18 },
- /* 6846 */ { MAD_F(0x07ef1f15) /* 0.495879252 */, 18 },
- /* 6847 */ { MAD_F(0x07ef845b) /* 0.495975833 */, 18 },
-
- /* 6848 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 18 },
- /* 6849 */ { MAD_F(0x07f04ee9) /* 0.496169007 */, 18 },
- /* 6850 */ { MAD_F(0x07f0b433) /* 0.496265602 */, 18 },
- /* 6851 */ { MAD_F(0x07f1197d) /* 0.496362201 */, 18 },
- /* 6852 */ { MAD_F(0x07f17ec9) /* 0.496458804 */, 18 },
- /* 6853 */ { MAD_F(0x07f1e416) /* 0.496555413 */, 18 },
- /* 6854 */ { MAD_F(0x07f24965) /* 0.496652026 */, 18 },
- /* 6855 */ { MAD_F(0x07f2aeb5) /* 0.496748644 */, 18 },
- /* 6856 */ { MAD_F(0x07f31405) /* 0.496845266 */, 18 },
- /* 6857 */ { MAD_F(0x07f37958) /* 0.496941894 */, 18 },
- /* 6858 */ { MAD_F(0x07f3deab) /* 0.497038526 */, 18 },
- /* 6859 */ { MAD_F(0x07f44400) /* 0.497135162 */, 18 },
- /* 6860 */ { MAD_F(0x07f4a956) /* 0.497231804 */, 18 },
- /* 6861 */ { MAD_F(0x07f50ead) /* 0.497328450 */, 18 },
- /* 6862 */ { MAD_F(0x07f57405) /* 0.497425100 */, 18 },
- /* 6863 */ { MAD_F(0x07f5d95f) /* 0.497521756 */, 18 },
-
- /* 6864 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 18 },
- /* 6865 */ { MAD_F(0x07f6a416) /* 0.497715081 */, 18 },
- /* 6866 */ { MAD_F(0x07f70974) /* 0.497811750 */, 18 },
- /* 6867 */ { MAD_F(0x07f76ed3) /* 0.497908425 */, 18 },
- /* 6868 */ { MAD_F(0x07f7d433) /* 0.498005103 */, 18 },
- /* 6869 */ { MAD_F(0x07f83994) /* 0.498101787 */, 18 },
- /* 6870 */ { MAD_F(0x07f89ef7) /* 0.498198475 */, 18 },
- /* 6871 */ { MAD_F(0x07f9045a) /* 0.498295168 */, 18 },
- /* 6872 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 18 },
- /* 6873 */ { MAD_F(0x07f9cf26) /* 0.498488568 */, 18 },
- /* 6874 */ { MAD_F(0x07fa348e) /* 0.498585275 */, 18 },
- /* 6875 */ { MAD_F(0x07fa99f6) /* 0.498681987 */, 18 },
- /* 6876 */ { MAD_F(0x07faff60) /* 0.498778704 */, 18 },
- /* 6877 */ { MAD_F(0x07fb64cc) /* 0.498875425 */, 18 },
- /* 6878 */ { MAD_F(0x07fbca38) /* 0.498972150 */, 18 },
- /* 6879 */ { MAD_F(0x07fc2fa6) /* 0.499068881 */, 18 },
-
- /* 6880 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 18 },
- /* 6881 */ { MAD_F(0x07fcfa86) /* 0.499262356 */, 18 },
- /* 6882 */ { MAD_F(0x07fd5ff8) /* 0.499359101 */, 18 },
- /* 6883 */ { MAD_F(0x07fdc56b) /* 0.499455850 */, 18 },
- /* 6884 */ { MAD_F(0x07fe2adf) /* 0.499552604 */, 18 },
- /* 6885 */ { MAD_F(0x07fe9054) /* 0.499649362 */, 18 },
- /* 6886 */ { MAD_F(0x07fef5cb) /* 0.499746126 */, 18 },
- /* 6887 */ { MAD_F(0x07ff5b43) /* 0.499842894 */, 18 },
- /* 6888 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 18 },
- /* 6889 */ { MAD_F(0x0400131b) /* 0.250018222 */, 19 },
- /* 6890 */ { MAD_F(0x040045d9) /* 0.250066613 */, 19 },
- /* 6891 */ { MAD_F(0x04007897) /* 0.250115006 */, 19 },
- /* 6892 */ { MAD_F(0x0400ab57) /* 0.250163402 */, 19 },
- /* 6893 */ { MAD_F(0x0400de16) /* 0.250211800 */, 19 },
- /* 6894 */ { MAD_F(0x040110d7) /* 0.250260200 */, 19 },
- /* 6895 */ { MAD_F(0x04014398) /* 0.250308603 */, 19 },
-
- /* 6896 */ { MAD_F(0x04017659) /* 0.250357008 */, 19 },
- /* 6897 */ { MAD_F(0x0401a91c) /* 0.250405415 */, 19 },
- /* 6898 */ { MAD_F(0x0401dbdf) /* 0.250453825 */, 19 },
- /* 6899 */ { MAD_F(0x04020ea2) /* 0.250502237 */, 19 },
- /* 6900 */ { MAD_F(0x04024166) /* 0.250550652 */, 19 },
- /* 6901 */ { MAD_F(0x0402742b) /* 0.250599068 */, 19 },
- /* 6902 */ { MAD_F(0x0402a6f0) /* 0.250647488 */, 19 },
- /* 6903 */ { MAD_F(0x0402d9b6) /* 0.250695909 */, 19 },
- /* 6904 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 19 },
- /* 6905 */ { MAD_F(0x04033f44) /* 0.250792759 */, 19 },
- /* 6906 */ { MAD_F(0x0403720c) /* 0.250841187 */, 19 },
- /* 6907 */ { MAD_F(0x0403a4d5) /* 0.250889618 */, 19 },
- /* 6908 */ { MAD_F(0x0403d79e) /* 0.250938051 */, 19 },
- /* 6909 */ { MAD_F(0x04040a68) /* 0.250986487 */, 19 },
- /* 6910 */ { MAD_F(0x04043d32) /* 0.251034924 */, 19 },
- /* 6911 */ { MAD_F(0x04046ffd) /* 0.251083365 */, 19 },
-
- /* 6912 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 19 },
- /* 6913 */ { MAD_F(0x0404d595) /* 0.251180252 */, 19 },
- /* 6914 */ { MAD_F(0x04050862) /* 0.251228699 */, 19 },
- /* 6915 */ { MAD_F(0x04053b30) /* 0.251277148 */, 19 },
- /* 6916 */ { MAD_F(0x04056dfe) /* 0.251325600 */, 19 },
- /* 6917 */ { MAD_F(0x0405a0cd) /* 0.251374054 */, 19 },
- /* 6918 */ { MAD_F(0x0405d39c) /* 0.251422511 */, 19 },
- /* 6919 */ { MAD_F(0x0406066c) /* 0.251470970 */, 19 },
- /* 6920 */ { MAD_F(0x0406393d) /* 0.251519431 */, 19 },
- /* 6921 */ { MAD_F(0x04066c0e) /* 0.251567894 */, 19 },
- /* 6922 */ { MAD_F(0x04069ee0) /* 0.251616360 */, 19 },
- /* 6923 */ { MAD_F(0x0406d1b3) /* 0.251664828 */, 19 },
- /* 6924 */ { MAD_F(0x04070486) /* 0.251713299 */, 19 },
- /* 6925 */ { MAD_F(0x0407375a) /* 0.251761772 */, 19 },
- /* 6926 */ { MAD_F(0x04076a2e) /* 0.251810247 */, 19 },
- /* 6927 */ { MAD_F(0x04079d03) /* 0.251858724 */, 19 },
-
- /* 6928 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 19 },
- /* 6929 */ { MAD_F(0x040802af) /* 0.251955686 */, 19 },
- /* 6930 */ { MAD_F(0x04083586) /* 0.252004171 */, 19 },
- /* 6931 */ { MAD_F(0x0408685e) /* 0.252052658 */, 19 },
- /* 6932 */ { MAD_F(0x04089b36) /* 0.252101147 */, 19 },
- /* 6933 */ { MAD_F(0x0408ce0f) /* 0.252149638 */, 19 },
- /* 6934 */ { MAD_F(0x040900e8) /* 0.252198132 */, 19 },
- /* 6935 */ { MAD_F(0x040933c2) /* 0.252246628 */, 19 },
- /* 6936 */ { MAD_F(0x0409669d) /* 0.252295127 */, 19 },
- /* 6937 */ { MAD_F(0x04099978) /* 0.252343627 */, 19 },
- /* 6938 */ { MAD_F(0x0409cc54) /* 0.252392131 */, 19 },
- /* 6939 */ { MAD_F(0x0409ff31) /* 0.252440636 */, 19 },
- /* 6940 */ { MAD_F(0x040a320e) /* 0.252489144 */, 19 },
- /* 6941 */ { MAD_F(0x040a64ec) /* 0.252537654 */, 19 },
- /* 6942 */ { MAD_F(0x040a97cb) /* 0.252586166 */, 19 },
- /* 6943 */ { MAD_F(0x040acaaa) /* 0.252634681 */, 19 },
-
- /* 6944 */ { MAD_F(0x040afd89) /* 0.252683198 */, 19 },
- /* 6945 */ { MAD_F(0x040b306a) /* 0.252731718 */, 19 },
- /* 6946 */ { MAD_F(0x040b634b) /* 0.252780240 */, 19 },
- /* 6947 */ { MAD_F(0x040b962c) /* 0.252828764 */, 19 },
- /* 6948 */ { MAD_F(0x040bc90e) /* 0.252877290 */, 19 },
- /* 6949 */ { MAD_F(0x040bfbf1) /* 0.252925819 */, 19 },
- /* 6950 */ { MAD_F(0x040c2ed5) /* 0.252974350 */, 19 },
- /* 6951 */ { MAD_F(0x040c61b9) /* 0.253022883 */, 19 },
- /* 6952 */ { MAD_F(0x040c949e) /* 0.253071419 */, 19 },
- /* 6953 */ { MAD_F(0x040cc783) /* 0.253119957 */, 19 },
- /* 6954 */ { MAD_F(0x040cfa69) /* 0.253168498 */, 19 },
- /* 6955 */ { MAD_F(0x040d2d4f) /* 0.253217040 */, 19 },
- /* 6956 */ { MAD_F(0x040d6037) /* 0.253265585 */, 19 },
- /* 6957 */ { MAD_F(0x040d931e) /* 0.253314133 */, 19 },
- /* 6958 */ { MAD_F(0x040dc607) /* 0.253362682 */, 19 },
- /* 6959 */ { MAD_F(0x040df8f0) /* 0.253411234 */, 19 },
-
- /* 6960 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 19 },
- /* 6961 */ { MAD_F(0x040e5ec4) /* 0.253508345 */, 19 },
- /* 6962 */ { MAD_F(0x040e91af) /* 0.253556904 */, 19 },
- /* 6963 */ { MAD_F(0x040ec49b) /* 0.253605466 */, 19 },
- /* 6964 */ { MAD_F(0x040ef787) /* 0.253654029 */, 19 },
- /* 6965 */ { MAD_F(0x040f2a74) /* 0.253702595 */, 19 },
- /* 6966 */ { MAD_F(0x040f5d61) /* 0.253751164 */, 19 },
- /* 6967 */ { MAD_F(0x040f904f) /* 0.253799734 */, 19 },
- /* 6968 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 19 },
- /* 6969 */ { MAD_F(0x040ff62d) /* 0.253896883 */, 19 },
- /* 6970 */ { MAD_F(0x0410291d) /* 0.253945460 */, 19 },
- /* 6971 */ { MAD_F(0x04105c0e) /* 0.253994040 */, 19 },
- /* 6972 */ { MAD_F(0x04108eff) /* 0.254042622 */, 19 },
- /* 6973 */ { MAD_F(0x0410c1f1) /* 0.254091207 */, 19 },
- /* 6974 */ { MAD_F(0x0410f4e3) /* 0.254139794 */, 19 },
- /* 6975 */ { MAD_F(0x041127d6) /* 0.254188383 */, 19 },
-
- /* 6976 */ { MAD_F(0x04115aca) /* 0.254236974 */, 19 },
- /* 6977 */ { MAD_F(0x04118dbe) /* 0.254285568 */, 19 },
- /* 6978 */ { MAD_F(0x0411c0b3) /* 0.254334165 */, 19 },
- /* 6979 */ { MAD_F(0x0411f3a9) /* 0.254382763 */, 19 },
- /* 6980 */ { MAD_F(0x0412269f) /* 0.254431364 */, 19 },
- /* 6981 */ { MAD_F(0x04125996) /* 0.254479967 */, 19 },
- /* 6982 */ { MAD_F(0x04128c8d) /* 0.254528572 */, 19 },
- /* 6983 */ { MAD_F(0x0412bf85) /* 0.254577180 */, 19 },
- /* 6984 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 19 },
- /* 6985 */ { MAD_F(0x04132577) /* 0.254674403 */, 19 },
- /* 6986 */ { MAD_F(0x04135871) /* 0.254723017 */, 19 },
- /* 6987 */ { MAD_F(0x04138b6c) /* 0.254771635 */, 19 },
- /* 6988 */ { MAD_F(0x0413be67) /* 0.254820254 */, 19 },
- /* 6989 */ { MAD_F(0x0413f163) /* 0.254868876 */, 19 },
- /* 6990 */ { MAD_F(0x0414245f) /* 0.254917500 */, 19 },
- /* 6991 */ { MAD_F(0x0414575c) /* 0.254966126 */, 19 },
-
- /* 6992 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 19 },
- /* 6993 */ { MAD_F(0x0414bd58) /* 0.255063386 */, 19 },
- /* 6994 */ { MAD_F(0x0414f057) /* 0.255112019 */, 19 },
- /* 6995 */ { MAD_F(0x04152356) /* 0.255160655 */, 19 },
- /* 6996 */ { MAD_F(0x04155657) /* 0.255209292 */, 19 },
- /* 6997 */ { MAD_F(0x04158957) /* 0.255257933 */, 19 },
- /* 6998 */ { MAD_F(0x0415bc59) /* 0.255306575 */, 19 },
- /* 6999 */ { MAD_F(0x0415ef5b) /* 0.255355220 */, 19 },
- /* 7000 */ { MAD_F(0x0416225d) /* 0.255403867 */, 19 },
- /* 7001 */ { MAD_F(0x04165561) /* 0.255452517 */, 19 },
- /* 7002 */ { MAD_F(0x04168864) /* 0.255501169 */, 19 },
- /* 7003 */ { MAD_F(0x0416bb69) /* 0.255549823 */, 19 },
- /* 7004 */ { MAD_F(0x0416ee6e) /* 0.255598479 */, 19 },
- /* 7005 */ { MAD_F(0x04172174) /* 0.255647138 */, 19 },
- /* 7006 */ { MAD_F(0x0417547a) /* 0.255695799 */, 19 },
- /* 7007 */ { MAD_F(0x04178781) /* 0.255744463 */, 19 },
-
- /* 7008 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 19 },
- /* 7009 */ { MAD_F(0x0417ed91) /* 0.255841796 */, 19 },
- /* 7010 */ { MAD_F(0x0418209a) /* 0.255890467 */, 19 },
- /* 7011 */ { MAD_F(0x041853a3) /* 0.255939139 */, 19 },
- /* 7012 */ { MAD_F(0x041886ad) /* 0.255987814 */, 19 },
- /* 7013 */ { MAD_F(0x0418b9b8) /* 0.256036492 */, 19 },
- /* 7014 */ { MAD_F(0x0418ecc3) /* 0.256085171 */, 19 },
- /* 7015 */ { MAD_F(0x04191fcf) /* 0.256133853 */, 19 },
- /* 7016 */ { MAD_F(0x041952dc) /* 0.256182537 */, 19 },
- /* 7017 */ { MAD_F(0x041985e9) /* 0.256231224 */, 19 },
- /* 7018 */ { MAD_F(0x0419b8f7) /* 0.256279913 */, 19 },
- /* 7019 */ { MAD_F(0x0419ec05) /* 0.256328604 */, 19 },
- /* 7020 */ { MAD_F(0x041a1f15) /* 0.256377297 */, 19 },
- /* 7021 */ { MAD_F(0x041a5224) /* 0.256425993 */, 19 },
- /* 7022 */ { MAD_F(0x041a8534) /* 0.256474691 */, 19 },
- /* 7023 */ { MAD_F(0x041ab845) /* 0.256523392 */, 19 },
-
- /* 7024 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 19 },
- /* 7025 */ { MAD_F(0x041b1e69) /* 0.256620800 */, 19 },
- /* 7026 */ { MAD_F(0x041b517c) /* 0.256669507 */, 19 },
- /* 7027 */ { MAD_F(0x041b848f) /* 0.256718217 */, 19 },
- /* 7028 */ { MAD_F(0x041bb7a3) /* 0.256766929 */, 19 },
- /* 7029 */ { MAD_F(0x041beab8) /* 0.256815643 */, 19 },
- /* 7030 */ { MAD_F(0x041c1dcd) /* 0.256864359 */, 19 },
- /* 7031 */ { MAD_F(0x041c50e3) /* 0.256913078 */, 19 },
- /* 7032 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 19 },
- /* 7033 */ { MAD_F(0x041cb711) /* 0.257010523 */, 19 },
- /* 7034 */ { MAD_F(0x041cea28) /* 0.257059249 */, 19 },
- /* 7035 */ { MAD_F(0x041d1d41) /* 0.257107977 */, 19 },
- /* 7036 */ { MAD_F(0x041d505a) /* 0.257156708 */, 19 },
- /* 7037 */ { MAD_F(0x041d8373) /* 0.257205440 */, 19 },
- /* 7038 */ { MAD_F(0x041db68e) /* 0.257254175 */, 19 },
- /* 7039 */ { MAD_F(0x041de9a8) /* 0.257302913 */, 19 },
-
- /* 7040 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 19 },
- /* 7041 */ { MAD_F(0x041e4fe0) /* 0.257400394 */, 19 },
- /* 7042 */ { MAD_F(0x041e82fd) /* 0.257449139 */, 19 },
- /* 7043 */ { MAD_F(0x041eb61a) /* 0.257497885 */, 19 },
- /* 7044 */ { MAD_F(0x041ee938) /* 0.257546634 */, 19 },
- /* 7045 */ { MAD_F(0x041f1c57) /* 0.257595386 */, 19 },
- /* 7046 */ { MAD_F(0x041f4f76) /* 0.257644139 */, 19 },
- /* 7047 */ { MAD_F(0x041f8296) /* 0.257692895 */, 19 },
- /* 7048 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 19 },
- /* 7049 */ { MAD_F(0x041fe8d7) /* 0.257790414 */, 19 },
- /* 7050 */ { MAD_F(0x04201bf9) /* 0.257839176 */, 19 },
- /* 7051 */ { MAD_F(0x04204f1b) /* 0.257887941 */, 19 },
- /* 7052 */ { MAD_F(0x0420823e) /* 0.257936709 */, 19 },
- /* 7053 */ { MAD_F(0x0420b561) /* 0.257985478 */, 19 },
- /* 7054 */ { MAD_F(0x0420e885) /* 0.258034250 */, 19 },
- /* 7055 */ { MAD_F(0x04211baa) /* 0.258083025 */, 19 },
-
- /* 7056 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 19 },
- /* 7057 */ { MAD_F(0x042181f6) /* 0.258180580 */, 19 },
- /* 7058 */ { MAD_F(0x0421b51c) /* 0.258229361 */, 19 },
- /* 7059 */ { MAD_F(0x0421e843) /* 0.258278145 */, 19 },
- /* 7060 */ { MAD_F(0x04221b6b) /* 0.258326931 */, 19 },
- /* 7061 */ { MAD_F(0x04224e94) /* 0.258375719 */, 19 },
- /* 7062 */ { MAD_F(0x042281bd) /* 0.258424509 */, 19 },
- /* 7063 */ { MAD_F(0x0422b4e6) /* 0.258473302 */, 19 },
- /* 7064 */ { MAD_F(0x0422e811) /* 0.258522097 */, 19 },
- /* 7065 */ { MAD_F(0x04231b3c) /* 0.258570894 */, 19 },
- /* 7066 */ { MAD_F(0x04234e67) /* 0.258619694 */, 19 },
- /* 7067 */ { MAD_F(0x04238193) /* 0.258668496 */, 19 },
- /* 7068 */ { MAD_F(0x0423b4c0) /* 0.258717300 */, 19 },
- /* 7069 */ { MAD_F(0x0423e7ee) /* 0.258766106 */, 19 },
- /* 7070 */ { MAD_F(0x04241b1c) /* 0.258814915 */, 19 },
- /* 7071 */ { MAD_F(0x04244e4a) /* 0.258863726 */, 19 },
-
- /* 7072 */ { MAD_F(0x04248179) /* 0.258912540 */, 19 },
- /* 7073 */ { MAD_F(0x0424b4a9) /* 0.258961356 */, 19 },
- /* 7074 */ { MAD_F(0x0424e7da) /* 0.259010174 */, 19 },
- /* 7075 */ { MAD_F(0x04251b0b) /* 0.259058994 */, 19 },
- /* 7076 */ { MAD_F(0x04254e3d) /* 0.259107817 */, 19 },
- /* 7077 */ { MAD_F(0x0425816f) /* 0.259156642 */, 19 },
- /* 7078 */ { MAD_F(0x0425b4a2) /* 0.259205469 */, 19 },
- /* 7079 */ { MAD_F(0x0425e7d6) /* 0.259254298 */, 19 },
- /* 7080 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 19 },
- /* 7081 */ { MAD_F(0x04264e3f) /* 0.259351964 */, 19 },
- /* 7082 */ { MAD_F(0x04268174) /* 0.259400801 */, 19 },
- /* 7083 */ { MAD_F(0x0426b4aa) /* 0.259449639 */, 19 },
- /* 7084 */ { MAD_F(0x0426e7e1) /* 0.259498480 */, 19 },
- /* 7085 */ { MAD_F(0x04271b18) /* 0.259547324 */, 19 },
- /* 7086 */ { MAD_F(0x04274e50) /* 0.259596169 */, 19 },
- /* 7087 */ { MAD_F(0x04278188) /* 0.259645017 */, 19 },
-
- /* 7088 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 19 },
- /* 7089 */ { MAD_F(0x0427e7fb) /* 0.259742720 */, 19 },
- /* 7090 */ { MAD_F(0x04281b36) /* 0.259791575 */, 19 },
- /* 7091 */ { MAD_F(0x04284e71) /* 0.259840432 */, 19 },
- /* 7092 */ { MAD_F(0x042881ac) /* 0.259889291 */, 19 },
- /* 7093 */ { MAD_F(0x0428b4e8) /* 0.259938153 */, 19 },
- /* 7094 */ { MAD_F(0x0428e825) /* 0.259987017 */, 19 },
- /* 7095 */ { MAD_F(0x04291b63) /* 0.260035883 */, 19 },
- /* 7096 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 19 },
- /* 7097 */ { MAD_F(0x042981df) /* 0.260133623 */, 19 },
- /* 7098 */ { MAD_F(0x0429b51f) /* 0.260182496 */, 19 },
- /* 7099 */ { MAD_F(0x0429e85f) /* 0.260231372 */, 19 },
- /* 7100 */ { MAD_F(0x042a1b9f) /* 0.260280249 */, 19 },
- /* 7101 */ { MAD_F(0x042a4ee0) /* 0.260329129 */, 19 },
- /* 7102 */ { MAD_F(0x042a8222) /* 0.260378012 */, 19 },
- /* 7103 */ { MAD_F(0x042ab564) /* 0.260426896 */, 19 },
-
- /* 7104 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 19 },
- /* 7105 */ { MAD_F(0x042b1beb) /* 0.260524673 */, 19 },
- /* 7106 */ { MAD_F(0x042b4f2f) /* 0.260573564 */, 19 },
- /* 7107 */ { MAD_F(0x042b8274) /* 0.260622458 */, 19 },
- /* 7108 */ { MAD_F(0x042bb5ba) /* 0.260671354 */, 19 },
- /* 7109 */ { MAD_F(0x042be900) /* 0.260720252 */, 19 },
- /* 7110 */ { MAD_F(0x042c1c46) /* 0.260769153 */, 19 },
- /* 7111 */ { MAD_F(0x042c4f8e) /* 0.260818056 */, 19 },
- /* 7112 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 19 },
- /* 7113 */ { MAD_F(0x042cb61e) /* 0.260915869 */, 19 },
- /* 7114 */ { MAD_F(0x042ce967) /* 0.260964779 */, 19 },
- /* 7115 */ { MAD_F(0x042d1cb1) /* 0.261013691 */, 19 },
- /* 7116 */ { MAD_F(0x042d4ffb) /* 0.261062606 */, 19 },
- /* 7117 */ { MAD_F(0x042d8346) /* 0.261111522 */, 19 },
- /* 7118 */ { MAD_F(0x042db692) /* 0.261160441 */, 19 },
- /* 7119 */ { MAD_F(0x042de9de) /* 0.261209363 */, 19 },
-
- /* 7120 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 19 },
- /* 7121 */ { MAD_F(0x042e5078) /* 0.261307212 */, 19 },
- /* 7122 */ { MAD_F(0x042e83c6) /* 0.261356140 */, 19 },
- /* 7123 */ { MAD_F(0x042eb715) /* 0.261405071 */, 19 },
- /* 7124 */ { MAD_F(0x042eea64) /* 0.261454004 */, 19 },
- /* 7125 */ { MAD_F(0x042f1db4) /* 0.261502939 */, 19 },
- /* 7126 */ { MAD_F(0x042f5105) /* 0.261551876 */, 19 },
- /* 7127 */ { MAD_F(0x042f8456) /* 0.261600816 */, 19 },
- /* 7128 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 19 },
- /* 7129 */ { MAD_F(0x042feafa) /* 0.261698702 */, 19 },
- /* 7130 */ { MAD_F(0x04301e4d) /* 0.261747649 */, 19 },
- /* 7131 */ { MAD_F(0x043051a1) /* 0.261796597 */, 19 },
- /* 7132 */ { MAD_F(0x043084f5) /* 0.261845548 */, 19 },
- /* 7133 */ { MAD_F(0x0430b84a) /* 0.261894502 */, 19 },
- /* 7134 */ { MAD_F(0x0430eb9f) /* 0.261943458 */, 19 },
- /* 7135 */ { MAD_F(0x04311ef5) /* 0.261992416 */, 19 },
-
- /* 7136 */ { MAD_F(0x0431524c) /* 0.262041376 */, 19 },
- /* 7137 */ { MAD_F(0x043185a3) /* 0.262090338 */, 19 },
- /* 7138 */ { MAD_F(0x0431b8fb) /* 0.262139303 */, 19 },
- /* 7139 */ { MAD_F(0x0431ec54) /* 0.262188270 */, 19 },
- /* 7140 */ { MAD_F(0x04321fad) /* 0.262237240 */, 19 },
- /* 7141 */ { MAD_F(0x04325306) /* 0.262286211 */, 19 },
- /* 7142 */ { MAD_F(0x04328661) /* 0.262335185 */, 19 },
- /* 7143 */ { MAD_F(0x0432b9bc) /* 0.262384162 */, 19 },
- /* 7144 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 19 },
- /* 7145 */ { MAD_F(0x04332074) /* 0.262482121 */, 19 },
- /* 7146 */ { MAD_F(0x043353d0) /* 0.262531104 */, 19 },
- /* 7147 */ { MAD_F(0x0433872e) /* 0.262580089 */, 19 },
- /* 7148 */ { MAD_F(0x0433ba8c) /* 0.262629077 */, 19 },
- /* 7149 */ { MAD_F(0x0433edea) /* 0.262678067 */, 19 },
- /* 7150 */ { MAD_F(0x0434214a) /* 0.262727059 */, 19 },
- /* 7151 */ { MAD_F(0x043454aa) /* 0.262776054 */, 19 },
-
- /* 7152 */ { MAD_F(0x0434880a) /* 0.262825051 */, 19 },
- /* 7153 */ { MAD_F(0x0434bb6b) /* 0.262874050 */, 19 },
- /* 7154 */ { MAD_F(0x0434eecd) /* 0.262923051 */, 19 },
- /* 7155 */ { MAD_F(0x0435222f) /* 0.262972055 */, 19 },
- /* 7156 */ { MAD_F(0x04355592) /* 0.263021061 */, 19 },
- /* 7157 */ { MAD_F(0x043588f6) /* 0.263070069 */, 19 },
- /* 7158 */ { MAD_F(0x0435bc5a) /* 0.263119079 */, 19 },
- /* 7159 */ { MAD_F(0x0435efbf) /* 0.263168092 */, 19 },
- /* 7160 */ { MAD_F(0x04362324) /* 0.263217107 */, 19 },
- /* 7161 */ { MAD_F(0x0436568a) /* 0.263266125 */, 19 },
- /* 7162 */ { MAD_F(0x043689f1) /* 0.263315144 */, 19 },
- /* 7163 */ { MAD_F(0x0436bd58) /* 0.263364166 */, 19 },
- /* 7164 */ { MAD_F(0x0436f0c0) /* 0.263413191 */, 19 },
- /* 7165 */ { MAD_F(0x04372428) /* 0.263462217 */, 19 },
- /* 7166 */ { MAD_F(0x04375791) /* 0.263511246 */, 19 },
- /* 7167 */ { MAD_F(0x04378afb) /* 0.263560277 */, 19 },
-
- /* 7168 */ { MAD_F(0x0437be65) /* 0.263609310 */, 19 },
- /* 7169 */ { MAD_F(0x0437f1d0) /* 0.263658346 */, 19 },
- /* 7170 */ { MAD_F(0x0438253c) /* 0.263707384 */, 19 },
- /* 7171 */ { MAD_F(0x043858a8) /* 0.263756424 */, 19 },
- /* 7172 */ { MAD_F(0x04388c14) /* 0.263805466 */, 19 },
- /* 7173 */ { MAD_F(0x0438bf82) /* 0.263854511 */, 19 },
- /* 7174 */ { MAD_F(0x0438f2f0) /* 0.263903558 */, 19 },
- /* 7175 */ { MAD_F(0x0439265e) /* 0.263952607 */, 19 },
- /* 7176 */ { MAD_F(0x043959cd) /* 0.264001659 */, 19 },
- /* 7177 */ { MAD_F(0x04398d3d) /* 0.264050713 */, 19 },
- /* 7178 */ { MAD_F(0x0439c0ae) /* 0.264099769 */, 19 },
- /* 7179 */ { MAD_F(0x0439f41f) /* 0.264148827 */, 19 },
- /* 7180 */ { MAD_F(0x043a2790) /* 0.264197888 */, 19 },
- /* 7181 */ { MAD_F(0x043a5b02) /* 0.264246951 */, 19 },
- /* 7182 */ { MAD_F(0x043a8e75) /* 0.264296016 */, 19 },
- /* 7183 */ { MAD_F(0x043ac1e9) /* 0.264345084 */, 19 },
-
- /* 7184 */ { MAD_F(0x043af55d) /* 0.264394153 */, 19 },
- /* 7185 */ { MAD_F(0x043b28d2) /* 0.264443225 */, 19 },
- /* 7186 */ { MAD_F(0x043b5c47) /* 0.264492300 */, 19 },
- /* 7187 */ { MAD_F(0x043b8fbd) /* 0.264541376 */, 19 },
- /* 7188 */ { MAD_F(0x043bc333) /* 0.264590455 */, 19 },
- /* 7189 */ { MAD_F(0x043bf6aa) /* 0.264639536 */, 19 },
- /* 7190 */ { MAD_F(0x043c2a22) /* 0.264688620 */, 19 },
- /* 7191 */ { MAD_F(0x043c5d9a) /* 0.264737706 */, 19 },
- /* 7192 */ { MAD_F(0x043c9113) /* 0.264786794 */, 19 },
- /* 7193 */ { MAD_F(0x043cc48d) /* 0.264835884 */, 19 },
- /* 7194 */ { MAD_F(0x043cf807) /* 0.264884976 */, 19 },
- /* 7195 */ { MAD_F(0x043d2b82) /* 0.264934071 */, 19 },
- /* 7196 */ { MAD_F(0x043d5efd) /* 0.264983168 */, 19 },
- /* 7197 */ { MAD_F(0x043d9279) /* 0.265032268 */, 19 },
- /* 7198 */ { MAD_F(0x043dc5f6) /* 0.265081369 */, 19 },
- /* 7199 */ { MAD_F(0x043df973) /* 0.265130473 */, 19 },
-
- /* 7200 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 19 },
- /* 7201 */ { MAD_F(0x043e6070) /* 0.265228688 */, 19 },
- /* 7202 */ { MAD_F(0x043e93ef) /* 0.265277799 */, 19 },
- /* 7203 */ { MAD_F(0x043ec76e) /* 0.265326912 */, 19 },
- /* 7204 */ { MAD_F(0x043efaef) /* 0.265376027 */, 19 },
- /* 7205 */ { MAD_F(0x043f2e6f) /* 0.265425145 */, 19 },
- /* 7206 */ { MAD_F(0x043f61f1) /* 0.265474264 */, 19 },
- /* 7207 */ { MAD_F(0x043f9573) /* 0.265523387 */, 19 },
- /* 7208 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 19 },
- /* 7209 */ { MAD_F(0x043ffc79) /* 0.265621638 */, 19 },
- /* 7210 */ { MAD_F(0x04402ffd) /* 0.265670766 */, 19 },
- /* 7211 */ { MAD_F(0x04406382) /* 0.265719898 */, 19 },
- /* 7212 */ { MAD_F(0x04409707) /* 0.265769031 */, 19 },
- /* 7213 */ { MAD_F(0x0440ca8d) /* 0.265818167 */, 19 },
- /* 7214 */ { MAD_F(0x0440fe13) /* 0.265867305 */, 19 },
- /* 7215 */ { MAD_F(0x0441319a) /* 0.265916445 */, 19 },
-
- /* 7216 */ { MAD_F(0x04416522) /* 0.265965588 */, 19 },
- /* 7217 */ { MAD_F(0x044198aa) /* 0.266014732 */, 19 },
- /* 7218 */ { MAD_F(0x0441cc33) /* 0.266063880 */, 19 },
- /* 7219 */ { MAD_F(0x0441ffbc) /* 0.266113029 */, 19 },
- /* 7220 */ { MAD_F(0x04423346) /* 0.266162181 */, 19 },
- /* 7221 */ { MAD_F(0x044266d1) /* 0.266211334 */, 19 },
- /* 7222 */ { MAD_F(0x04429a5c) /* 0.266260491 */, 19 },
- /* 7223 */ { MAD_F(0x0442cde8) /* 0.266309649 */, 19 },
- /* 7224 */ { MAD_F(0x04430174) /* 0.266358810 */, 19 },
- /* 7225 */ { MAD_F(0x04433501) /* 0.266407973 */, 19 },
- /* 7226 */ { MAD_F(0x0443688f) /* 0.266457138 */, 19 },
- /* 7227 */ { MAD_F(0x04439c1d) /* 0.266506305 */, 19 },
- /* 7228 */ { MAD_F(0x0443cfac) /* 0.266555475 */, 19 },
- /* 7229 */ { MAD_F(0x0444033c) /* 0.266604647 */, 19 },
- /* 7230 */ { MAD_F(0x044436cc) /* 0.266653822 */, 19 },
- /* 7231 */ { MAD_F(0x04446a5d) /* 0.266702998 */, 19 },
-
- /* 7232 */ { MAD_F(0x04449dee) /* 0.266752177 */, 19 },
- /* 7233 */ { MAD_F(0x0444d180) /* 0.266801358 */, 19 },
- /* 7234 */ { MAD_F(0x04450513) /* 0.266850541 */, 19 },
- /* 7235 */ { MAD_F(0x044538a6) /* 0.266899727 */, 19 },
- /* 7236 */ { MAD_F(0x04456c39) /* 0.266948915 */, 19 },
- /* 7237 */ { MAD_F(0x04459fce) /* 0.266998105 */, 19 },
- /* 7238 */ { MAD_F(0x0445d363) /* 0.267047298 */, 19 },
- /* 7239 */ { MAD_F(0x044606f8) /* 0.267096492 */, 19 },
- /* 7240 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 19 },
- /* 7241 */ { MAD_F(0x04466e25) /* 0.267194888 */, 19 },
- /* 7242 */ { MAD_F(0x0446a1bd) /* 0.267244090 */, 19 },
- /* 7243 */ { MAD_F(0x0446d555) /* 0.267293294 */, 19 },
- /* 7244 */ { MAD_F(0x044708ee) /* 0.267342500 */, 19 },
- /* 7245 */ { MAD_F(0x04473c87) /* 0.267391708 */, 19 },
- /* 7246 */ { MAD_F(0x04477021) /* 0.267440919 */, 19 },
- /* 7247 */ { MAD_F(0x0447a3bb) /* 0.267490131 */, 19 },
-
- /* 7248 */ { MAD_F(0x0447d756) /* 0.267539347 */, 19 },
- /* 7249 */ { MAD_F(0x04480af2) /* 0.267588564 */, 19 },
- /* 7250 */ { MAD_F(0x04483e8e) /* 0.267637783 */, 19 },
- /* 7251 */ { MAD_F(0x0448722b) /* 0.267687005 */, 19 },
- /* 7252 */ { MAD_F(0x0448a5c9) /* 0.267736229 */, 19 },
- /* 7253 */ { MAD_F(0x0448d967) /* 0.267785456 */, 19 },
- /* 7254 */ { MAD_F(0x04490d05) /* 0.267834685 */, 19 },
- /* 7255 */ { MAD_F(0x044940a5) /* 0.267883915 */, 19 },
- /* 7256 */ { MAD_F(0x04497445) /* 0.267933149 */, 19 },
- /* 7257 */ { MAD_F(0x0449a7e5) /* 0.267982384 */, 19 },
- /* 7258 */ { MAD_F(0x0449db86) /* 0.268031622 */, 19 },
- /* 7259 */ { MAD_F(0x044a0f28) /* 0.268080862 */, 19 },
- /* 7260 */ { MAD_F(0x044a42ca) /* 0.268130104 */, 19 },
- /* 7261 */ { MAD_F(0x044a766d) /* 0.268179349 */, 19 },
- /* 7262 */ { MAD_F(0x044aaa11) /* 0.268228595 */, 19 },
- /* 7263 */ { MAD_F(0x044addb5) /* 0.268277844 */, 19 },
-
- /* 7264 */ { MAD_F(0x044b115a) /* 0.268327096 */, 19 },
- /* 7265 */ { MAD_F(0x044b44ff) /* 0.268376349 */, 19 },
- /* 7266 */ { MAD_F(0x044b78a5) /* 0.268425605 */, 19 },
- /* 7267 */ { MAD_F(0x044bac4c) /* 0.268474863 */, 19 },
- /* 7268 */ { MAD_F(0x044bdff3) /* 0.268524123 */, 19 },
- /* 7269 */ { MAD_F(0x044c139b) /* 0.268573386 */, 19 },
- /* 7270 */ { MAD_F(0x044c4743) /* 0.268622651 */, 19 },
- /* 7271 */ { MAD_F(0x044c7aec) /* 0.268671918 */, 19 },
- /* 7272 */ { MAD_F(0x044cae96) /* 0.268721187 */, 19 },
- /* 7273 */ { MAD_F(0x044ce240) /* 0.268770459 */, 19 },
- /* 7274 */ { MAD_F(0x044d15eb) /* 0.268819733 */, 19 },
- /* 7275 */ { MAD_F(0x044d4997) /* 0.268869009 */, 19 },
- /* 7276 */ { MAD_F(0x044d7d43) /* 0.268918287 */, 19 },
- /* 7277 */ { MAD_F(0x044db0ef) /* 0.268967568 */, 19 },
- /* 7278 */ { MAD_F(0x044de49d) /* 0.269016851 */, 19 },
- /* 7279 */ { MAD_F(0x044e184b) /* 0.269066136 */, 19 },
-
- /* 7280 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 19 },
- /* 7281 */ { MAD_F(0x044e7fa8) /* 0.269164713 */, 19 },
- /* 7282 */ { MAD_F(0x044eb358) /* 0.269214005 */, 19 },
- /* 7283 */ { MAD_F(0x044ee708) /* 0.269263299 */, 19 },
- /* 7284 */ { MAD_F(0x044f1ab9) /* 0.269312595 */, 19 },
- /* 7285 */ { MAD_F(0x044f4e6b) /* 0.269361894 */, 19 },
- /* 7286 */ { MAD_F(0x044f821d) /* 0.269411195 */, 19 },
- /* 7287 */ { MAD_F(0x044fb5cf) /* 0.269460498 */, 19 },
- /* 7288 */ { MAD_F(0x044fe983) /* 0.269509804 */, 19 },
- /* 7289 */ { MAD_F(0x04501d37) /* 0.269559111 */, 19 },
- /* 7290 */ { MAD_F(0x045050eb) /* 0.269608421 */, 19 },
- /* 7291 */ { MAD_F(0x045084a0) /* 0.269657734 */, 19 },
- /* 7292 */ { MAD_F(0x0450b856) /* 0.269707048 */, 19 },
- /* 7293 */ { MAD_F(0x0450ec0d) /* 0.269756365 */, 19 },
- /* 7294 */ { MAD_F(0x04511fc4) /* 0.269805684 */, 19 },
- /* 7295 */ { MAD_F(0x0451537b) /* 0.269855005 */, 19 },
-
- /* 7296 */ { MAD_F(0x04518733) /* 0.269904329 */, 19 },
- /* 7297 */ { MAD_F(0x0451baec) /* 0.269953654 */, 19 },
- /* 7298 */ { MAD_F(0x0451eea5) /* 0.270002982 */, 19 },
- /* 7299 */ { MAD_F(0x0452225f) /* 0.270052313 */, 19 },
- /* 7300 */ { MAD_F(0x0452561a) /* 0.270101645 */, 19 },
- /* 7301 */ { MAD_F(0x045289d5) /* 0.270150980 */, 19 },
- /* 7302 */ { MAD_F(0x0452bd91) /* 0.270200317 */, 19 },
- /* 7303 */ { MAD_F(0x0452f14d) /* 0.270249656 */, 19 },
- /* 7304 */ { MAD_F(0x0453250a) /* 0.270298998 */, 19 },
- /* 7305 */ { MAD_F(0x045358c8) /* 0.270348341 */, 19 },
- /* 7306 */ { MAD_F(0x04538c86) /* 0.270397687 */, 19 },
- /* 7307 */ { MAD_F(0x0453c045) /* 0.270447036 */, 19 },
- /* 7308 */ { MAD_F(0x0453f405) /* 0.270496386 */, 19 },
- /* 7309 */ { MAD_F(0x045427c5) /* 0.270545739 */, 19 },
- /* 7310 */ { MAD_F(0x04545b85) /* 0.270595094 */, 19 },
- /* 7311 */ { MAD_F(0x04548f46) /* 0.270644451 */, 19 },
-
- /* 7312 */ { MAD_F(0x0454c308) /* 0.270693811 */, 19 },
- /* 7313 */ { MAD_F(0x0454f6cb) /* 0.270743173 */, 19 },
- /* 7314 */ { MAD_F(0x04552a8e) /* 0.270792537 */, 19 },
- /* 7315 */ { MAD_F(0x04555e51) /* 0.270841903 */, 19 },
- /* 7316 */ { MAD_F(0x04559216) /* 0.270891271 */, 19 },
- /* 7317 */ { MAD_F(0x0455c5db) /* 0.270940642 */, 19 },
- /* 7318 */ { MAD_F(0x0455f9a0) /* 0.270990015 */, 19 },
- /* 7319 */ { MAD_F(0x04562d66) /* 0.271039390 */, 19 },
- /* 7320 */ { MAD_F(0x0456612d) /* 0.271088768 */, 19 },
- /* 7321 */ { MAD_F(0x045694f4) /* 0.271138148 */, 19 },
- /* 7322 */ { MAD_F(0x0456c8bc) /* 0.271187530 */, 19 },
- /* 7323 */ { MAD_F(0x0456fc84) /* 0.271236914 */, 19 },
- /* 7324 */ { MAD_F(0x0457304e) /* 0.271286301 */, 19 },
- /* 7325 */ { MAD_F(0x04576417) /* 0.271335689 */, 19 },
- /* 7326 */ { MAD_F(0x045797e2) /* 0.271385080 */, 19 },
- /* 7327 */ { MAD_F(0x0457cbac) /* 0.271434474 */, 19 },
-
- /* 7328 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 19 },
- /* 7329 */ { MAD_F(0x04583344) /* 0.271533267 */, 19 },
- /* 7330 */ { MAD_F(0x04586711) /* 0.271582667 */, 19 },
- /* 7331 */ { MAD_F(0x04589ade) /* 0.271632069 */, 19 },
- /* 7332 */ { MAD_F(0x0458ceac) /* 0.271681474 */, 19 },
- /* 7333 */ { MAD_F(0x0459027b) /* 0.271730880 */, 19 },
- /* 7334 */ { MAD_F(0x0459364a) /* 0.271780289 */, 19 },
- /* 7335 */ { MAD_F(0x04596a19) /* 0.271829701 */, 19 },
- /* 7336 */ { MAD_F(0x04599dea) /* 0.271879114 */, 19 },
- /* 7337 */ { MAD_F(0x0459d1bb) /* 0.271928530 */, 19 },
- /* 7338 */ { MAD_F(0x045a058c) /* 0.271977948 */, 19 },
- /* 7339 */ { MAD_F(0x045a395e) /* 0.272027368 */, 19 },
- /* 7340 */ { MAD_F(0x045a6d31) /* 0.272076790 */, 19 },
- /* 7341 */ { MAD_F(0x045aa104) /* 0.272126215 */, 19 },
- /* 7342 */ { MAD_F(0x045ad4d8) /* 0.272175642 */, 19 },
- /* 7343 */ { MAD_F(0x045b08ad) /* 0.272225071 */, 19 },
-
- /* 7344 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 19 },
- /* 7345 */ { MAD_F(0x045b7058) /* 0.272323936 */, 19 },
- /* 7346 */ { MAD_F(0x045ba42e) /* 0.272373372 */, 19 },
- /* 7347 */ { MAD_F(0x045bd805) /* 0.272422810 */, 19 },
- /* 7348 */ { MAD_F(0x045c0bdd) /* 0.272472251 */, 19 },
- /* 7349 */ { MAD_F(0x045c3fb5) /* 0.272521693 */, 19 },
- /* 7350 */ { MAD_F(0x045c738e) /* 0.272571138 */, 19 },
- /* 7351 */ { MAD_F(0x045ca767) /* 0.272620585 */, 19 },
- /* 7352 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 19 },
- /* 7353 */ { MAD_F(0x045d0f1b) /* 0.272719486 */, 19 },
- /* 7354 */ { MAD_F(0x045d42f7) /* 0.272768940 */, 19 },
- /* 7355 */ { MAD_F(0x045d76d2) /* 0.272818396 */, 19 },
- /* 7356 */ { MAD_F(0x045daaaf) /* 0.272867855 */, 19 },
- /* 7357 */ { MAD_F(0x045dde8c) /* 0.272917315 */, 19 },
- /* 7358 */ { MAD_F(0x045e1269) /* 0.272966778 */, 19 },
- /* 7359 */ { MAD_F(0x045e4647) /* 0.273016243 */, 19 },
-
- /* 7360 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 19 },
- /* 7361 */ { MAD_F(0x045eae06) /* 0.273115180 */, 19 },
- /* 7362 */ { MAD_F(0x045ee1e6) /* 0.273164652 */, 19 },
- /* 7363 */ { MAD_F(0x045f15c6) /* 0.273214126 */, 19 },
- /* 7364 */ { MAD_F(0x045f49a7) /* 0.273263602 */, 19 },
- /* 7365 */ { MAD_F(0x045f7d89) /* 0.273313081 */, 19 },
- /* 7366 */ { MAD_F(0x045fb16c) /* 0.273362561 */, 19 },
- /* 7367 */ { MAD_F(0x045fe54f) /* 0.273412044 */, 19 },
- /* 7368 */ { MAD_F(0x04601932) /* 0.273461530 */, 19 },
- /* 7369 */ { MAD_F(0x04604d16) /* 0.273511017 */, 19 },
- /* 7370 */ { MAD_F(0x046080fb) /* 0.273560507 */, 19 },
- /* 7371 */ { MAD_F(0x0460b4e1) /* 0.273609999 */, 19 },
- /* 7372 */ { MAD_F(0x0460e8c7) /* 0.273659493 */, 19 },
- /* 7373 */ { MAD_F(0x04611cad) /* 0.273708989 */, 19 },
- /* 7374 */ { MAD_F(0x04615094) /* 0.273758488 */, 19 },
- /* 7375 */ { MAD_F(0x0461847c) /* 0.273807989 */, 19 },
-
- /* 7376 */ { MAD_F(0x0461b864) /* 0.273857492 */, 19 },
- /* 7377 */ { MAD_F(0x0461ec4d) /* 0.273906997 */, 19 },
- /* 7378 */ { MAD_F(0x04622037) /* 0.273956505 */, 19 },
- /* 7379 */ { MAD_F(0x04625421) /* 0.274006015 */, 19 },
- /* 7380 */ { MAD_F(0x0462880c) /* 0.274055527 */, 19 },
- /* 7381 */ { MAD_F(0x0462bbf7) /* 0.274105041 */, 19 },
- /* 7382 */ { MAD_F(0x0462efe3) /* 0.274154558 */, 19 },
- /* 7383 */ { MAD_F(0x046323d0) /* 0.274204076 */, 19 },
- /* 7384 */ { MAD_F(0x046357bd) /* 0.274253597 */, 19 },
- /* 7385 */ { MAD_F(0x04638bab) /* 0.274303121 */, 19 },
- /* 7386 */ { MAD_F(0x0463bf99) /* 0.274352646 */, 19 },
- /* 7387 */ { MAD_F(0x0463f388) /* 0.274402174 */, 19 },
- /* 7388 */ { MAD_F(0x04642778) /* 0.274451704 */, 19 },
- /* 7389 */ { MAD_F(0x04645b68) /* 0.274501236 */, 19 },
- /* 7390 */ { MAD_F(0x04648f59) /* 0.274550771 */, 19 },
- /* 7391 */ { MAD_F(0x0464c34a) /* 0.274600307 */, 19 },
-
- /* 7392 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 19 },
- /* 7393 */ { MAD_F(0x04652b2f) /* 0.274699387 */, 19 },
- /* 7394 */ { MAD_F(0x04655f22) /* 0.274748931 */, 19 },
- /* 7395 */ { MAD_F(0x04659316) /* 0.274798476 */, 19 },
- /* 7396 */ { MAD_F(0x0465c70a) /* 0.274848024 */, 19 },
- /* 7397 */ { MAD_F(0x0465faff) /* 0.274897574 */, 19 },
- /* 7398 */ { MAD_F(0x04662ef5) /* 0.274947126 */, 19 },
- /* 7399 */ { MAD_F(0x046662eb) /* 0.274996681 */, 19 },
- /* 7400 */ { MAD_F(0x046696e2) /* 0.275046238 */, 19 },
- /* 7401 */ { MAD_F(0x0466cad9) /* 0.275095797 */, 19 },
- /* 7402 */ { MAD_F(0x0466fed1) /* 0.275145358 */, 19 },
- /* 7403 */ { MAD_F(0x046732ca) /* 0.275194921 */, 19 },
- /* 7404 */ { MAD_F(0x046766c3) /* 0.275244487 */, 19 },
- /* 7405 */ { MAD_F(0x04679abd) /* 0.275294055 */, 19 },
- /* 7406 */ { MAD_F(0x0467ceb7) /* 0.275343625 */, 19 },
- /* 7407 */ { MAD_F(0x046802b2) /* 0.275393198 */, 19 },
-
- /* 7408 */ { MAD_F(0x046836ae) /* 0.275442772 */, 19 },
- /* 7409 */ { MAD_F(0x04686aaa) /* 0.275492349 */, 19 },
- /* 7410 */ { MAD_F(0x04689ea7) /* 0.275541928 */, 19 },
- /* 7411 */ { MAD_F(0x0468d2a4) /* 0.275591509 */, 19 },
- /* 7412 */ { MAD_F(0x046906a2) /* 0.275641093 */, 19 },
- /* 7413 */ { MAD_F(0x04693aa1) /* 0.275690679 */, 19 },
- /* 7414 */ { MAD_F(0x04696ea0) /* 0.275740267 */, 19 },
- /* 7415 */ { MAD_F(0x0469a2a0) /* 0.275789857 */, 19 },
- /* 7416 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 19 },
- /* 7417 */ { MAD_F(0x046a0aa1) /* 0.275889044 */, 19 },
- /* 7418 */ { MAD_F(0x046a3ea3) /* 0.275938641 */, 19 },
- /* 7419 */ { MAD_F(0x046a72a5) /* 0.275988240 */, 19 },
- /* 7420 */ { MAD_F(0x046aa6a8) /* 0.276037842 */, 19 },
- /* 7421 */ { MAD_F(0x046adaab) /* 0.276087445 */, 19 },
- /* 7422 */ { MAD_F(0x046b0eaf) /* 0.276137051 */, 19 },
- /* 7423 */ { MAD_F(0x046b42b3) /* 0.276186659 */, 19 },
-
- /* 7424 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 19 },
- /* 7425 */ { MAD_F(0x046baabe) /* 0.276285882 */, 19 },
- /* 7426 */ { MAD_F(0x046bdec5) /* 0.276335497 */, 19 },
- /* 7427 */ { MAD_F(0x046c12cc) /* 0.276385113 */, 19 },
- /* 7428 */ { MAD_F(0x046c46d3) /* 0.276434733 */, 19 },
- /* 7429 */ { MAD_F(0x046c7adb) /* 0.276484354 */, 19 },
- /* 7430 */ { MAD_F(0x046caee4) /* 0.276533978 */, 19 },
- /* 7431 */ { MAD_F(0x046ce2ee) /* 0.276583604 */, 19 },
- /* 7432 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 19 },
- /* 7433 */ { MAD_F(0x046d4b02) /* 0.276682862 */, 19 },
- /* 7434 */ { MAD_F(0x046d7f0d) /* 0.276732495 */, 19 },
- /* 7435 */ { MAD_F(0x046db319) /* 0.276782129 */, 19 },
- /* 7436 */ { MAD_F(0x046de725) /* 0.276831766 */, 19 },
- /* 7437 */ { MAD_F(0x046e1b32) /* 0.276881406 */, 19 },
- /* 7438 */ { MAD_F(0x046e4f40) /* 0.276931047 */, 19 },
- /* 7439 */ { MAD_F(0x046e834e) /* 0.276980691 */, 19 },
-
- /* 7440 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 19 },
- /* 7441 */ { MAD_F(0x046eeb6c) /* 0.277079985 */, 19 },
- /* 7442 */ { MAD_F(0x046f1f7c) /* 0.277129635 */, 19 },
- /* 7443 */ { MAD_F(0x046f538c) /* 0.277179288 */, 19 },
- /* 7444 */ { MAD_F(0x046f879d) /* 0.277228942 */, 19 },
- /* 7445 */ { MAD_F(0x046fbbaf) /* 0.277278600 */, 19 },
- /* 7446 */ { MAD_F(0x046fefc1) /* 0.277328259 */, 19 },
- /* 7447 */ { MAD_F(0x047023d4) /* 0.277377920 */, 19 },
- /* 7448 */ { MAD_F(0x047057e8) /* 0.277427584 */, 19 },
- /* 7449 */ { MAD_F(0x04708bfc) /* 0.277477250 */, 19 },
- /* 7450 */ { MAD_F(0x0470c011) /* 0.277526918 */, 19 },
- /* 7451 */ { MAD_F(0x0470f426) /* 0.277576588 */, 19 },
- /* 7452 */ { MAD_F(0x0471283c) /* 0.277626261 */, 19 },
- /* 7453 */ { MAD_F(0x04715c52) /* 0.277675936 */, 19 },
- /* 7454 */ { MAD_F(0x04719069) /* 0.277725613 */, 19 },
- /* 7455 */ { MAD_F(0x0471c481) /* 0.277775292 */, 19 },
-
- /* 7456 */ { MAD_F(0x0471f899) /* 0.277824973 */, 19 },
- /* 7457 */ { MAD_F(0x04722cb2) /* 0.277874657 */, 19 },
- /* 7458 */ { MAD_F(0x047260cc) /* 0.277924343 */, 19 },
- /* 7459 */ { MAD_F(0x047294e6) /* 0.277974031 */, 19 },
- /* 7460 */ { MAD_F(0x0472c900) /* 0.278023722 */, 19 },
- /* 7461 */ { MAD_F(0x0472fd1b) /* 0.278073414 */, 19 },
- /* 7462 */ { MAD_F(0x04733137) /* 0.278123109 */, 19 },
- /* 7463 */ { MAD_F(0x04736554) /* 0.278172806 */, 19 },
- /* 7464 */ { MAD_F(0x04739971) /* 0.278222505 */, 19 },
- /* 7465 */ { MAD_F(0x0473cd8e) /* 0.278272207 */, 19 },
- /* 7466 */ { MAD_F(0x047401ad) /* 0.278321910 */, 19 },
- /* 7467 */ { MAD_F(0x047435cb) /* 0.278371616 */, 19 },
- /* 7468 */ { MAD_F(0x047469eb) /* 0.278421324 */, 19 },
- /* 7469 */ { MAD_F(0x04749e0b) /* 0.278471035 */, 19 },
- /* 7470 */ { MAD_F(0x0474d22c) /* 0.278520747 */, 19 },
- /* 7471 */ { MAD_F(0x0475064d) /* 0.278570462 */, 19 },
-
- /* 7472 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 19 },
- /* 7473 */ { MAD_F(0x04756e91) /* 0.278669898 */, 19 },
- /* 7474 */ { MAD_F(0x0475a2b4) /* 0.278719619 */, 19 },
- /* 7475 */ { MAD_F(0x0475d6d7) /* 0.278769343 */, 19 },
- /* 7476 */ { MAD_F(0x04760afc) /* 0.278819069 */, 19 },
- /* 7477 */ { MAD_F(0x04763f20) /* 0.278868797 */, 19 },
- /* 7478 */ { MAD_F(0x04767346) /* 0.278918527 */, 19 },
- /* 7479 */ { MAD_F(0x0476a76c) /* 0.278968260 */, 19 },
- /* 7480 */ { MAD_F(0x0476db92) /* 0.279017995 */, 19 },
- /* 7481 */ { MAD_F(0x04770fba) /* 0.279067731 */, 19 },
- /* 7482 */ { MAD_F(0x047743e1) /* 0.279117471 */, 19 },
- /* 7483 */ { MAD_F(0x0477780a) /* 0.279167212 */, 19 },
- /* 7484 */ { MAD_F(0x0477ac33) /* 0.279216956 */, 19 },
- /* 7485 */ { MAD_F(0x0477e05c) /* 0.279266701 */, 19 },
- /* 7486 */ { MAD_F(0x04781486) /* 0.279316449 */, 19 },
- /* 7487 */ { MAD_F(0x047848b1) /* 0.279366200 */, 19 },
-
- /* 7488 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 19 },
- /* 7489 */ { MAD_F(0x0478b108) /* 0.279465707 */, 19 },
- /* 7490 */ { MAD_F(0x0478e535) /* 0.279515464 */, 19 },
- /* 7491 */ { MAD_F(0x04791962) /* 0.279565223 */, 19 },
- /* 7492 */ { MAD_F(0x04794d8f) /* 0.279614984 */, 19 },
- /* 7493 */ { MAD_F(0x047981be) /* 0.279664748 */, 19 },
- /* 7494 */ { MAD_F(0x0479b5ed) /* 0.279714513 */, 19 },
- /* 7495 */ { MAD_F(0x0479ea1c) /* 0.279764281 */, 19 },
- /* 7496 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 19 },
- /* 7497 */ { MAD_F(0x047a527d) /* 0.279863824 */, 19 },
- /* 7498 */ { MAD_F(0x047a86ae) /* 0.279913598 */, 19 },
- /* 7499 */ { MAD_F(0x047abae0) /* 0.279963375 */, 19 },
- /* 7500 */ { MAD_F(0x047aef12) /* 0.280013154 */, 19 },
- /* 7501 */ { MAD_F(0x047b2346) /* 0.280062935 */, 19 },
- /* 7502 */ { MAD_F(0x047b5779) /* 0.280112719 */, 19 },
- /* 7503 */ { MAD_F(0x047b8bad) /* 0.280162504 */, 19 },
-
- /* 7504 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 19 },
- /* 7505 */ { MAD_F(0x047bf418) /* 0.280262082 */, 19 },
- /* 7506 */ { MAD_F(0x047c284e) /* 0.280311875 */, 19 },
- /* 7507 */ { MAD_F(0x047c5c84) /* 0.280361669 */, 19 },
- /* 7508 */ { MAD_F(0x047c90bb) /* 0.280411466 */, 19 },
- /* 7509 */ { MAD_F(0x047cc4f3) /* 0.280461265 */, 19 },
- /* 7510 */ { MAD_F(0x047cf92c) /* 0.280511066 */, 19 },
- /* 7511 */ { MAD_F(0x047d2d65) /* 0.280560869 */, 19 },
- /* 7512 */ { MAD_F(0x047d619e) /* 0.280610675 */, 19 },
- /* 7513 */ { MAD_F(0x047d95d8) /* 0.280660483 */, 19 },
- /* 7514 */ { MAD_F(0x047dca13) /* 0.280710292 */, 19 },
- /* 7515 */ { MAD_F(0x047dfe4e) /* 0.280760105 */, 19 },
- /* 7516 */ { MAD_F(0x047e328a) /* 0.280809919 */, 19 },
- /* 7517 */ { MAD_F(0x047e66c7) /* 0.280859736 */, 19 },
- /* 7518 */ { MAD_F(0x047e9b04) /* 0.280909554 */, 19 },
- /* 7519 */ { MAD_F(0x047ecf42) /* 0.280959375 */, 19 },
-
- /* 7520 */ { MAD_F(0x047f0380) /* 0.281009199 */, 19 },
- /* 7521 */ { MAD_F(0x047f37bf) /* 0.281059024 */, 19 },
- /* 7522 */ { MAD_F(0x047f6bff) /* 0.281108852 */, 19 },
- /* 7523 */ { MAD_F(0x047fa03f) /* 0.281158682 */, 19 },
- /* 7524 */ { MAD_F(0x047fd47f) /* 0.281208514 */, 19 },
- /* 7525 */ { MAD_F(0x048008c1) /* 0.281258348 */, 19 },
- /* 7526 */ { MAD_F(0x04803d02) /* 0.281308184 */, 19 },
- /* 7527 */ { MAD_F(0x04807145) /* 0.281358023 */, 19 },
- /* 7528 */ { MAD_F(0x0480a588) /* 0.281407864 */, 19 },
- /* 7529 */ { MAD_F(0x0480d9cc) /* 0.281457707 */, 19 },
- /* 7530 */ { MAD_F(0x04810e10) /* 0.281507552 */, 19 },
- /* 7531 */ { MAD_F(0x04814255) /* 0.281557400 */, 19 },
- /* 7532 */ { MAD_F(0x0481769a) /* 0.281607250 */, 19 },
- /* 7533 */ { MAD_F(0x0481aae0) /* 0.281657101 */, 19 },
- /* 7534 */ { MAD_F(0x0481df27) /* 0.281706956 */, 19 },
- /* 7535 */ { MAD_F(0x0482136e) /* 0.281756812 */, 19 },
-
- /* 7536 */ { MAD_F(0x048247b6) /* 0.281806670 */, 19 },
- /* 7537 */ { MAD_F(0x04827bfe) /* 0.281856531 */, 19 },
- /* 7538 */ { MAD_F(0x0482b047) /* 0.281906394 */, 19 },
- /* 7539 */ { MAD_F(0x0482e491) /* 0.281956259 */, 19 },
- /* 7540 */ { MAD_F(0x048318db) /* 0.282006127 */, 19 },
- /* 7541 */ { MAD_F(0x04834d26) /* 0.282055996 */, 19 },
- /* 7542 */ { MAD_F(0x04838171) /* 0.282105868 */, 19 },
- /* 7543 */ { MAD_F(0x0483b5bd) /* 0.282155742 */, 19 },
- /* 7544 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 19 },
- /* 7545 */ { MAD_F(0x04841e57) /* 0.282255496 */, 19 },
- /* 7546 */ { MAD_F(0x048452a4) /* 0.282305377 */, 19 },
- /* 7547 */ { MAD_F(0x048486f3) /* 0.282355260 */, 19 },
- /* 7548 */ { MAD_F(0x0484bb42) /* 0.282405145 */, 19 },
- /* 7549 */ { MAD_F(0x0484ef91) /* 0.282455032 */, 19 },
- /* 7550 */ { MAD_F(0x048523e1) /* 0.282504921 */, 19 },
- /* 7551 */ { MAD_F(0x04855832) /* 0.282554813 */, 19 },
-
- /* 7552 */ { MAD_F(0x04858c83) /* 0.282604707 */, 19 },
- /* 7553 */ { MAD_F(0x0485c0d5) /* 0.282654603 */, 19 },
- /* 7554 */ { MAD_F(0x0485f527) /* 0.282704501 */, 19 },
- /* 7555 */ { MAD_F(0x0486297a) /* 0.282754401 */, 19 },
- /* 7556 */ { MAD_F(0x04865dce) /* 0.282804304 */, 19 },
- /* 7557 */ { MAD_F(0x04869222) /* 0.282854209 */, 19 },
- /* 7558 */ { MAD_F(0x0486c677) /* 0.282904116 */, 19 },
- /* 7559 */ { MAD_F(0x0486facc) /* 0.282954025 */, 19 },
- /* 7560 */ { MAD_F(0x04872f22) /* 0.283003936 */, 19 },
- /* 7561 */ { MAD_F(0x04876379) /* 0.283053850 */, 19 },
- /* 7562 */ { MAD_F(0x048797d0) /* 0.283103766 */, 19 },
- /* 7563 */ { MAD_F(0x0487cc28) /* 0.283153684 */, 19 },
- /* 7564 */ { MAD_F(0x04880080) /* 0.283203604 */, 19 },
- /* 7565 */ { MAD_F(0x048834d9) /* 0.283253527 */, 19 },
- /* 7566 */ { MAD_F(0x04886933) /* 0.283303451 */, 19 },
- /* 7567 */ { MAD_F(0x04889d8d) /* 0.283353378 */, 19 },
-
- /* 7568 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 19 },
- /* 7569 */ { MAD_F(0x04890643) /* 0.283453238 */, 19 },
- /* 7570 */ { MAD_F(0x04893a9f) /* 0.283503172 */, 19 },
- /* 7571 */ { MAD_F(0x04896efb) /* 0.283553107 */, 19 },
- /* 7572 */ { MAD_F(0x0489a358) /* 0.283603045 */, 19 },
- /* 7573 */ { MAD_F(0x0489d7b6) /* 0.283652985 */, 19 },
- /* 7574 */ { MAD_F(0x048a0c14) /* 0.283702927 */, 19 },
- /* 7575 */ { MAD_F(0x048a4073) /* 0.283752872 */, 19 },
- /* 7576 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 19 },
- /* 7577 */ { MAD_F(0x048aa933) /* 0.283852767 */, 19 },
- /* 7578 */ { MAD_F(0x048add93) /* 0.283902718 */, 19 },
- /* 7579 */ { MAD_F(0x048b11f5) /* 0.283952671 */, 19 },
- /* 7580 */ { MAD_F(0x048b4656) /* 0.284002627 */, 19 },
- /* 7581 */ { MAD_F(0x048b7ab9) /* 0.284052584 */, 19 },
- /* 7582 */ { MAD_F(0x048baf1c) /* 0.284102544 */, 19 },
- /* 7583 */ { MAD_F(0x048be37f) /* 0.284152506 */, 19 },
-
- /* 7584 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 19 },
- /* 7585 */ { MAD_F(0x048c4c48) /* 0.284252436 */, 19 },
- /* 7586 */ { MAD_F(0x048c80ad) /* 0.284302405 */, 19 },
- /* 7587 */ { MAD_F(0x048cb513) /* 0.284352376 */, 19 },
- /* 7588 */ { MAD_F(0x048ce97a) /* 0.284402349 */, 19 },
- /* 7589 */ { MAD_F(0x048d1de1) /* 0.284452324 */, 19 },
- /* 7590 */ { MAD_F(0x048d5249) /* 0.284502301 */, 19 },
- /* 7591 */ { MAD_F(0x048d86b1) /* 0.284552281 */, 19 },
- /* 7592 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 19 },
- /* 7593 */ { MAD_F(0x048def83) /* 0.284652246 */, 19 },
- /* 7594 */ { MAD_F(0x048e23ed) /* 0.284702233 */, 19 },
- /* 7595 */ { MAD_F(0x048e5858) /* 0.284752221 */, 19 },
- /* 7596 */ { MAD_F(0x048e8cc3) /* 0.284802211 */, 19 },
- /* 7597 */ { MAD_F(0x048ec12f) /* 0.284852204 */, 19 },
- /* 7598 */ { MAD_F(0x048ef59b) /* 0.284902199 */, 19 },
- /* 7599 */ { MAD_F(0x048f2a08) /* 0.284952196 */, 19 },
-
- /* 7600 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 19 },
- /* 7601 */ { MAD_F(0x048f92e4) /* 0.285052197 */, 19 },
- /* 7602 */ { MAD_F(0x048fc753) /* 0.285102201 */, 19 },
- /* 7603 */ { MAD_F(0x048ffbc2) /* 0.285152206 */, 19 },
- /* 7604 */ { MAD_F(0x04903032) /* 0.285202214 */, 19 },
- /* 7605 */ { MAD_F(0x049064a3) /* 0.285252225 */, 19 },
- /* 7606 */ { MAD_F(0x04909914) /* 0.285302237 */, 19 },
- /* 7607 */ { MAD_F(0x0490cd86) /* 0.285352252 */, 19 },
- /* 7608 */ { MAD_F(0x049101f8) /* 0.285402269 */, 19 },
- /* 7609 */ { MAD_F(0x0491366b) /* 0.285452288 */, 19 },
- /* 7610 */ { MAD_F(0x04916ade) /* 0.285502309 */, 19 },
- /* 7611 */ { MAD_F(0x04919f52) /* 0.285552332 */, 19 },
- /* 7612 */ { MAD_F(0x0491d3c7) /* 0.285602358 */, 19 },
- /* 7613 */ { MAD_F(0x0492083c) /* 0.285652386 */, 19 },
- /* 7614 */ { MAD_F(0x04923cb2) /* 0.285702416 */, 19 },
- /* 7615 */ { MAD_F(0x04927128) /* 0.285752448 */, 19 },
-
- /* 7616 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 19 },
- /* 7617 */ { MAD_F(0x0492da17) /* 0.285852519 */, 19 },
- /* 7618 */ { MAD_F(0x04930e8f) /* 0.285902557 */, 19 },
- /* 7619 */ { MAD_F(0x04934308) /* 0.285952598 */, 19 },
- /* 7620 */ { MAD_F(0x04937781) /* 0.286002641 */, 19 },
- /* 7621 */ { MAD_F(0x0493abfb) /* 0.286052687 */, 19 },
- /* 7622 */ { MAD_F(0x0493e076) /* 0.286102734 */, 19 },
- /* 7623 */ { MAD_F(0x049414f1) /* 0.286152784 */, 19 },
- /* 7624 */ { MAD_F(0x0494496c) /* 0.286202836 */, 19 },
- /* 7625 */ { MAD_F(0x04947de9) /* 0.286252890 */, 19 },
- /* 7626 */ { MAD_F(0x0494b266) /* 0.286302946 */, 19 },
- /* 7627 */ { MAD_F(0x0494e6e3) /* 0.286353005 */, 19 },
- /* 7628 */ { MAD_F(0x04951b61) /* 0.286403065 */, 19 },
- /* 7629 */ { MAD_F(0x04954fe0) /* 0.286453128 */, 19 },
- /* 7630 */ { MAD_F(0x0495845f) /* 0.286503193 */, 19 },
- /* 7631 */ { MAD_F(0x0495b8df) /* 0.286553260 */, 19 },
-
- /* 7632 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 19 },
- /* 7633 */ { MAD_F(0x049621e0) /* 0.286653401 */, 19 },
- /* 7634 */ { MAD_F(0x04965662) /* 0.286703475 */, 19 },
- /* 7635 */ { MAD_F(0x04968ae4) /* 0.286753551 */, 19 },
- /* 7636 */ { MAD_F(0x0496bf67) /* 0.286803629 */, 19 },
- /* 7637 */ { MAD_F(0x0496f3ea) /* 0.286853709 */, 19 },
- /* 7638 */ { MAD_F(0x0497286e) /* 0.286903792 */, 19 },
- /* 7639 */ { MAD_F(0x04975cf2) /* 0.286953876 */, 19 },
- /* 7640 */ { MAD_F(0x04979177) /* 0.287003963 */, 19 },
- /* 7641 */ { MAD_F(0x0497c5fd) /* 0.287054052 */, 19 },
- /* 7642 */ { MAD_F(0x0497fa83) /* 0.287104143 */, 19 },
- /* 7643 */ { MAD_F(0x04982f0a) /* 0.287154237 */, 19 },
- /* 7644 */ { MAD_F(0x04986392) /* 0.287204332 */, 19 },
- /* 7645 */ { MAD_F(0x0498981a) /* 0.287254430 */, 19 },
- /* 7646 */ { MAD_F(0x0498cca2) /* 0.287304530 */, 19 },
- /* 7647 */ { MAD_F(0x0499012c) /* 0.287354632 */, 19 },
-
- /* 7648 */ { MAD_F(0x049935b5) /* 0.287404737 */, 19 },
- /* 7649 */ { MAD_F(0x04996a40) /* 0.287454843 */, 19 },
- /* 7650 */ { MAD_F(0x04999ecb) /* 0.287504952 */, 19 },
- /* 7651 */ { MAD_F(0x0499d356) /* 0.287555063 */, 19 },
- /* 7652 */ { MAD_F(0x049a07e2) /* 0.287605176 */, 19 },
- /* 7653 */ { MAD_F(0x049a3c6f) /* 0.287655291 */, 19 },
- /* 7654 */ { MAD_F(0x049a70fc) /* 0.287705409 */, 19 },
- /* 7655 */ { MAD_F(0x049aa58a) /* 0.287755528 */, 19 },
- /* 7656 */ { MAD_F(0x049ada19) /* 0.287805650 */, 19 },
- /* 7657 */ { MAD_F(0x049b0ea8) /* 0.287855774 */, 19 },
- /* 7658 */ { MAD_F(0x049b4337) /* 0.287905900 */, 19 },
- /* 7659 */ { MAD_F(0x049b77c8) /* 0.287956028 */, 19 },
- /* 7660 */ { MAD_F(0x049bac58) /* 0.288006159 */, 19 },
- /* 7661 */ { MAD_F(0x049be0ea) /* 0.288056292 */, 19 },
- /* 7662 */ { MAD_F(0x049c157c) /* 0.288106427 */, 19 },
- /* 7663 */ { MAD_F(0x049c4a0e) /* 0.288156564 */, 19 },
-
- /* 7664 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 19 },
- /* 7665 */ { MAD_F(0x049cb335) /* 0.288256844 */, 19 },
- /* 7666 */ { MAD_F(0x049ce7ca) /* 0.288306988 */, 19 },
- /* 7667 */ { MAD_F(0x049d1c5e) /* 0.288357134 */, 19 },
- /* 7668 */ { MAD_F(0x049d50f4) /* 0.288407282 */, 19 },
- /* 7669 */ { MAD_F(0x049d858a) /* 0.288457432 */, 19 },
- /* 7670 */ { MAD_F(0x049dba21) /* 0.288507584 */, 19 },
- /* 7671 */ { MAD_F(0x049deeb8) /* 0.288557739 */, 19 },
- /* 7672 */ { MAD_F(0x049e2350) /* 0.288607895 */, 19 },
- /* 7673 */ { MAD_F(0x049e57e8) /* 0.288658054 */, 19 },
- /* 7674 */ { MAD_F(0x049e8c81) /* 0.288708215 */, 19 },
- /* 7675 */ { MAD_F(0x049ec11b) /* 0.288758379 */, 19 },
- /* 7676 */ { MAD_F(0x049ef5b5) /* 0.288808544 */, 19 },
- /* 7677 */ { MAD_F(0x049f2a50) /* 0.288858712 */, 19 },
- /* 7678 */ { MAD_F(0x049f5eeb) /* 0.288908881 */, 19 },
- /* 7679 */ { MAD_F(0x049f9387) /* 0.288959053 */, 19 },
-
- /* 7680 */ { MAD_F(0x049fc824) /* 0.289009227 */, 19 },
- /* 7681 */ { MAD_F(0x049ffcc1) /* 0.289059404 */, 19 },
- /* 7682 */ { MAD_F(0x04a0315e) /* 0.289109582 */, 19 },
- /* 7683 */ { MAD_F(0x04a065fd) /* 0.289159763 */, 19 },
- /* 7684 */ { MAD_F(0x04a09a9b) /* 0.289209946 */, 19 },
- /* 7685 */ { MAD_F(0x04a0cf3b) /* 0.289260131 */, 19 },
- /* 7686 */ { MAD_F(0x04a103db) /* 0.289310318 */, 19 },
- /* 7687 */ { MAD_F(0x04a1387b) /* 0.289360507 */, 19 },
- /* 7688 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 19 },
- /* 7689 */ { MAD_F(0x04a1a1be) /* 0.289460893 */, 19 },
- /* 7690 */ { MAD_F(0x04a1d661) /* 0.289511088 */, 19 },
- /* 7691 */ { MAD_F(0x04a20b04) /* 0.289561287 */, 19 },
- /* 7692 */ { MAD_F(0x04a23fa7) /* 0.289611487 */, 19 },
- /* 7693 */ { MAD_F(0x04a2744b) /* 0.289661689 */, 19 },
- /* 7694 */ { MAD_F(0x04a2a8f0) /* 0.289711894 */, 19 },
- /* 7695 */ { MAD_F(0x04a2dd95) /* 0.289762101 */, 19 },
-
- /* 7696 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 19 },
- /* 7697 */ { MAD_F(0x04a346e2) /* 0.289862521 */, 19 },
- /* 7698 */ { MAD_F(0x04a37b89) /* 0.289912734 */, 19 },
- /* 7699 */ { MAD_F(0x04a3b030) /* 0.289962949 */, 19 },
- /* 7700 */ { MAD_F(0x04a3e4d8) /* 0.290013167 */, 19 },
- /* 7701 */ { MAD_F(0x04a41981) /* 0.290063387 */, 19 },
- /* 7702 */ { MAD_F(0x04a44e2b) /* 0.290113609 */, 19 },
- /* 7703 */ { MAD_F(0x04a482d5) /* 0.290163833 */, 19 },
- /* 7704 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 19 },
- /* 7705 */ { MAD_F(0x04a4ec2a) /* 0.290264288 */, 19 },
- /* 7706 */ { MAD_F(0x04a520d6) /* 0.290314519 */, 19 },
- /* 7707 */ { MAD_F(0x04a55582) /* 0.290364751 */, 19 },
- /* 7708 */ { MAD_F(0x04a58a2f) /* 0.290414986 */, 19 },
- /* 7709 */ { MAD_F(0x04a5bedd) /* 0.290465224 */, 19 },
- /* 7710 */ { MAD_F(0x04a5f38b) /* 0.290515463 */, 19 },
- /* 7711 */ { MAD_F(0x04a62839) /* 0.290565705 */, 19 },
-
- /* 7712 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 19 },
- /* 7713 */ { MAD_F(0x04a69198) /* 0.290666194 */, 19 },
- /* 7714 */ { MAD_F(0x04a6c648) /* 0.290716442 */, 19 },
- /* 7715 */ { MAD_F(0x04a6faf9) /* 0.290766692 */, 19 },
- /* 7716 */ { MAD_F(0x04a72fab) /* 0.290816945 */, 19 },
- /* 7717 */ { MAD_F(0x04a7645d) /* 0.290867199 */, 19 },
- /* 7718 */ { MAD_F(0x04a79910) /* 0.290917456 */, 19 },
- /* 7719 */ { MAD_F(0x04a7cdc3) /* 0.290967715 */, 19 },
- /* 7720 */ { MAD_F(0x04a80277) /* 0.291017976 */, 19 },
- /* 7721 */ { MAD_F(0x04a8372b) /* 0.291068239 */, 19 },
- /* 7722 */ { MAD_F(0x04a86be0) /* 0.291118505 */, 19 },
- /* 7723 */ { MAD_F(0x04a8a096) /* 0.291168772 */, 19 },
- /* 7724 */ { MAD_F(0x04a8d54c) /* 0.291219042 */, 19 },
- /* 7725 */ { MAD_F(0x04a90a03) /* 0.291269314 */, 19 },
- /* 7726 */ { MAD_F(0x04a93eba) /* 0.291319588 */, 19 },
- /* 7727 */ { MAD_F(0x04a97372) /* 0.291369865 */, 19 },
-
- /* 7728 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 19 },
- /* 7729 */ { MAD_F(0x04a9dce4) /* 0.291470424 */, 19 },
- /* 7730 */ { MAD_F(0x04aa119d) /* 0.291520706 */, 19 },
- /* 7731 */ { MAD_F(0x04aa4658) /* 0.291570991 */, 19 },
- /* 7732 */ { MAD_F(0x04aa7b13) /* 0.291621278 */, 19 },
- /* 7733 */ { MAD_F(0x04aaafce) /* 0.291671568 */, 19 },
- /* 7734 */ { MAD_F(0x04aae48a) /* 0.291721859 */, 19 },
- /* 7735 */ { MAD_F(0x04ab1947) /* 0.291772153 */, 19 },
- /* 7736 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 19 },
- /* 7737 */ { MAD_F(0x04ab82c2) /* 0.291872747 */, 19 },
- /* 7738 */ { MAD_F(0x04abb780) /* 0.291923047 */, 19 },
- /* 7739 */ { MAD_F(0x04abec3f) /* 0.291973349 */, 19 },
- /* 7740 */ { MAD_F(0x04ac20fe) /* 0.292023653 */, 19 },
- /* 7741 */ { MAD_F(0x04ac55be) /* 0.292073960 */, 19 },
- /* 7742 */ { MAD_F(0x04ac8a7f) /* 0.292124269 */, 19 },
- /* 7743 */ { MAD_F(0x04acbf40) /* 0.292174580 */, 19 },
-
- /* 7744 */ { MAD_F(0x04acf402) /* 0.292224893 */, 19 },
- /* 7745 */ { MAD_F(0x04ad28c5) /* 0.292275208 */, 19 },
- /* 7746 */ { MAD_F(0x04ad5d88) /* 0.292325526 */, 19 },
- /* 7747 */ { MAD_F(0x04ad924b) /* 0.292375845 */, 19 },
- /* 7748 */ { MAD_F(0x04adc70f) /* 0.292426167 */, 19 },
- /* 7749 */ { MAD_F(0x04adfbd4) /* 0.292476491 */, 19 },
- /* 7750 */ { MAD_F(0x04ae3099) /* 0.292526817 */, 19 },
- /* 7751 */ { MAD_F(0x04ae655f) /* 0.292577145 */, 19 },
- /* 7752 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 19 },
- /* 7753 */ { MAD_F(0x04aeceed) /* 0.292677808 */, 19 },
- /* 7754 */ { MAD_F(0x04af03b4) /* 0.292728143 */, 19 },
- /* 7755 */ { MAD_F(0x04af387d) /* 0.292778480 */, 19 },
- /* 7756 */ { MAD_F(0x04af6d45) /* 0.292828819 */, 19 },
- /* 7757 */ { MAD_F(0x04afa20f) /* 0.292879160 */, 19 },
- /* 7758 */ { MAD_F(0x04afd6d9) /* 0.292929504 */, 19 },
- /* 7759 */ { MAD_F(0x04b00ba3) /* 0.292979849 */, 19 },
-
- /* 7760 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 19 },
- /* 7761 */ { MAD_F(0x04b0753a) /* 0.293080547 */, 19 },
- /* 7762 */ { MAD_F(0x04b0aa06) /* 0.293130899 */, 19 },
- /* 7763 */ { MAD_F(0x04b0ded3) /* 0.293181253 */, 19 },
- /* 7764 */ { MAD_F(0x04b113a1) /* 0.293231610 */, 19 },
- /* 7765 */ { MAD_F(0x04b1486f) /* 0.293281968 */, 19 },
- /* 7766 */ { MAD_F(0x04b17d3d) /* 0.293332329 */, 19 },
- /* 7767 */ { MAD_F(0x04b1b20c) /* 0.293382692 */, 19 },
- /* 7768 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 19 },
- /* 7769 */ { MAD_F(0x04b21bad) /* 0.293483424 */, 19 },
- /* 7770 */ { MAD_F(0x04b2507d) /* 0.293533794 */, 19 },
- /* 7771 */ { MAD_F(0x04b2854f) /* 0.293584165 */, 19 },
- /* 7772 */ { MAD_F(0x04b2ba21) /* 0.293634539 */, 19 },
- /* 7773 */ { MAD_F(0x04b2eef4) /* 0.293684915 */, 19 },
- /* 7774 */ { MAD_F(0x04b323c7) /* 0.293735293 */, 19 },
- /* 7775 */ { MAD_F(0x04b3589b) /* 0.293785673 */, 19 },
-
- /* 7776 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 19 },
- /* 7777 */ { MAD_F(0x04b3c244) /* 0.293886440 */, 19 },
- /* 7778 */ { MAD_F(0x04b3f71a) /* 0.293936826 */, 19 },
- /* 7779 */ { MAD_F(0x04b42bf0) /* 0.293987215 */, 19 },
- /* 7780 */ { MAD_F(0x04b460c7) /* 0.294037606 */, 19 },
- /* 7781 */ { MAD_F(0x04b4959e) /* 0.294087999 */, 19 },
- /* 7782 */ { MAD_F(0x04b4ca76) /* 0.294138395 */, 19 },
- /* 7783 */ { MAD_F(0x04b4ff4e) /* 0.294188792 */, 19 },
- /* 7784 */ { MAD_F(0x04b53427) /* 0.294239192 */, 19 },
- /* 7785 */ { MAD_F(0x04b56901) /* 0.294289593 */, 19 },
- /* 7786 */ { MAD_F(0x04b59ddb) /* 0.294339997 */, 19 },
- /* 7787 */ { MAD_F(0x04b5d2b6) /* 0.294390403 */, 19 },
- /* 7788 */ { MAD_F(0x04b60791) /* 0.294440812 */, 19 },
- /* 7789 */ { MAD_F(0x04b63c6d) /* 0.294491222 */, 19 },
- /* 7790 */ { MAD_F(0x04b6714a) /* 0.294541635 */, 19 },
- /* 7791 */ { MAD_F(0x04b6a627) /* 0.294592049 */, 19 },
-
- /* 7792 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 19 },
- /* 7793 */ { MAD_F(0x04b70fe3) /* 0.294692885 */, 19 },
- /* 7794 */ { MAD_F(0x04b744c2) /* 0.294743306 */, 19 },
- /* 7795 */ { MAD_F(0x04b779a1) /* 0.294793730 */, 19 },
- /* 7796 */ { MAD_F(0x04b7ae81) /* 0.294844155 */, 19 },
- /* 7797 */ { MAD_F(0x04b7e362) /* 0.294894583 */, 19 },
- /* 7798 */ { MAD_F(0x04b81843) /* 0.294945013 */, 19 },
- /* 7799 */ { MAD_F(0x04b84d24) /* 0.294995445 */, 19 },
- /* 7800 */ { MAD_F(0x04b88207) /* 0.295045879 */, 19 },
- /* 7801 */ { MAD_F(0x04b8b6ea) /* 0.295096315 */, 19 },
- /* 7802 */ { MAD_F(0x04b8ebcd) /* 0.295146753 */, 19 },
- /* 7803 */ { MAD_F(0x04b920b1) /* 0.295197194 */, 19 },
- /* 7804 */ { MAD_F(0x04b95596) /* 0.295247637 */, 19 },
- /* 7805 */ { MAD_F(0x04b98a7b) /* 0.295298082 */, 19 },
- /* 7806 */ { MAD_F(0x04b9bf61) /* 0.295348529 */, 19 },
- /* 7807 */ { MAD_F(0x04b9f447) /* 0.295398978 */, 19 },
-
- /* 7808 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 19 },
- /* 7809 */ { MAD_F(0x04ba5e16) /* 0.295499883 */, 19 },
- /* 7810 */ { MAD_F(0x04ba92fe) /* 0.295550338 */, 19 },
- /* 7811 */ { MAD_F(0x04bac7e6) /* 0.295600796 */, 19 },
- /* 7812 */ { MAD_F(0x04bafcd0) /* 0.295651256 */, 19 },
- /* 7813 */ { MAD_F(0x04bb31b9) /* 0.295701718 */, 19 },
- /* 7814 */ { MAD_F(0x04bb66a4) /* 0.295752183 */, 19 },
- /* 7815 */ { MAD_F(0x04bb9b8f) /* 0.295802649 */, 19 },
- /* 7816 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 19 },
- /* 7817 */ { MAD_F(0x04bc0566) /* 0.295903588 */, 19 },
- /* 7818 */ { MAD_F(0x04bc3a53) /* 0.295954061 */, 19 },
- /* 7819 */ { MAD_F(0x04bc6f40) /* 0.296004536 */, 19 },
- /* 7820 */ { MAD_F(0x04bca42e) /* 0.296055013 */, 19 },
- /* 7821 */ { MAD_F(0x04bcd91d) /* 0.296105493 */, 19 },
- /* 7822 */ { MAD_F(0x04bd0e0c) /* 0.296155974 */, 19 },
- /* 7823 */ { MAD_F(0x04bd42fb) /* 0.296206458 */, 19 },
-
- /* 7824 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 19 },
- /* 7825 */ { MAD_F(0x04bdacdc) /* 0.296307432 */, 19 },
- /* 7826 */ { MAD_F(0x04bde1ce) /* 0.296357922 */, 19 },
- /* 7827 */ { MAD_F(0x04be16c0) /* 0.296408414 */, 19 },
- /* 7828 */ { MAD_F(0x04be4bb2) /* 0.296458908 */, 19 },
- /* 7829 */ { MAD_F(0x04be80a5) /* 0.296509405 */, 19 },
- /* 7830 */ { MAD_F(0x04beb599) /* 0.296559904 */, 19 },
- /* 7831 */ { MAD_F(0x04beea8d) /* 0.296610404 */, 19 },
- /* 7832 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 19 },
- /* 7833 */ { MAD_F(0x04bf5477) /* 0.296711413 */, 19 },
- /* 7834 */ { MAD_F(0x04bf896d) /* 0.296761920 */, 19 },
- /* 7835 */ { MAD_F(0x04bfbe64) /* 0.296812429 */, 19 },
- /* 7836 */ { MAD_F(0x04bff35b) /* 0.296862941 */, 19 },
- /* 7837 */ { MAD_F(0x04c02852) /* 0.296913455 */, 19 },
- /* 7838 */ { MAD_F(0x04c05d4b) /* 0.296963971 */, 19 },
- /* 7839 */ { MAD_F(0x04c09243) /* 0.297014489 */, 19 },
-
- /* 7840 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 19 },
- /* 7841 */ { MAD_F(0x04c0fc37) /* 0.297115531 */, 19 },
- /* 7842 */ { MAD_F(0x04c13131) /* 0.297166056 */, 19 },
- /* 7843 */ { MAD_F(0x04c1662d) /* 0.297216582 */, 19 },
- /* 7844 */ { MAD_F(0x04c19b28) /* 0.297267111 */, 19 },
- /* 7845 */ { MAD_F(0x04c1d025) /* 0.297317642 */, 19 },
- /* 7846 */ { MAD_F(0x04c20521) /* 0.297368175 */, 19 },
- /* 7847 */ { MAD_F(0x04c23a1f) /* 0.297418710 */, 19 },
- /* 7848 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 19 },
- /* 7849 */ { MAD_F(0x04c2a41b) /* 0.297519787 */, 19 },
- /* 7850 */ { MAD_F(0x04c2d91b) /* 0.297570329 */, 19 },
- /* 7851 */ { MAD_F(0x04c30e1a) /* 0.297620873 */, 19 },
- /* 7852 */ { MAD_F(0x04c3431b) /* 0.297671418 */, 19 },
- /* 7853 */ { MAD_F(0x04c3781c) /* 0.297721967 */, 19 },
- /* 7854 */ { MAD_F(0x04c3ad1d) /* 0.297772517 */, 19 },
- /* 7855 */ { MAD_F(0x04c3e21f) /* 0.297823069 */, 19 },
-
- /* 7856 */ { MAD_F(0x04c41722) /* 0.297873624 */, 19 },
- /* 7857 */ { MAD_F(0x04c44c25) /* 0.297924180 */, 19 },
- /* 7858 */ { MAD_F(0x04c48129) /* 0.297974739 */, 19 },
- /* 7859 */ { MAD_F(0x04c4b62d) /* 0.298025300 */, 19 },
- /* 7860 */ { MAD_F(0x04c4eb32) /* 0.298075863 */, 19 },
- /* 7861 */ { MAD_F(0x04c52038) /* 0.298126429 */, 19 },
- /* 7862 */ { MAD_F(0x04c5553e) /* 0.298176996 */, 19 },
- /* 7863 */ { MAD_F(0x04c58a44) /* 0.298227565 */, 19 },
- /* 7864 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 19 },
- /* 7865 */ { MAD_F(0x04c5f453) /* 0.298328711 */, 19 },
- /* 7866 */ { MAD_F(0x04c6295c) /* 0.298379287 */, 19 },
- /* 7867 */ { MAD_F(0x04c65e65) /* 0.298429865 */, 19 },
- /* 7868 */ { MAD_F(0x04c6936e) /* 0.298480445 */, 19 },
- /* 7869 */ { MAD_F(0x04c6c878) /* 0.298531028 */, 19 },
- /* 7870 */ { MAD_F(0x04c6fd83) /* 0.298581612 */, 19 },
- /* 7871 */ { MAD_F(0x04c7328e) /* 0.298632199 */, 19 },
-
- /* 7872 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 19 },
- /* 7873 */ { MAD_F(0x04c79ca7) /* 0.298733379 */, 19 },
- /* 7874 */ { MAD_F(0x04c7d1b4) /* 0.298783972 */, 19 },
- /* 7875 */ { MAD_F(0x04c806c1) /* 0.298834567 */, 19 },
- /* 7876 */ { MAD_F(0x04c83bcf) /* 0.298885165 */, 19 },
- /* 7877 */ { MAD_F(0x04c870de) /* 0.298935764 */, 19 },
- /* 7878 */ { MAD_F(0x04c8a5ed) /* 0.298986366 */, 19 },
- /* 7879 */ { MAD_F(0x04c8dafd) /* 0.299036970 */, 19 },
- /* 7880 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 19 },
- /* 7881 */ { MAD_F(0x04c9451e) /* 0.299138184 */, 19 },
- /* 7882 */ { MAD_F(0x04c97a30) /* 0.299188794 */, 19 },
- /* 7883 */ { MAD_F(0x04c9af42) /* 0.299239406 */, 19 },
- /* 7884 */ { MAD_F(0x04c9e455) /* 0.299290021 */, 19 },
- /* 7885 */ { MAD_F(0x04ca1968) /* 0.299340638 */, 19 },
- /* 7886 */ { MAD_F(0x04ca4e7c) /* 0.299391256 */, 19 },
- /* 7887 */ { MAD_F(0x04ca8391) /* 0.299441877 */, 19 },
-
- /* 7888 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 19 },
- /* 7889 */ { MAD_F(0x04caedbb) /* 0.299543126 */, 19 },
- /* 7890 */ { MAD_F(0x04cb22d1) /* 0.299593753 */, 19 },
- /* 7891 */ { MAD_F(0x04cb57e8) /* 0.299644382 */, 19 },
- /* 7892 */ { MAD_F(0x04cb8d00) /* 0.299695014 */, 19 },
- /* 7893 */ { MAD_F(0x04cbc217) /* 0.299745648 */, 19 },
- /* 7894 */ { MAD_F(0x04cbf730) /* 0.299796284 */, 19 },
- /* 7895 */ { MAD_F(0x04cc2c49) /* 0.299846922 */, 19 },
- /* 7896 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 19 },
- /* 7897 */ { MAD_F(0x04cc967d) /* 0.299948204 */, 19 },
- /* 7898 */ { MAD_F(0x04cccb98) /* 0.299998849 */, 19 },
- /* 7899 */ { MAD_F(0x04cd00b3) /* 0.300049495 */, 19 },
- /* 7900 */ { MAD_F(0x04cd35cf) /* 0.300100144 */, 19 },
- /* 7901 */ { MAD_F(0x04cd6aeb) /* 0.300150795 */, 19 },
- /* 7902 */ { MAD_F(0x04cda008) /* 0.300201448 */, 19 },
- /* 7903 */ { MAD_F(0x04cdd526) /* 0.300252103 */, 19 },
-
- /* 7904 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 19 },
- /* 7905 */ { MAD_F(0x04ce3f63) /* 0.300353420 */, 19 },
- /* 7906 */ { MAD_F(0x04ce7482) /* 0.300404082 */, 19 },
- /* 7907 */ { MAD_F(0x04cea9a2) /* 0.300454745 */, 19 },
- /* 7908 */ { MAD_F(0x04cedec3) /* 0.300505411 */, 19 },
- /* 7909 */ { MAD_F(0x04cf13e4) /* 0.300556079 */, 19 },
- /* 7910 */ { MAD_F(0x04cf4906) /* 0.300606749 */, 19 },
- /* 7911 */ { MAD_F(0x04cf7e28) /* 0.300657421 */, 19 },
- /* 7912 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 19 },
- /* 7913 */ { MAD_F(0x04cfe86e) /* 0.300758772 */, 19 },
- /* 7914 */ { MAD_F(0x04d01d92) /* 0.300809451 */, 19 },
- /* 7915 */ { MAD_F(0x04d052b6) /* 0.300860132 */, 19 },
- /* 7916 */ { MAD_F(0x04d087db) /* 0.300910815 */, 19 },
- /* 7917 */ { MAD_F(0x04d0bd01) /* 0.300961500 */, 19 },
- /* 7918 */ { MAD_F(0x04d0f227) /* 0.301012187 */, 19 },
- /* 7919 */ { MAD_F(0x04d1274e) /* 0.301062876 */, 19 },
-
- /* 7920 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 19 },
- /* 7921 */ { MAD_F(0x04d1919e) /* 0.301164261 */, 19 },
- /* 7922 */ { MAD_F(0x04d1c6c6) /* 0.301214957 */, 19 },
- /* 7923 */ { MAD_F(0x04d1fbef) /* 0.301265655 */, 19 },
- /* 7924 */ { MAD_F(0x04d23119) /* 0.301316355 */, 19 },
- /* 7925 */ { MAD_F(0x04d26643) /* 0.301367057 */, 19 },
- /* 7926 */ { MAD_F(0x04d29b6e) /* 0.301417761 */, 19 },
- /* 7927 */ { MAD_F(0x04d2d099) /* 0.301468468 */, 19 },
- /* 7928 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 19 },
- /* 7929 */ { MAD_F(0x04d33af2) /* 0.301569887 */, 19 },
- /* 7930 */ { MAD_F(0x04d3701f) /* 0.301620599 */, 19 },
- /* 7931 */ { MAD_F(0x04d3a54d) /* 0.301671314 */, 19 },
- /* 7932 */ { MAD_F(0x04d3da7b) /* 0.301722031 */, 19 },
- /* 7933 */ { MAD_F(0x04d40faa) /* 0.301772751 */, 19 },
- /* 7934 */ { MAD_F(0x04d444d9) /* 0.301823472 */, 19 },
- /* 7935 */ { MAD_F(0x04d47a09) /* 0.301874195 */, 19 },
-
- /* 7936 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 19 },
- /* 7937 */ { MAD_F(0x04d4e46b) /* 0.301975649 */, 19 },
- /* 7938 */ { MAD_F(0x04d5199c) /* 0.302026378 */, 19 },
- /* 7939 */ { MAD_F(0x04d54ecf) /* 0.302077110 */, 19 },
- /* 7940 */ { MAD_F(0x04d58401) /* 0.302127845 */, 19 },
- /* 7941 */ { MAD_F(0x04d5b935) /* 0.302178581 */, 19 },
- /* 7942 */ { MAD_F(0x04d5ee69) /* 0.302229319 */, 19 },
- /* 7943 */ { MAD_F(0x04d6239d) /* 0.302280060 */, 19 },
- /* 7944 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 19 },
- /* 7945 */ { MAD_F(0x04d68e08) /* 0.302381547 */, 19 },
- /* 7946 */ { MAD_F(0x04d6c33e) /* 0.302432294 */, 19 },
- /* 7947 */ { MAD_F(0x04d6f875) /* 0.302483043 */, 19 },
- /* 7948 */ { MAD_F(0x04d72dad) /* 0.302533794 */, 19 },
- /* 7949 */ { MAD_F(0x04d762e5) /* 0.302584547 */, 19 },
- /* 7950 */ { MAD_F(0x04d7981d) /* 0.302635303 */, 19 },
- /* 7951 */ { MAD_F(0x04d7cd56) /* 0.302686060 */, 19 },
-
- /* 7952 */ { MAD_F(0x04d80290) /* 0.302736820 */, 19 },
- /* 7953 */ { MAD_F(0x04d837ca) /* 0.302787581 */, 19 },
- /* 7954 */ { MAD_F(0x04d86d05) /* 0.302838345 */, 19 },
- /* 7955 */ { MAD_F(0x04d8a240) /* 0.302889111 */, 19 },
- /* 7956 */ { MAD_F(0x04d8d77c) /* 0.302939879 */, 19 },
- /* 7957 */ { MAD_F(0x04d90cb9) /* 0.302990650 */, 19 },
- /* 7958 */ { MAD_F(0x04d941f6) /* 0.303041422 */, 19 },
- /* 7959 */ { MAD_F(0x04d97734) /* 0.303092197 */, 19 },
- /* 7960 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 19 },
- /* 7961 */ { MAD_F(0x04d9e1b1) /* 0.303193752 */, 19 },
- /* 7962 */ { MAD_F(0x04da16f0) /* 0.303244533 */, 19 },
- /* 7963 */ { MAD_F(0x04da4c30) /* 0.303295316 */, 19 },
- /* 7964 */ { MAD_F(0x04da8171) /* 0.303346101 */, 19 },
- /* 7965 */ { MAD_F(0x04dab6b2) /* 0.303396889 */, 19 },
- /* 7966 */ { MAD_F(0x04daebf4) /* 0.303447678 */, 19 },
- /* 7967 */ { MAD_F(0x04db2136) /* 0.303498469 */, 19 },
-
- /* 7968 */ { MAD_F(0x04db5679) /* 0.303549263 */, 19 },
- /* 7969 */ { MAD_F(0x04db8bbc) /* 0.303600059 */, 19 },
- /* 7970 */ { MAD_F(0x04dbc100) /* 0.303650857 */, 19 },
- /* 7971 */ { MAD_F(0x04dbf644) /* 0.303701657 */, 19 },
- /* 7972 */ { MAD_F(0x04dc2b8a) /* 0.303752459 */, 19 },
- /* 7973 */ { MAD_F(0x04dc60cf) /* 0.303803263 */, 19 },
- /* 7974 */ { MAD_F(0x04dc9616) /* 0.303854070 */, 19 },
- /* 7975 */ { MAD_F(0x04dccb5c) /* 0.303904878 */, 19 },
- /* 7976 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 19 },
- /* 7977 */ { MAD_F(0x04dd35ec) /* 0.304006502 */, 19 },
- /* 7978 */ { MAD_F(0x04dd6b34) /* 0.304057317 */, 19 },
- /* 7979 */ { MAD_F(0x04dda07d) /* 0.304108134 */, 19 },
- /* 7980 */ { MAD_F(0x04ddd5c7) /* 0.304158953 */, 19 },
- /* 7981 */ { MAD_F(0x04de0b11) /* 0.304209774 */, 19 },
- /* 7982 */ { MAD_F(0x04de405c) /* 0.304260597 */, 19 },
- /* 7983 */ { MAD_F(0x04de75a7) /* 0.304311423 */, 19 },
-
- /* 7984 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 19 },
- /* 7985 */ { MAD_F(0x04dee040) /* 0.304413080 */, 19 },
- /* 7986 */ { MAD_F(0x04df158d) /* 0.304463912 */, 19 },
- /* 7987 */ { MAD_F(0x04df4adb) /* 0.304514746 */, 19 },
- /* 7988 */ { MAD_F(0x04df8029) /* 0.304565582 */, 19 },
- /* 7989 */ { MAD_F(0x04dfb578) /* 0.304616421 */, 19 },
- /* 7990 */ { MAD_F(0x04dfeac7) /* 0.304667261 */, 19 },
- /* 7991 */ { MAD_F(0x04e02017) /* 0.304718103 */, 19 },
- /* 7992 */ { MAD_F(0x04e05567) /* 0.304768948 */, 19 },
- /* 7993 */ { MAD_F(0x04e08ab8) /* 0.304819795 */, 19 },
- /* 7994 */ { MAD_F(0x04e0c00a) /* 0.304870644 */, 19 },
- /* 7995 */ { MAD_F(0x04e0f55c) /* 0.304921495 */, 19 },
- /* 7996 */ { MAD_F(0x04e12aaf) /* 0.304972348 */, 19 },
- /* 7997 */ { MAD_F(0x04e16002) /* 0.305023203 */, 19 },
- /* 7998 */ { MAD_F(0x04e19556) /* 0.305074060 */, 19 },
- /* 7999 */ { MAD_F(0x04e1caab) /* 0.305124920 */, 19 },
-
- /* 8000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 19 },
- /* 8001 */ { MAD_F(0x04e23555) /* 0.305226645 */, 19 },
- /* 8002 */ { MAD_F(0x04e26aac) /* 0.305277511 */, 19 },
- /* 8003 */ { MAD_F(0x04e2a002) /* 0.305328379 */, 19 },
- /* 8004 */ { MAD_F(0x04e2d55a) /* 0.305379249 */, 19 },
- /* 8005 */ { MAD_F(0x04e30ab2) /* 0.305430121 */, 19 },
- /* 8006 */ { MAD_F(0x04e3400a) /* 0.305480995 */, 19 },
- /* 8007 */ { MAD_F(0x04e37563) /* 0.305531872 */, 19 },
- /* 8008 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 19 },
- /* 8009 */ { MAD_F(0x04e3e017) /* 0.305633631 */, 19 },
- /* 8010 */ { MAD_F(0x04e41572) /* 0.305684513 */, 19 },
- /* 8011 */ { MAD_F(0x04e44acd) /* 0.305735398 */, 19 },
- /* 8012 */ { MAD_F(0x04e48029) /* 0.305786285 */, 19 },
- /* 8013 */ { MAD_F(0x04e4b585) /* 0.305837174 */, 19 },
- /* 8014 */ { MAD_F(0x04e4eae2) /* 0.305888066 */, 19 },
- /* 8015 */ { MAD_F(0x04e52040) /* 0.305938959 */, 19 },
-
- /* 8016 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 19 },
- /* 8017 */ { MAD_F(0x04e58afd) /* 0.306040752 */, 19 },
- /* 8018 */ { MAD_F(0x04e5c05c) /* 0.306091652 */, 19 },
- /* 8019 */ { MAD_F(0x04e5f5bc) /* 0.306142554 */, 19 },
- /* 8020 */ { MAD_F(0x04e62b1c) /* 0.306193457 */, 19 },
- /* 8021 */ { MAD_F(0x04e6607d) /* 0.306244364 */, 19 },
- /* 8022 */ { MAD_F(0x04e695df) /* 0.306295272 */, 19 },
- /* 8023 */ { MAD_F(0x04e6cb41) /* 0.306346182 */, 19 },
- /* 8024 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 19 },
- /* 8025 */ { MAD_F(0x04e73607) /* 0.306448009 */, 19 },
- /* 8026 */ { MAD_F(0x04e76b6b) /* 0.306498925 */, 19 },
- /* 8027 */ { MAD_F(0x04e7a0cf) /* 0.306549844 */, 19 },
- /* 8028 */ { MAD_F(0x04e7d634) /* 0.306600765 */, 19 },
- /* 8029 */ { MAD_F(0x04e80b99) /* 0.306651688 */, 19 },
- /* 8030 */ { MAD_F(0x04e84100) /* 0.306702613 */, 19 },
- /* 8031 */ { MAD_F(0x04e87666) /* 0.306753540 */, 19 },
-
- /* 8032 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 19 },
- /* 8033 */ { MAD_F(0x04e8e135) /* 0.306855401 */, 19 },
- /* 8034 */ { MAD_F(0x04e9169e) /* 0.306906334 */, 19 },
- /* 8035 */ { MAD_F(0x04e94c07) /* 0.306957270 */, 19 },
- /* 8036 */ { MAD_F(0x04e98170) /* 0.307008208 */, 19 },
- /* 8037 */ { MAD_F(0x04e9b6da) /* 0.307059148 */, 19 },
- /* 8038 */ { MAD_F(0x04e9ec45) /* 0.307110090 */, 19 },
- /* 8039 */ { MAD_F(0x04ea21b0) /* 0.307161034 */, 19 },
- /* 8040 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 19 },
- /* 8041 */ { MAD_F(0x04ea8c88) /* 0.307262928 */, 19 },
- /* 8042 */ { MAD_F(0x04eac1f5) /* 0.307313879 */, 19 },
- /* 8043 */ { MAD_F(0x04eaf762) /* 0.307364831 */, 19 },
- /* 8044 */ { MAD_F(0x04eb2cd0) /* 0.307415786 */, 19 },
- /* 8045 */ { MAD_F(0x04eb623f) /* 0.307466743 */, 19 },
- /* 8046 */ { MAD_F(0x04eb97ae) /* 0.307517702 */, 19 },
- /* 8047 */ { MAD_F(0x04ebcd1e) /* 0.307568663 */, 19 },
-
- /* 8048 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 19 },
- /* 8049 */ { MAD_F(0x04ec37ff) /* 0.307670591 */, 19 },
- /* 8050 */ { MAD_F(0x04ec6d71) /* 0.307721558 */, 19 },
- /* 8051 */ { MAD_F(0x04eca2e3) /* 0.307772528 */, 19 },
- /* 8052 */ { MAD_F(0x04ecd855) /* 0.307823499 */, 19 },
- /* 8053 */ { MAD_F(0x04ed0dc8) /* 0.307874473 */, 19 },
- /* 8054 */ { MAD_F(0x04ed433c) /* 0.307925449 */, 19 },
- /* 8055 */ { MAD_F(0x04ed78b0) /* 0.307976426 */, 19 },
- /* 8056 */ { MAD_F(0x04edae25) /* 0.308027406 */, 19 },
- /* 8057 */ { MAD_F(0x04ede39a) /* 0.308078389 */, 19 },
- /* 8058 */ { MAD_F(0x04ee1910) /* 0.308129373 */, 19 },
- /* 8059 */ { MAD_F(0x04ee4e87) /* 0.308180359 */, 19 },
- /* 8060 */ { MAD_F(0x04ee83fe) /* 0.308231347 */, 19 },
- /* 8061 */ { MAD_F(0x04eeb976) /* 0.308282338 */, 19 },
- /* 8062 */ { MAD_F(0x04eeeeee) /* 0.308333331 */, 19 },
- /* 8063 */ { MAD_F(0x04ef2467) /* 0.308384325 */, 19 },
-
- /* 8064 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 19 },
- /* 8065 */ { MAD_F(0x04ef8f5a) /* 0.308486321 */, 19 },
- /* 8066 */ { MAD_F(0x04efc4d5) /* 0.308537322 */, 19 },
- /* 8067 */ { MAD_F(0x04effa50) /* 0.308588325 */, 19 },
- /* 8068 */ { MAD_F(0x04f02fcb) /* 0.308639331 */, 19 },
- /* 8069 */ { MAD_F(0x04f06547) /* 0.308690338 */, 19 },
- /* 8070 */ { MAD_F(0x04f09ac4) /* 0.308741348 */, 19 },
- /* 8071 */ { MAD_F(0x04f0d041) /* 0.308792359 */, 19 },
- /* 8072 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 19 },
- /* 8073 */ { MAD_F(0x04f13b3e) /* 0.308894389 */, 19 },
- /* 8074 */ { MAD_F(0x04f170bd) /* 0.308945407 */, 19 },
- /* 8075 */ { MAD_F(0x04f1a63c) /* 0.308996427 */, 19 },
- /* 8076 */ { MAD_F(0x04f1dbbd) /* 0.309047449 */, 19 },
- /* 8077 */ { MAD_F(0x04f2113d) /* 0.309098473 */, 19 },
- /* 8078 */ { MAD_F(0x04f246bf) /* 0.309149499 */, 19 },
- /* 8079 */ { MAD_F(0x04f27c40) /* 0.309200528 */, 19 },
-
- /* 8080 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 19 },
- /* 8081 */ { MAD_F(0x04f2e746) /* 0.309302591 */, 19 },
- /* 8082 */ { MAD_F(0x04f31cc9) /* 0.309353626 */, 19 },
- /* 8083 */ { MAD_F(0x04f3524d) /* 0.309404663 */, 19 },
- /* 8084 */ { MAD_F(0x04f387d2) /* 0.309455702 */, 19 },
- /* 8085 */ { MAD_F(0x04f3bd57) /* 0.309506743 */, 19 },
- /* 8086 */ { MAD_F(0x04f3f2dd) /* 0.309557786 */, 19 },
- /* 8087 */ { MAD_F(0x04f42864) /* 0.309608831 */, 19 },
- /* 8088 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 19 },
- /* 8089 */ { MAD_F(0x04f49372) /* 0.309710928 */, 19 },
- /* 8090 */ { MAD_F(0x04f4c8fa) /* 0.309761980 */, 19 },
- /* 8091 */ { MAD_F(0x04f4fe83) /* 0.309813033 */, 19 },
- /* 8092 */ { MAD_F(0x04f5340c) /* 0.309864089 */, 19 },
- /* 8093 */ { MAD_F(0x04f56996) /* 0.309915147 */, 19 },
- /* 8094 */ { MAD_F(0x04f59f20) /* 0.309966207 */, 19 },
- /* 8095 */ { MAD_F(0x04f5d4ab) /* 0.310017269 */, 19 },
-
- /* 8096 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 19 },
- /* 8097 */ { MAD_F(0x04f63fc2) /* 0.310119400 */, 19 },
- /* 8098 */ { MAD_F(0x04f6754f) /* 0.310170468 */, 19 },
- /* 8099 */ { MAD_F(0x04f6aadc) /* 0.310221539 */, 19 },
- /* 8100 */ { MAD_F(0x04f6e06a) /* 0.310272611 */, 19 },
- /* 8101 */ { MAD_F(0x04f715f8) /* 0.310323686 */, 19 },
- /* 8102 */ { MAD_F(0x04f74b87) /* 0.310374763 */, 19 },
- /* 8103 */ { MAD_F(0x04f78116) /* 0.310425842 */, 19 },
- /* 8104 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 19 },
- /* 8105 */ { MAD_F(0x04f7ec37) /* 0.310528006 */, 19 },
- /* 8106 */ { MAD_F(0x04f821c8) /* 0.310579091 */, 19 },
- /* 8107 */ { MAD_F(0x04f85759) /* 0.310630179 */, 19 },
- /* 8108 */ { MAD_F(0x04f88cec) /* 0.310681268 */, 19 },
- /* 8109 */ { MAD_F(0x04f8c27e) /* 0.310732360 */, 19 },
- /* 8110 */ { MAD_F(0x04f8f812) /* 0.310783453 */, 19 },
- /* 8111 */ { MAD_F(0x04f92da6) /* 0.310834549 */, 19 },
-
- /* 8112 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 19 },
- /* 8113 */ { MAD_F(0x04f998cf) /* 0.310936747 */, 19 },
- /* 8114 */ { MAD_F(0x04f9ce65) /* 0.310987849 */, 19 },
- /* 8115 */ { MAD_F(0x04fa03fb) /* 0.311038953 */, 19 },
- /* 8116 */ { MAD_F(0x04fa3992) /* 0.311090059 */, 19 },
- /* 8117 */ { MAD_F(0x04fa6f29) /* 0.311141168 */, 19 },
- /* 8118 */ { MAD_F(0x04faa4c1) /* 0.311192278 */, 19 },
- /* 8119 */ { MAD_F(0x04fada59) /* 0.311243390 */, 19 },
- /* 8120 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 19 },
- /* 8121 */ { MAD_F(0x04fb458c) /* 0.311345622 */, 19 },
- /* 8122 */ { MAD_F(0x04fb7b26) /* 0.311396741 */, 19 },
- /* 8123 */ { MAD_F(0x04fbb0c1) /* 0.311447862 */, 19 },
- /* 8124 */ { MAD_F(0x04fbe65c) /* 0.311498985 */, 19 },
- /* 8125 */ { MAD_F(0x04fc1bf8) /* 0.311550110 */, 19 },
- /* 8126 */ { MAD_F(0x04fc5194) /* 0.311601237 */, 19 },
- /* 8127 */ { MAD_F(0x04fc8731) /* 0.311652366 */, 19 },
-
- /* 8128 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 19 },
- /* 8129 */ { MAD_F(0x04fcf26c) /* 0.311754631 */, 19 },
- /* 8130 */ { MAD_F(0x04fd280b) /* 0.311805767 */, 19 },
- /* 8131 */ { MAD_F(0x04fd5daa) /* 0.311856905 */, 19 },
- /* 8132 */ { MAD_F(0x04fd934a) /* 0.311908044 */, 19 },
- /* 8133 */ { MAD_F(0x04fdc8ea) /* 0.311959186 */, 19 },
- /* 8134 */ { MAD_F(0x04fdfe8b) /* 0.312010330 */, 19 },
- /* 8135 */ { MAD_F(0x04fe342c) /* 0.312061476 */, 19 },
- /* 8136 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 19 },
- /* 8137 */ { MAD_F(0x04fe9f71) /* 0.312163775 */, 19 },
- /* 8138 */ { MAD_F(0x04fed514) /* 0.312214927 */, 19 },
- /* 8139 */ { MAD_F(0x04ff0ab8) /* 0.312266082 */, 19 },
- /* 8140 */ { MAD_F(0x04ff405c) /* 0.312317238 */, 19 },
- /* 8141 */ { MAD_F(0x04ff7601) /* 0.312368397 */, 19 },
- /* 8142 */ { MAD_F(0x04ffaba6) /* 0.312419558 */, 19 },
- /* 8143 */ { MAD_F(0x04ffe14c) /* 0.312470720 */, 19 },
-
- /* 8144 */ { MAD_F(0x050016f3) /* 0.312521885 */, 19 },
- /* 8145 */ { MAD_F(0x05004c9a) /* 0.312573052 */, 19 },
- /* 8146 */ { MAD_F(0x05008241) /* 0.312624222 */, 19 },
- /* 8147 */ { MAD_F(0x0500b7e9) /* 0.312675393 */, 19 },
- /* 8148 */ { MAD_F(0x0500ed92) /* 0.312726566 */, 19 },
- /* 8149 */ { MAD_F(0x0501233b) /* 0.312777742 */, 19 },
- /* 8150 */ { MAD_F(0x050158e5) /* 0.312828919 */, 19 },
- /* 8151 */ { MAD_F(0x05018e90) /* 0.312880099 */, 19 },
- /* 8152 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 19 },
- /* 8153 */ { MAD_F(0x0501f9e6) /* 0.312982464 */, 19 },
- /* 8154 */ { MAD_F(0x05022f92) /* 0.313033650 */, 19 },
- /* 8155 */ { MAD_F(0x0502653f) /* 0.313084838 */, 19 },
- /* 8156 */ { MAD_F(0x05029aec) /* 0.313136028 */, 19 },
- /* 8157 */ { MAD_F(0x0502d09a) /* 0.313187220 */, 19 },
- /* 8158 */ { MAD_F(0x05030648) /* 0.313238414 */, 19 },
- /* 8159 */ { MAD_F(0x05033bf7) /* 0.313289611 */, 19 },
-
- /* 8160 */ { MAD_F(0x050371a7) /* 0.313340809 */, 19 },
- /* 8161 */ { MAD_F(0x0503a757) /* 0.313392010 */, 19 },
- /* 8162 */ { MAD_F(0x0503dd07) /* 0.313443212 */, 19 },
- /* 8163 */ { MAD_F(0x050412b9) /* 0.313494417 */, 19 },
- /* 8164 */ { MAD_F(0x0504486a) /* 0.313545624 */, 19 },
- /* 8165 */ { MAD_F(0x05047e1d) /* 0.313596833 */, 19 },
- /* 8166 */ { MAD_F(0x0504b3cf) /* 0.313648044 */, 19 },
- /* 8167 */ { MAD_F(0x0504e983) /* 0.313699257 */, 19 },
- /* 8168 */ { MAD_F(0x05051f37) /* 0.313750472 */, 19 },
- /* 8169 */ { MAD_F(0x050554eb) /* 0.313801689 */, 19 },
- /* 8170 */ { MAD_F(0x05058aa0) /* 0.313852909 */, 19 },
- /* 8171 */ { MAD_F(0x0505c056) /* 0.313904130 */, 19 },
- /* 8172 */ { MAD_F(0x0505f60c) /* 0.313955354 */, 19 },
- /* 8173 */ { MAD_F(0x05062bc3) /* 0.314006579 */, 19 },
- /* 8174 */ { MAD_F(0x0506617a) /* 0.314057807 */, 19 },
- /* 8175 */ { MAD_F(0x05069732) /* 0.314109037 */, 19 },
-
- /* 8176 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 19 },
- /* 8177 */ { MAD_F(0x050702a4) /* 0.314211502 */, 19 },
- /* 8178 */ { MAD_F(0x0507385d) /* 0.314262739 */, 19 },
- /* 8179 */ { MAD_F(0x05076e17) /* 0.314313977 */, 19 },
- /* 8180 */ { MAD_F(0x0507a3d2) /* 0.314365217 */, 19 },
- /* 8181 */ { MAD_F(0x0507d98d) /* 0.314416459 */, 19 },
- /* 8182 */ { MAD_F(0x05080f49) /* 0.314467704 */, 19 },
- /* 8183 */ { MAD_F(0x05084506) /* 0.314518950 */, 19 },
- /* 8184 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 19 },
- /* 8185 */ { MAD_F(0x0508b080) /* 0.314621449 */, 19 },
- /* 8186 */ { MAD_F(0x0508e63e) /* 0.314672702 */, 19 },
- /* 8187 */ { MAD_F(0x05091bfd) /* 0.314723957 */, 19 },
- /* 8188 */ { MAD_F(0x050951bc) /* 0.314775214 */, 19 },
- /* 8189 */ { MAD_F(0x0509877c) /* 0.314826473 */, 19 },
- /* 8190 */ { MAD_F(0x0509bd3c) /* 0.314877734 */, 19 },
- /* 8191 */ { MAD_F(0x0509f2fd) /* 0.314928997 */, 19 },
-
- /* 8192 */ { MAD_F(0x050a28be) /* 0.314980262 */, 19 },
- /* 8193 */ { MAD_F(0x050a5e80) /* 0.315031530 */, 19 },
- /* 8194 */ { MAD_F(0x050a9443) /* 0.315082799 */, 19 },
- /* 8195 */ { MAD_F(0x050aca06) /* 0.315134071 */, 19 },
- /* 8196 */ { MAD_F(0x050affc9) /* 0.315185344 */, 19 },
- /* 8197 */ { MAD_F(0x050b358e) /* 0.315236620 */, 19 },
- /* 8198 */ { MAD_F(0x050b6b52) /* 0.315287898 */, 19 },
- /* 8199 */ { MAD_F(0x050ba118) /* 0.315339178 */, 19 },
- /* 8200 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 19 },
- /* 8201 */ { MAD_F(0x050c0ca4) /* 0.315441744 */, 19 },
- /* 8202 */ { MAD_F(0x050c426b) /* 0.315493030 */, 19 },
- /* 8203 */ { MAD_F(0x050c7833) /* 0.315544318 */, 19 },
- /* 8204 */ { MAD_F(0x050cadfb) /* 0.315595608 */, 19 },
- /* 8205 */ { MAD_F(0x050ce3c4) /* 0.315646901 */, 19 },
- /* 8206 */ { MAD_F(0x050d198d) /* 0.315698195 */, 19 }
diff --git a/libmad/src/sf_table.dat b/libmad/src/sf_table.dat
deleted file mode 100644
index db1484a..0000000
--- a/libmad/src/sf_table.dat
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: sf_table.dat,v 1.7 2004/01/23 09:41:33 rob Exp $
- */
-
-/*
- * These are the scalefactor values for Layer I and Layer II.
- * The values are from Table B.1 of ISO/IEC 11172-3.
- *
- * There is some error introduced by the 32-bit fixed-point representation;
- * the amount of error is shown. For 16-bit PCM output, this shouldn't be
- * too much of a problem.
- *
- * Strictly speaking, Table B.1 has only 63 entries (0-62), thus a strict
- * interpretation of ISO/IEC 11172-3 would suggest that a scalefactor index of
- * 63 is invalid. However, for better compatibility with current practices, we
- * add a 64th entry.
- */
-
- MAD_F(0x20000000), /* 2.000000000000 => 2.000000000000, e 0.000000000000 */
- MAD_F(0x1965fea5), /* 1.587401051968 => 1.587401051074, e 0.000000000894 */
- MAD_F(0x1428a2fa), /* 1.259921049895 => 1.259921051562, e -0.000000001667 */
- MAD_F(0x10000000), /* 1.000000000000 => 1.000000000000, e 0.000000000000 */
- MAD_F(0x0cb2ff53), /* 0.793700525984 => 0.793700527400, e -0.000000001416 */
- MAD_F(0x0a14517d), /* 0.629960524947 => 0.629960525781, e -0.000000000833 */
- MAD_F(0x08000000), /* 0.500000000000 => 0.500000000000, e 0.000000000000 */
- MAD_F(0x06597fa9), /* 0.396850262992 => 0.396850261837, e 0.000000001155 */
-
- MAD_F(0x050a28be), /* 0.314980262474 => 0.314980261028, e 0.000000001446 */
- MAD_F(0x04000000), /* 0.250000000000 => 0.250000000000, e 0.000000000000 */
- MAD_F(0x032cbfd5), /* 0.198425131496 => 0.198425132781, e -0.000000001285 */
- MAD_F(0x0285145f), /* 0.157490131237 => 0.157490130514, e 0.000000000723 */
- MAD_F(0x02000000), /* 0.125000000000 => 0.125000000000, e 0.000000000000 */
- MAD_F(0x01965fea), /* 0.099212565748 => 0.099212564528, e 0.000000001220 */
- MAD_F(0x01428a30), /* 0.078745065618 => 0.078745067120, e -0.000000001501 */
- MAD_F(0x01000000), /* 0.062500000000 => 0.062500000000, e 0.000000000000 */
-
- MAD_F(0x00cb2ff5), /* 0.049606282874 => 0.049606282264, e 0.000000000610 */
- MAD_F(0x00a14518), /* 0.039372532809 => 0.039372533560, e -0.000000000751 */
- MAD_F(0x00800000), /* 0.031250000000 => 0.031250000000, e 0.000000000000 */
- MAD_F(0x006597fb), /* 0.024803141437 => 0.024803142995, e -0.000000001558 */
- MAD_F(0x0050a28c), /* 0.019686266405 => 0.019686266780, e -0.000000000375 */
- MAD_F(0x00400000), /* 0.015625000000 => 0.015625000000, e 0.000000000000 */
- MAD_F(0x0032cbfd), /* 0.012401570719 => 0.012401569635, e 0.000000001084 */
- MAD_F(0x00285146), /* 0.009843133202 => 0.009843133390, e -0.000000000188 */
-
- MAD_F(0x00200000), /* 0.007812500000 => 0.007812500000, e 0.000000000000 */
- MAD_F(0x001965ff), /* 0.006200785359 => 0.006200786680, e -0.000000001321 */
- MAD_F(0x001428a3), /* 0.004921566601 => 0.004921566695, e -0.000000000094 */
- MAD_F(0x00100000), /* 0.003906250000 => 0.003906250000, e 0.000000000000 */
- MAD_F(0x000cb2ff), /* 0.003100392680 => 0.003100391477, e 0.000000001202 */
- MAD_F(0x000a1451), /* 0.002460783301 => 0.002460781485, e 0.000000001816 */
- MAD_F(0x00080000), /* 0.001953125000 => 0.001953125000, e 0.000000000000 */
- MAD_F(0x00065980), /* 0.001550196340 => 0.001550197601, e -0.000000001262 */
-
- MAD_F(0x00050a29), /* 0.001230391650 => 0.001230392605, e -0.000000000955 */
- MAD_F(0x00040000), /* 0.000976562500 => 0.000976562500, e 0.000000000000 */
- MAD_F(0x00032cc0), /* 0.000775098170 => 0.000775098801, e -0.000000000631 */
- MAD_F(0x00028514), /* 0.000615195825 => 0.000615194440, e 0.000000001385 */
- MAD_F(0x00020000), /* 0.000488281250 => 0.000488281250, e 0.000000000000 */
- MAD_F(0x00019660), /* 0.000387549085 => 0.000387549400, e -0.000000000315 */
- MAD_F(0x0001428a), /* 0.000307597913 => 0.000307597220, e 0.000000000693 */
- MAD_F(0x00010000), /* 0.000244140625 => 0.000244140625, e 0.000000000000 */
-
- MAD_F(0x0000cb30), /* 0.000193774542 => 0.000193774700, e -0.000000000158 */
- MAD_F(0x0000a145), /* 0.000153798956 => 0.000153798610, e 0.000000000346 */
- MAD_F(0x00008000), /* 0.000122070313 => 0.000122070313, e 0.000000000000 */
- MAD_F(0x00006598), /* 0.000096887271 => 0.000096887350, e -0.000000000079 */
- MAD_F(0x000050a3), /* 0.000076899478 => 0.000076901168, e -0.000000001689 */
- MAD_F(0x00004000), /* 0.000061035156 => 0.000061035156, e 0.000000000000 */
- MAD_F(0x000032cc), /* 0.000048443636 => 0.000048443675, e -0.000000000039 */
- MAD_F(0x00002851), /* 0.000038449739 => 0.000038448721, e 0.000000001018 */
-
- MAD_F(0x00002000), /* 0.000030517578 => 0.000030517578, e 0.000000000000 */
- MAD_F(0x00001966), /* 0.000024221818 => 0.000024221838, e -0.000000000020 */
- MAD_F(0x00001429), /* 0.000019224870 => 0.000019226223, e -0.000000001354 */
- MAD_F(0x00001000), /* 0.000015258789 => 0.000015258789, e -0.000000000000 */
- MAD_F(0x00000cb3), /* 0.000012110909 => 0.000012110919, e -0.000000000010 */
- MAD_F(0x00000a14), /* 0.000009612435 => 0.000009611249, e 0.000000001186 */
- MAD_F(0x00000800), /* 0.000007629395 => 0.000007629395, e -0.000000000000 */
- MAD_F(0x00000659), /* 0.000006055454 => 0.000006053597, e 0.000000001858 */
-
- MAD_F(0x0000050a), /* 0.000004806217 => 0.000004805624, e 0.000000000593 */
- MAD_F(0x00000400), /* 0.000003814697 => 0.000003814697, e 0.000000000000 */
- MAD_F(0x0000032d), /* 0.000003027727 => 0.000003028661, e -0.000000000934 */
- MAD_F(0x00000285), /* 0.000002403109 => 0.000002402812, e 0.000000000296 */
- MAD_F(0x00000200), /* 0.000001907349 => 0.000001907349, e -0.000000000000 */
- MAD_F(0x00000196), /* 0.000001513864 => 0.000001512468, e 0.000000001396 */
- MAD_F(0x00000143), /* 0.000001201554 => 0.000001203269, e -0.000000001714 */
- MAD_F(0x00000000) /* this compatibility entry is not part of Table B.1 */
diff --git a/libmad/src/stream.c b/libmad/src/stream.c
deleted file mode 100644
index 8bb4d6a..0000000
--- a/libmad/src/stream.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: stream.c,v 1.12 2004/02/05 09:02:39 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-
-# include "bit.h"
-# include "stream.h"
-
-/*
- * NAME: stream->init()
- * DESCRIPTION: initialize stream struct
- */
-void mad_stream_init(struct mad_stream *stream)
-{
- stream->buffer = 0;
- stream->bufend = 0;
- stream->skiplen = 0;
-
- stream->sync = 0;
- stream->freerate = 0;
-
- stream->this_frame = 0;
- stream->next_frame = 0;
- mad_bit_init(&stream->ptr, 0);
-
- mad_bit_init(&stream->anc_ptr, 0);
- stream->anc_bitlen = 0;
-
- stream->main_data = 0;
- stream->md_len = 0;
-
- stream->options = 0;
- stream->error = MAD_ERROR_NONE;
-}
-
-/*
- * NAME: stream->finish()
- * DESCRIPTION: deallocate any dynamic memory associated with stream
- */
-void mad_stream_finish(struct mad_stream *stream)
-{
- if (stream->main_data) {
- free(stream->main_data);
- stream->main_data = 0;
- }
-
- mad_bit_finish(&stream->anc_ptr);
- mad_bit_finish(&stream->ptr);
-}
-
-/*
- * NAME: stream->buffer()
- * DESCRIPTION: set stream buffer pointers
- */
-void mad_stream_buffer(struct mad_stream *stream,
- unsigned char const *buffer, unsigned long length)
-{
- stream->buffer = buffer;
- stream->bufend = buffer + length;
-
- stream->this_frame = buffer;
- stream->next_frame = buffer;
-
- stream->sync = 1;
-
- mad_bit_init(&stream->ptr, buffer);
-}
-
-/*
- * NAME: stream->skip()
- * DESCRIPTION: arrange to skip bytes before the next frame
- */
-void mad_stream_skip(struct mad_stream *stream, unsigned long length)
-{
- stream->skiplen += length;
-}
-
-/*
- * NAME: stream->sync()
- * DESCRIPTION: locate the next stream sync word
- */
-int mad_stream_sync(struct mad_stream *stream)
-{
- register unsigned char const *ptr, *end;
-
- ptr = mad_bit_nextbyte(&stream->ptr);
- end = stream->bufend;
-
- while (ptr < end - 1 &&
- !(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0))
- ++ptr;
-
- if (end - ptr < MAD_BUFFER_GUARD)
- return -1;
-
- mad_bit_init(&stream->ptr, ptr);
-
- return 0;
-}
-
-/*
- * NAME: stream->errorstr()
- * DESCRIPTION: return a string description of the current error condition
- */
-char const *mad_stream_errorstr(struct mad_stream const *stream)
-{
- switch (stream->error) {
- case MAD_ERROR_NONE: return "no error";
-
- case MAD_ERROR_BUFLEN: return "input buffer too small (or EOF)";
- case MAD_ERROR_BUFPTR: return "invalid (null) buffer pointer";
-
- case MAD_ERROR_NOMEM: return "not enough memory";
-
- case MAD_ERROR_LOSTSYNC: return "lost synchronization";
- case MAD_ERROR_BADLAYER: return "reserved header layer value";
- case MAD_ERROR_BADBITRATE: return "forbidden bitrate value";
- case MAD_ERROR_BADSAMPLERATE: return "reserved sample frequency value";
- case MAD_ERROR_BADEMPHASIS: return "reserved emphasis value";
-
- case MAD_ERROR_BADCRC: return "CRC check failed";
- case MAD_ERROR_BADBITALLOC: return "forbidden bit allocation value";
- case MAD_ERROR_BADSCALEFACTOR: return "bad scalefactor index";
- case MAD_ERROR_BADMODE: return "bad bitrate/mode combination";
- case MAD_ERROR_BADFRAMELEN: return "bad frame length";
- case MAD_ERROR_BADBIGVALUES: return "bad big_values count";
- case MAD_ERROR_BADBLOCKTYPE: return "reserved block_type";
- case MAD_ERROR_BADSCFSI: return "bad scalefactor selection info";
- case MAD_ERROR_BADDATAPTR: return "bad main_data_begin pointer";
- case MAD_ERROR_BADPART3LEN: return "bad audio data length";
- case MAD_ERROR_BADHUFFTABLE: return "bad Huffman table select";
- case MAD_ERROR_BADHUFFDATA: return "Huffman data overrun";
- case MAD_ERROR_BADSTEREO: return "incompatible block_type for JS";
- }
-
- return 0;
-}
diff --git a/libmad/src/stream.h b/libmad/src/stream.h
deleted file mode 100644
index 8bff8b4..0000000
--- a/libmad/src/stream.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: stream.h,v 1.20 2004/02/05 09:02:39 rob Exp $
- */
-
-# ifndef LIBMAD_STREAM_H
-# define LIBMAD_STREAM_H
-
-# include "bit.h"
-
-# define MAD_BUFFER_GUARD 8
-# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD)
-
-enum mad_error {
- MAD_ERROR_NONE = 0x0000, /* no error */
-
- MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */
- MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */
-
- MAD_ERROR_NOMEM = 0x0031, /* not enough memory */
-
- MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */
- MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */
- MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */
- MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */
- MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */
-
- MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */
- MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */
- MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */
- MAD_ERROR_BADMODE = 0x0222, /* bad bitrate/mode combination */
- MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */
- MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */
- MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */
- MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */
- MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */
- MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */
- MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */
- MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */
- MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */
-};
-
-# define MAD_RECOVERABLE(error) ((error) & 0xff00)
-
-struct mad_stream {
- unsigned char const *buffer; /* input bitstream buffer */
- unsigned char const *bufend; /* end of buffer */
- unsigned long skiplen; /* bytes to skip before next frame */
-
- int sync; /* stream sync found */
- unsigned long freerate; /* free bitrate (fixed) */
-
- unsigned char const *this_frame; /* start of current frame */
- unsigned char const *next_frame; /* start of next frame */
- struct mad_bitptr ptr; /* current processing bit pointer */
-
- struct mad_bitptr anc_ptr; /* ancillary bits pointer */
- unsigned int anc_bitlen; /* number of ancillary bits */
-
- unsigned char (*main_data)[MAD_BUFFER_MDLEN];
- /* Layer III main_data() */
- unsigned int md_len; /* bytes in main_data */
-
- int options; /* decoding options (see below) */
- enum mad_error error; /* error code (see above) */
-};
-
-enum {
- MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */
- MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */
-# if 0 /* not yet implemented */
- MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */
- MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */
- MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */
-# endif
-};
-
-void mad_stream_init(struct mad_stream *);
-void mad_stream_finish(struct mad_stream *);
-
-# define mad_stream_options(stream, opts) \
- ((void) ((stream)->options = (opts)))
-
-void mad_stream_buffer(struct mad_stream *,
- unsigned char const *, unsigned long);
-void mad_stream_skip(struct mad_stream *, unsigned long);
-
-int mad_stream_sync(struct mad_stream *);
-
-char const *mad_stream_errorstr(struct mad_stream const *);
-
-# endif
diff --git a/libmad/src/synth.c b/libmad/src/synth.c
deleted file mode 100644
index 0ccb106..0000000
--- a/libmad/src/synth.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: synth.c,v 1.25 2004/01/23 09:41:33 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include "fixed.h"
-# include "frame.h"
-# include "synth.h"
-
-# ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4146)
-# endif
-
-/*
- * NAME: synth->init()
- * DESCRIPTION: initialize synth struct
- */
-void mad_synth_init(struct mad_synth *synth)
-{
- mad_synth_mute(synth);
-
- synth->phase = 0;
-
- synth->pcm.samplerate = 0;
- synth->pcm.channels = 0;
- synth->pcm.length = 0;
-}
-
-/*
- * NAME: synth->mute()
- * DESCRIPTION: zero all polyphase filterbank values, resetting synthesis
- */
-void mad_synth_mute(struct mad_synth *synth)
-{
- unsigned int ch, s, v;
-
- for (ch = 0; ch < 2; ++ch) {
- for (s = 0; s < 16; ++s) {
- for (v = 0; v < 8; ++v) {
- synth->filter[ch][0][0][s][v] = synth->filter[ch][0][1][s][v] =
- synth->filter[ch][1][0][s][v] = synth->filter[ch][1][1][s][v] = 0;
- }
- }
- }
-}
-
-/*
- * An optional optimization called here the Subband Synthesis Optimization
- * (SSO) improves the performance of subband synthesis at the expense of
- * accuracy.
- *
- * The idea is to simplify 32x32->64-bit multiplication to 32x32->32 such
- * that extra scaling and rounding are not necessary. This often allows the
- * compiler to use faster 32-bit multiply-accumulate instructions instead of
- * explicit 64-bit multiply, shift, and add instructions.
- *
- * SSO works like this: a full 32x32->64-bit multiply of two mad_fixed_t
- * values requires the result to be right-shifted 28 bits to be properly
- * scaled to the same fixed-point format. Right shifts can be applied at any
- * time to either operand or to the result, so the optimization involves
- * careful placement of these shifts to minimize the loss of accuracy.
- *
- * First, a 14-bit shift is applied with rounding at compile-time to the D[]
- * table of coefficients for the subband synthesis window. This only loses 2
- * bits of accuracy because the lower 12 bits are always zero. A second
- * 12-bit shift occurs after the DCT calculation. This loses 12 bits of
- * accuracy. Finally, a third 2-bit shift occurs just before the sample is
- * saved in the PCM buffer. 14 + 12 + 2 == 28 bits.
- */
-
-/* FPM_DEFAULT without OPT_SSO will actually lose accuracy and performance */
-
-# if defined(FPM_DEFAULT) && !defined(OPT_SSO)
-# define OPT_SSO
-# endif
-
-/* second SSO shift, with rounding */
-
-# if defined(OPT_SSO)
-# define SHIFT(x) (((x) + (1L << 11)) >> 12)
-# else
-# define SHIFT(x) (x)
-# endif
-
-/* possible DCT speed optimization */
-
-# if defined(OPT_SPEED) && defined(MAD_F_MLX)
-# define OPT_DCTO
-# define MUL(x, y) \
- ({ mad_fixed64hi_t hi; \
- mad_fixed64lo_t lo; \
- MAD_F_MLX(hi, lo, (x), (y)); \
- hi << (32 - MAD_F_SCALEBITS - 3); \
- })
-# else
-# undef OPT_DCTO
-# define MUL(x, y) mad_f_mul((x), (y))
-# endif
-
-/*
- * NAME: dct32()
- * DESCRIPTION: perform fast in[32]->out[32] DCT
- */
-static
-void dct32(mad_fixed_t const in[32], unsigned int slot,
- mad_fixed_t lo[16][8], mad_fixed_t hi[16][8])
-{
- mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7;
- mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15;
- mad_fixed_t t16, t17, t18, t19, t20, t21, t22, t23;
- mad_fixed_t t24, t25, t26, t27, t28, t29, t30, t31;
- mad_fixed_t t32, t33, t34, t35, t36, t37, t38, t39;
- mad_fixed_t t40, t41, t42, t43, t44, t45, t46, t47;
- mad_fixed_t t48, t49, t50, t51, t52, t53, t54, t55;
- mad_fixed_t t56, t57, t58, t59, t60, t61, t62, t63;
- mad_fixed_t t64, t65, t66, t67, t68, t69, t70, t71;
- mad_fixed_t t72, t73, t74, t75, t76, t77, t78, t79;
- mad_fixed_t t80, t81, t82, t83, t84, t85, t86, t87;
- mad_fixed_t t88, t89, t90, t91, t92, t93, t94, t95;
- mad_fixed_t t96, t97, t98, t99, t100, t101, t102, t103;
- mad_fixed_t t104, t105, t106, t107, t108, t109, t110, t111;
- mad_fixed_t t112, t113, t114, t115, t116, t117, t118, t119;
- mad_fixed_t t120, t121, t122, t123, t124, t125, t126, t127;
- mad_fixed_t t128, t129, t130, t131, t132, t133, t134, t135;
- mad_fixed_t t136, t137, t138, t139, t140, t141, t142, t143;
- mad_fixed_t t144, t145, t146, t147, t148, t149, t150, t151;
- mad_fixed_t t152, t153, t154, t155, t156, t157, t158, t159;
- mad_fixed_t t160, t161, t162, t163, t164, t165, t166, t167;
- mad_fixed_t t168, t169, t170, t171, t172, t173, t174, t175;
- mad_fixed_t t176;
-
- /* costab[i] = cos(PI / (2 * 32) * i) */
-
-# if defined(OPT_DCTO)
-# define costab1 MAD_F(0x7fd8878e)
-# define costab2 MAD_F(0x7f62368f)
-# define costab3 MAD_F(0x7e9d55fc)
-# define costab4 MAD_F(0x7d8a5f40)
-# define costab5 MAD_F(0x7c29fbee)
-# define costab6 MAD_F(0x7a7d055b)
-# define costab7 MAD_F(0x78848414)
-# define costab8 MAD_F(0x7641af3d)
-# define costab9 MAD_F(0x73b5ebd1)
-# define costab10 MAD_F(0x70e2cbc6)
-# define costab11 MAD_F(0x6dca0d14)
-# define costab12 MAD_F(0x6a6d98a4)
-# define costab13 MAD_F(0x66cf8120)
-# define costab14 MAD_F(0x62f201ac)
-# define costab15 MAD_F(0x5ed77c8a)
-# define costab16 MAD_F(0x5a82799a)
-# define costab17 MAD_F(0x55f5a4d2)
-# define costab18 MAD_F(0x5133cc94)
-# define costab19 MAD_F(0x4c3fdff4)
-# define costab20 MAD_F(0x471cece7)
-# define costab21 MAD_F(0x41ce1e65)
-# define costab22 MAD_F(0x3c56ba70)
-# define costab23 MAD_F(0x36ba2014)
-# define costab24 MAD_F(0x30fbc54d)
-# define costab25 MAD_F(0x2b1f34eb)
-# define costab26 MAD_F(0x25280c5e)
-# define costab27 MAD_F(0x1f19f97b)
-# define costab28 MAD_F(0x18f8b83c)
-# define costab29 MAD_F(0x12c8106f)
-# define costab30 MAD_F(0x0c8bd35e)
-# define costab31 MAD_F(0x0647d97c)
-# else
-# define costab1 MAD_F(0x0ffb10f2) /* 0.998795456 */
-# define costab2 MAD_F(0x0fec46d2) /* 0.995184727 */
-# define costab3 MAD_F(0x0fd3aac0) /* 0.989176510 */
-# define costab4 MAD_F(0x0fb14be8) /* 0.980785280 */
-# define costab5 MAD_F(0x0f853f7e) /* 0.970031253 */
-# define costab6 MAD_F(0x0f4fa0ab) /* 0.956940336 */
-# define costab7 MAD_F(0x0f109082) /* 0.941544065 */
-# define costab8 MAD_F(0x0ec835e8) /* 0.923879533 */
-# define costab9 MAD_F(0x0e76bd7a) /* 0.903989293 */
-# define costab10 MAD_F(0x0e1c5979) /* 0.881921264 */
-# define costab11 MAD_F(0x0db941a3) /* 0.857728610 */
-# define costab12 MAD_F(0x0d4db315) /* 0.831469612 */
-# define costab13 MAD_F(0x0cd9f024) /* 0.803207531 */
-# define costab14 MAD_F(0x0c5e4036) /* 0.773010453 */
-# define costab15 MAD_F(0x0bdaef91) /* 0.740951125 */
-# define costab16 MAD_F(0x0b504f33) /* 0.707106781 */
-# define costab17 MAD_F(0x0abeb49a) /* 0.671558955 */
-# define costab18 MAD_F(0x0a267993) /* 0.634393284 */
-# define costab19 MAD_F(0x0987fbfe) /* 0.595699304 */
-# define costab20 MAD_F(0x08e39d9d) /* 0.555570233 */
-# define costab21 MAD_F(0x0839c3cd) /* 0.514102744 */
-# define costab22 MAD_F(0x078ad74e) /* 0.471396737 */
-# define costab23 MAD_F(0x06d74402) /* 0.427555093 */
-# define costab24 MAD_F(0x061f78aa) /* 0.382683432 */
-# define costab25 MAD_F(0x0563e69d) /* 0.336889853 */
-# define costab26 MAD_F(0x04a5018c) /* 0.290284677 */
-# define costab27 MAD_F(0x03e33f2f) /* 0.242980180 */
-# define costab28 MAD_F(0x031f1708) /* 0.195090322 */
-# define costab29 MAD_F(0x0259020e) /* 0.146730474 */
-# define costab30 MAD_F(0x01917a6c) /* 0.098017140 */
-# define costab31 MAD_F(0x00c8fb30) /* 0.049067674 */
-# endif
-
- t0 = in[0] + in[31]; t16 = MUL(in[0] - in[31], costab1);
- t1 = in[15] + in[16]; t17 = MUL(in[15] - in[16], costab31);
-
- t41 = t16 + t17;
- t59 = MUL(t16 - t17, costab2);
- t33 = t0 + t1;
- t50 = MUL(t0 - t1, costab2);
-
- t2 = in[7] + in[24]; t18 = MUL(in[7] - in[24], costab15);
- t3 = in[8] + in[23]; t19 = MUL(in[8] - in[23], costab17);
-
- t42 = t18 + t19;
- t60 = MUL(t18 - t19, costab30);
- t34 = t2 + t3;
- t51 = MUL(t2 - t3, costab30);
-
- t4 = in[3] + in[28]; t20 = MUL(in[3] - in[28], costab7);
- t5 = in[12] + in[19]; t21 = MUL(in[12] - in[19], costab25);
-
- t43 = t20 + t21;
- t61 = MUL(t20 - t21, costab14);
- t35 = t4 + t5;
- t52 = MUL(t4 - t5, costab14);
-
- t6 = in[4] + in[27]; t22 = MUL(in[4] - in[27], costab9);
- t7 = in[11] + in[20]; t23 = MUL(in[11] - in[20], costab23);
-
- t44 = t22 + t23;
- t62 = MUL(t22 - t23, costab18);
- t36 = t6 + t7;
- t53 = MUL(t6 - t7, costab18);
-
- t8 = in[1] + in[30]; t24 = MUL(in[1] - in[30], costab3);
- t9 = in[14] + in[17]; t25 = MUL(in[14] - in[17], costab29);
-
- t45 = t24 + t25;
- t63 = MUL(t24 - t25, costab6);
- t37 = t8 + t9;
- t54 = MUL(t8 - t9, costab6);
-
- t10 = in[6] + in[25]; t26 = MUL(in[6] - in[25], costab13);
- t11 = in[9] + in[22]; t27 = MUL(in[9] - in[22], costab19);
-
- t46 = t26 + t27;
- t64 = MUL(t26 - t27, costab26);
- t38 = t10 + t11;
- t55 = MUL(t10 - t11, costab26);
-
- t12 = in[2] + in[29]; t28 = MUL(in[2] - in[29], costab5);
- t13 = in[13] + in[18]; t29 = MUL(in[13] - in[18], costab27);
-
- t47 = t28 + t29;
- t65 = MUL(t28 - t29, costab10);
- t39 = t12 + t13;
- t56 = MUL(t12 - t13, costab10);
-
- t14 = in[5] + in[26]; t30 = MUL(in[5] - in[26], costab11);
- t15 = in[10] + in[21]; t31 = MUL(in[10] - in[21], costab21);
-
- t48 = t30 + t31;
- t66 = MUL(t30 - t31, costab22);
- t40 = t14 + t15;
- t57 = MUL(t14 - t15, costab22);
-
- t69 = t33 + t34; t89 = MUL(t33 - t34, costab4);
- t70 = t35 + t36; t90 = MUL(t35 - t36, costab28);
- t71 = t37 + t38; t91 = MUL(t37 - t38, costab12);
- t72 = t39 + t40; t92 = MUL(t39 - t40, costab20);
- t73 = t41 + t42; t94 = MUL(t41 - t42, costab4);
- t74 = t43 + t44; t95 = MUL(t43 - t44, costab28);
- t75 = t45 + t46; t96 = MUL(t45 - t46, costab12);
- t76 = t47 + t48; t97 = MUL(t47 - t48, costab20);
-
- t78 = t50 + t51; t100 = MUL(t50 - t51, costab4);
- t79 = t52 + t53; t101 = MUL(t52 - t53, costab28);
- t80 = t54 + t55; t102 = MUL(t54 - t55, costab12);
- t81 = t56 + t57; t103 = MUL(t56 - t57, costab20);
-
- t83 = t59 + t60; t106 = MUL(t59 - t60, costab4);
- t84 = t61 + t62; t107 = MUL(t61 - t62, costab28);
- t85 = t63 + t64; t108 = MUL(t63 - t64, costab12);
- t86 = t65 + t66; t109 = MUL(t65 - t66, costab20);
-
- t113 = t69 + t70;
- t114 = t71 + t72;
-
- /* 0 */ hi[15][slot] = SHIFT(t113 + t114);
- /* 16 */ lo[ 0][slot] = SHIFT(MUL(t113 - t114, costab16));
-
- t115 = t73 + t74;
- t116 = t75 + t76;
-
- t32 = t115 + t116;
-
- /* 1 */ hi[14][slot] = SHIFT(t32);
-
- t118 = t78 + t79;
- t119 = t80 + t81;
-
- t58 = t118 + t119;
-
- /* 2 */ hi[13][slot] = SHIFT(t58);
-
- t121 = t83 + t84;
- t122 = t85 + t86;
-
- t67 = t121 + t122;
-
- t49 = (t67 * 2) - t32;
-
- /* 3 */ hi[12][slot] = SHIFT(t49);
-
- t125 = t89 + t90;
- t126 = t91 + t92;
-
- t93 = t125 + t126;
-
- /* 4 */ hi[11][slot] = SHIFT(t93);
-
- t128 = t94 + t95;
- t129 = t96 + t97;
-
- t98 = t128 + t129;
-
- t68 = (t98 * 2) - t49;
-
- /* 5 */ hi[10][slot] = SHIFT(t68);
-
- t132 = t100 + t101;
- t133 = t102 + t103;
-
- t104 = t132 + t133;
-
- t82 = (t104 * 2) - t58;
-
- /* 6 */ hi[ 9][slot] = SHIFT(t82);
-
- t136 = t106 + t107;
- t137 = t108 + t109;
-
- t110 = t136 + t137;
-
- t87 = (t110 * 2) - t67;
-
- t77 = (t87 * 2) - t68;
-
- /* 7 */ hi[ 8][slot] = SHIFT(t77);
-
- t141 = MUL(t69 - t70, costab8);
- t142 = MUL(t71 - t72, costab24);
- t143 = t141 + t142;
-
- /* 8 */ hi[ 7][slot] = SHIFT(t143);
- /* 24 */ lo[ 8][slot] =
- SHIFT((MUL(t141 - t142, costab16) * 2) - t143);
-
- t144 = MUL(t73 - t74, costab8);
- t145 = MUL(t75 - t76, costab24);
- t146 = t144 + t145;
-
- t88 = (t146 * 2) - t77;
-
- /* 9 */ hi[ 6][slot] = SHIFT(t88);
-
- t148 = MUL(t78 - t79, costab8);
- t149 = MUL(t80 - t81, costab24);
- t150 = t148 + t149;
-
- t105 = (t150 * 2) - t82;
-
- /* 10 */ hi[ 5][slot] = SHIFT(t105);
-
- t152 = MUL(t83 - t84, costab8);
- t153 = MUL(t85 - t86, costab24);
- t154 = t152 + t153;
-
- t111 = (t154 * 2) - t87;
-
- t99 = (t111 * 2) - t88;
-
- /* 11 */ hi[ 4][slot] = SHIFT(t99);
-
- t157 = MUL(t89 - t90, costab8);
- t158 = MUL(t91 - t92, costab24);
- t159 = t157 + t158;
-
- t127 = (t159 * 2) - t93;
-
- /* 12 */ hi[ 3][slot] = SHIFT(t127);
-
- t160 = (MUL(t125 - t126, costab16) * 2) - t127;
-
- /* 20 */ lo[ 4][slot] = SHIFT(t160);
- /* 28 */ lo[12][slot] =
- SHIFT((((MUL(t157 - t158, costab16) * 2) - t159) * 2) - t160);
-
- t161 = MUL(t94 - t95, costab8);
- t162 = MUL(t96 - t97, costab24);
- t163 = t161 + t162;
-
- t130 = (t163 * 2) - t98;
-
- t112 = (t130 * 2) - t99;
-
- /* 13 */ hi[ 2][slot] = SHIFT(t112);
-
- t164 = (MUL(t128 - t129, costab16) * 2) - t130;
-
- t166 = MUL(t100 - t101, costab8);
- t167 = MUL(t102 - t103, costab24);
- t168 = t166 + t167;
-
- t134 = (t168 * 2) - t104;
-
- t120 = (t134 * 2) - t105;
-
- /* 14 */ hi[ 1][slot] = SHIFT(t120);
-
- t135 = (MUL(t118 - t119, costab16) * 2) - t120;
-
- /* 18 */ lo[ 2][slot] = SHIFT(t135);
-
- t169 = (MUL(t132 - t133, costab16) * 2) - t134;
-
- t151 = (t169 * 2) - t135;
-
- /* 22 */ lo[ 6][slot] = SHIFT(t151);
-
- t170 = (((MUL(t148 - t149, costab16) * 2) - t150) * 2) - t151;
-
- /* 26 */ lo[10][slot] = SHIFT(t170);
- /* 30 */ lo[14][slot] =
- SHIFT((((((MUL(t166 - t167, costab16) * 2) -
- t168) * 2) - t169) * 2) - t170);
-
- t171 = MUL(t106 - t107, costab8);
- t172 = MUL(t108 - t109, costab24);
- t173 = t171 + t172;
-
- t138 = (t173 * 2) - t110;
-
- t123 = (t138 * 2) - t111;
-
- t139 = (MUL(t121 - t122, costab16) * 2) - t123;
-
- t117 = (t123 * 2) - t112;
-
- /* 15 */ hi[ 0][slot] = SHIFT(t117);
-
- t124 = (MUL(t115 - t116, costab16) * 2) - t117;
-
- /* 17 */ lo[ 1][slot] = SHIFT(t124);
-
- t131 = (t139 * 2) - t124;
-
- /* 19 */ lo[ 3][slot] = SHIFT(t131);
-
- t140 = (t164 * 2) - t131;
-
- /* 21 */ lo[ 5][slot] = SHIFT(t140);
-
- t174 = (MUL(t136 - t137, costab16) * 2) - t138;
-
- t155 = (t174 * 2) - t139;
-
- t147 = (t155 * 2) - t140;
-
- /* 23 */ lo[ 7][slot] = SHIFT(t147);
-
- t156 = (((MUL(t144 - t145, costab16) * 2) - t146) * 2) - t147;
-
- /* 25 */ lo[ 9][slot] = SHIFT(t156);
-
- t175 = (((MUL(t152 - t153, costab16) * 2) - t154) * 2) - t155;
-
- t165 = (t175 * 2) - t156;
-
- /* 27 */ lo[11][slot] = SHIFT(t165);
-
- t176 = (((((MUL(t161 - t162, costab16) * 2) -
- t163) * 2) - t164) * 2) - t165;
-
- /* 29 */ lo[13][slot] = SHIFT(t176);
- /* 31 */ lo[15][slot] =
- SHIFT((((((((MUL(t171 - t172, costab16) * 2) -
- t173) * 2) - t174) * 2) - t175) * 2) - t176);
-
- /*
- * Totals:
- * 80 multiplies
- * 80 additions
- * 119 subtractions
- * 49 shifts (not counting SSO)
- */
-}
-
-# undef MUL
-# undef SHIFT
-
-/* third SSO shift and/or D[] optimization preshift */
-
-# if defined(OPT_SSO)
-# if MAD_F_FRACBITS != 28
-# error "MAD_F_FRACBITS must be 28 to use OPT_SSO"
-# endif
-# define ML0(hi, lo, x, y) ((lo) = (x) * (y))
-# define MLA(hi, lo, x, y) ((lo) += (x) * (y))
-# define MLN(hi, lo) ((lo) = -(lo))
-# define MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo))
-# define SHIFT(x) ((x) >> 2)
-# define PRESHIFT(x) ((MAD_F(x) + (1L << 13)) >> 14)
-# else
-# define ML0(hi, lo, x, y) MAD_F_ML0((hi), (lo), (x), (y))
-# define MLA(hi, lo, x, y) MAD_F_MLA((hi), (lo), (x), (y))
-# define MLN(hi, lo) MAD_F_MLN((hi), (lo))
-# define MLZ(hi, lo) MAD_F_MLZ((hi), (lo))
-# define SHIFT(x) (x)
-# if defined(MAD_F_SCALEBITS)
-# undef MAD_F_SCALEBITS
-# define MAD_F_SCALEBITS (MAD_F_FRACBITS - 12)
-# define PRESHIFT(x) (MAD_F(x) >> 12)
-# else
-# define PRESHIFT(x) MAD_F(x)
-# endif
-# endif
-
-static
-mad_fixed_t const D[17][32] = {
-# include "D.dat"
-};
-
-# if defined(ASO_SYNTH)
-void synth_full(struct mad_synth *, struct mad_frame const *,
- unsigned int, unsigned int);
-# else
-/*
- * NAME: synth->full()
- * DESCRIPTION: perform full frequency PCM synthesis
- */
-static
-void synth_full(struct mad_synth *synth, struct mad_frame const *frame,
- unsigned int nch, unsigned int ns)
-{
- unsigned int phase, ch, s, sb, pe, po;
- mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8];
- mad_fixed_t const (*sbsample)[36][32];
- register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8];
- register mad_fixed_t const (*Dptr)[32], *ptr;
- register mad_fixed64hi_t hi;
- register mad_fixed64lo_t lo;
-
- for (ch = 0; ch < nch; ++ch) {
- sbsample = &frame->sbsample[ch];
- filter = &synth->filter[ch];
- phase = synth->phase;
- pcm1 = synth->pcm.samples[ch];
-
- for (s = 0; s < ns; ++s) {
- dct32((*sbsample)[s], phase >> 1,
- (*filter)[0][phase & 1], (*filter)[1][phase & 1]);
-
- pe = phase & ~1;
- po = ((phase - 1) & 0xf) | 1;
-
- /* calculate 32 samples */
-
- fe = &(*filter)[0][ phase & 1][0];
- fx = &(*filter)[0][~phase & 1][0];
- fo = &(*filter)[1][~phase & 1][0];
-
- Dptr = &D[0];
-
- ptr = *Dptr + po;
- ML0(hi, lo, (*fx)[0], ptr[ 0]);
- MLA(hi, lo, (*fx)[1], ptr[14]);
- MLA(hi, lo, (*fx)[2], ptr[12]);
- MLA(hi, lo, (*fx)[3], ptr[10]);
- MLA(hi, lo, (*fx)[4], ptr[ 8]);
- MLA(hi, lo, (*fx)[5], ptr[ 6]);
- MLA(hi, lo, (*fx)[6], ptr[ 4]);
- MLA(hi, lo, (*fx)[7], ptr[ 2]);
- MLN(hi, lo);
-
- ptr = *Dptr + pe;
- MLA(hi, lo, (*fe)[0], ptr[ 0]);
- MLA(hi, lo, (*fe)[1], ptr[14]);
- MLA(hi, lo, (*fe)[2], ptr[12]);
- MLA(hi, lo, (*fe)[3], ptr[10]);
- MLA(hi, lo, (*fe)[4], ptr[ 8]);
- MLA(hi, lo, (*fe)[5], ptr[ 6]);
- MLA(hi, lo, (*fe)[6], ptr[ 4]);
- MLA(hi, lo, (*fe)[7], ptr[ 2]);
-
- *pcm1++ = SHIFT(MLZ(hi, lo));
-
- pcm2 = pcm1 + 30;
-
- for (sb = 1; sb < 16; ++sb) {
- ++fe;
- ++Dptr;
-
- /* D[32 - sb][i] == -D[sb][31 - i] */
-
- ptr = *Dptr + po;
- ML0(hi, lo, (*fo)[0], ptr[ 0]);
- MLA(hi, lo, (*fo)[1], ptr[14]);
- MLA(hi, lo, (*fo)[2], ptr[12]);
- MLA(hi, lo, (*fo)[3], ptr[10]);
- MLA(hi, lo, (*fo)[4], ptr[ 8]);
- MLA(hi, lo, (*fo)[5], ptr[ 6]);
- MLA(hi, lo, (*fo)[6], ptr[ 4]);
- MLA(hi, lo, (*fo)[7], ptr[ 2]);
- MLN(hi, lo);
-
- ptr = *Dptr + pe;
- MLA(hi, lo, (*fe)[7], ptr[ 2]);
- MLA(hi, lo, (*fe)[6], ptr[ 4]);
- MLA(hi, lo, (*fe)[5], ptr[ 6]);
- MLA(hi, lo, (*fe)[4], ptr[ 8]);
- MLA(hi, lo, (*fe)[3], ptr[10]);
- MLA(hi, lo, (*fe)[2], ptr[12]);
- MLA(hi, lo, (*fe)[1], ptr[14]);
- MLA(hi, lo, (*fe)[0], ptr[ 0]);
-
- *pcm1++ = SHIFT(MLZ(hi, lo));
-
- ptr = *Dptr - pe;
- ML0(hi, lo, (*fe)[0], ptr[31 - 16]);
- MLA(hi, lo, (*fe)[1], ptr[31 - 14]);
- MLA(hi, lo, (*fe)[2], ptr[31 - 12]);
- MLA(hi, lo, (*fe)[3], ptr[31 - 10]);
- MLA(hi, lo, (*fe)[4], ptr[31 - 8]);
- MLA(hi, lo, (*fe)[5], ptr[31 - 6]);
- MLA(hi, lo, (*fe)[6], ptr[31 - 4]);
- MLA(hi, lo, (*fe)[7], ptr[31 - 2]);
-
- ptr = *Dptr - po;
- MLA(hi, lo, (*fo)[7], ptr[31 - 2]);
- MLA(hi, lo, (*fo)[6], ptr[31 - 4]);
- MLA(hi, lo, (*fo)[5], ptr[31 - 6]);
- MLA(hi, lo, (*fo)[4], ptr[31 - 8]);
- MLA(hi, lo, (*fo)[3], ptr[31 - 10]);
- MLA(hi, lo, (*fo)[2], ptr[31 - 12]);
- MLA(hi, lo, (*fo)[1], ptr[31 - 14]);
- MLA(hi, lo, (*fo)[0], ptr[31 - 16]);
-
- *pcm2-- = SHIFT(MLZ(hi, lo));
-
- ++fo;
- }
-
- ++Dptr;
-
- ptr = *Dptr + po;
- ML0(hi, lo, (*fo)[0], ptr[ 0]);
- MLA(hi, lo, (*fo)[1], ptr[14]);
- MLA(hi, lo, (*fo)[2], ptr[12]);
- MLA(hi, lo, (*fo)[3], ptr[10]);
- MLA(hi, lo, (*fo)[4], ptr[ 8]);
- MLA(hi, lo, (*fo)[5], ptr[ 6]);
- MLA(hi, lo, (*fo)[6], ptr[ 4]);
- MLA(hi, lo, (*fo)[7], ptr[ 2]);
-
- *pcm1 = SHIFT(-MLZ(hi, lo));
- pcm1 += 16;
-
- phase = (phase + 1) % 16;
- }
- }
-}
-# endif
-
-/*
- * NAME: synth->half()
- * DESCRIPTION: perform half frequency PCM synthesis
- */
-static
-void synth_half(struct mad_synth *synth, struct mad_frame const *frame,
- unsigned int nch, unsigned int ns)
-{
- unsigned int phase, ch, s, sb, pe, po;
- mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8];
- mad_fixed_t const (*sbsample)[36][32];
- register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8];
- register mad_fixed_t const (*Dptr)[32], *ptr;
- register mad_fixed64hi_t hi;
- register mad_fixed64lo_t lo;
-
- for (ch = 0; ch < nch; ++ch) {
- sbsample = &frame->sbsample[ch];
- filter = &synth->filter[ch];
- phase = synth->phase;
- pcm1 = synth->pcm.samples[ch];
-
- for (s = 0; s < ns; ++s) {
- dct32((*sbsample)[s], phase >> 1,
- (*filter)[0][phase & 1], (*filter)[1][phase & 1]);
-
- pe = phase & ~1;
- po = ((phase - 1) & 0xf) | 1;
-
- /* calculate 16 samples */
-
- fe = &(*filter)[0][ phase & 1][0];
- fx = &(*filter)[0][~phase & 1][0];
- fo = &(*filter)[1][~phase & 1][0];
-
- Dptr = &D[0];
-
- ptr = *Dptr + po;
- ML0(hi, lo, (*fx)[0], ptr[ 0]);
- MLA(hi, lo, (*fx)[1], ptr[14]);
- MLA(hi, lo, (*fx)[2], ptr[12]);
- MLA(hi, lo, (*fx)[3], ptr[10]);
- MLA(hi, lo, (*fx)[4], ptr[ 8]);
- MLA(hi, lo, (*fx)[5], ptr[ 6]);
- MLA(hi, lo, (*fx)[6], ptr[ 4]);
- MLA(hi, lo, (*fx)[7], ptr[ 2]);
- MLN(hi, lo);
-
- ptr = *Dptr + pe;
- MLA(hi, lo, (*fe)[0], ptr[ 0]);
- MLA(hi, lo, (*fe)[1], ptr[14]);
- MLA(hi, lo, (*fe)[2], ptr[12]);
- MLA(hi, lo, (*fe)[3], ptr[10]);
- MLA(hi, lo, (*fe)[4], ptr[ 8]);
- MLA(hi, lo, (*fe)[5], ptr[ 6]);
- MLA(hi, lo, (*fe)[6], ptr[ 4]);
- MLA(hi, lo, (*fe)[7], ptr[ 2]);
-
- *pcm1++ = SHIFT(MLZ(hi, lo));
-
- pcm2 = pcm1 + 14;
-
- for (sb = 1; sb < 16; ++sb) {
- ++fe;
- ++Dptr;
-
- /* D[32 - sb][i] == -D[sb][31 - i] */
-
- if (!(sb & 1)) {
- ptr = *Dptr + po;
- ML0(hi, lo, (*fo)[0], ptr[ 0]);
- MLA(hi, lo, (*fo)[1], ptr[14]);
- MLA(hi, lo, (*fo)[2], ptr[12]);
- MLA(hi, lo, (*fo)[3], ptr[10]);
- MLA(hi, lo, (*fo)[4], ptr[ 8]);
- MLA(hi, lo, (*fo)[5], ptr[ 6]);
- MLA(hi, lo, (*fo)[6], ptr[ 4]);
- MLA(hi, lo, (*fo)[7], ptr[ 2]);
- MLN(hi, lo);
-
- ptr = *Dptr + pe;
- MLA(hi, lo, (*fe)[7], ptr[ 2]);
- MLA(hi, lo, (*fe)[6], ptr[ 4]);
- MLA(hi, lo, (*fe)[5], ptr[ 6]);
- MLA(hi, lo, (*fe)[4], ptr[ 8]);
- MLA(hi, lo, (*fe)[3], ptr[10]);
- MLA(hi, lo, (*fe)[2], ptr[12]);
- MLA(hi, lo, (*fe)[1], ptr[14]);
- MLA(hi, lo, (*fe)[0], ptr[ 0]);
-
- *pcm1++ = SHIFT(MLZ(hi, lo));
-
- ptr = *Dptr - po;
- ML0(hi, lo, (*fo)[7], ptr[31 - 2]);
- MLA(hi, lo, (*fo)[6], ptr[31 - 4]);
- MLA(hi, lo, (*fo)[5], ptr[31 - 6]);
- MLA(hi, lo, (*fo)[4], ptr[31 - 8]);
- MLA(hi, lo, (*fo)[3], ptr[31 - 10]);
- MLA(hi, lo, (*fo)[2], ptr[31 - 12]);
- MLA(hi, lo, (*fo)[1], ptr[31 - 14]);
- MLA(hi, lo, (*fo)[0], ptr[31 - 16]);
-
- ptr = *Dptr - pe;
- MLA(hi, lo, (*fe)[0], ptr[31 - 16]);
- MLA(hi, lo, (*fe)[1], ptr[31 - 14]);
- MLA(hi, lo, (*fe)[2], ptr[31 - 12]);
- MLA(hi, lo, (*fe)[3], ptr[31 - 10]);
- MLA(hi, lo, (*fe)[4], ptr[31 - 8]);
- MLA(hi, lo, (*fe)[5], ptr[31 - 6]);
- MLA(hi, lo, (*fe)[6], ptr[31 - 4]);
- MLA(hi, lo, (*fe)[7], ptr[31 - 2]);
-
- *pcm2-- = SHIFT(MLZ(hi, lo));
- }
-
- ++fo;
- }
-
- ++Dptr;
-
- ptr = *Dptr + po;
- ML0(hi, lo, (*fo)[0], ptr[ 0]);
- MLA(hi, lo, (*fo)[1], ptr[14]);
- MLA(hi, lo, (*fo)[2], ptr[12]);
- MLA(hi, lo, (*fo)[3], ptr[10]);
- MLA(hi, lo, (*fo)[4], ptr[ 8]);
- MLA(hi, lo, (*fo)[5], ptr[ 6]);
- MLA(hi, lo, (*fo)[6], ptr[ 4]);
- MLA(hi, lo, (*fo)[7], ptr[ 2]);
-
- *pcm1 = SHIFT(-MLZ(hi, lo));
- pcm1 += 8;
-
- phase = (phase + 1) % 16;
- }
- }
-}
-
-/*
- * NAME: synth->frame()
- * DESCRIPTION: perform PCM synthesis of frame subband samples
- */
-void mad_synth_frame(struct mad_synth *synth, struct mad_frame const *frame)
-{
- unsigned int nch, ns;
- void (*synth_frame)(struct mad_synth *, struct mad_frame const *,
- unsigned int, unsigned int);
-
- nch = MAD_NCHANNELS(&frame->header);
- ns = MAD_NSBSAMPLES(&frame->header);
-
- synth->pcm.samplerate = frame->header.samplerate;
- synth->pcm.channels = nch;
- synth->pcm.length = 32 * ns;
-
- synth_frame = synth_full;
-
- if (frame->options & MAD_OPTION_HALFSAMPLERATE) {
- synth->pcm.samplerate /= 2;
- synth->pcm.length /= 2;
-
- synth_frame = synth_half;
- }
-
- synth_frame(synth, frame, nch, ns);
-
- synth->phase = (synth->phase + ns) % 16;
-}
-
-# ifdef _MSC_VER
-# pragma warning(pop)
-# endif
diff --git a/libmad/src/synth.h b/libmad/src/synth.h
deleted file mode 100644
index 8ae4bc9..0000000
--- a/libmad/src/synth.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: synth.h,v 1.15 2004/01/23 09:41:33 rob Exp $
- */
-
-# ifndef LIBMAD_SYNTH_H
-# define LIBMAD_SYNTH_H
-
-# include "fixed.h"
-# include "frame.h"
-
-struct mad_pcm {
- unsigned int samplerate; /* sampling frequency (Hz) */
- unsigned short channels; /* number of channels */
- unsigned short length; /* number of samples per channel */
- mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */
-};
-
-struct mad_synth {
- mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */
- /* [ch][eo][peo][s][v] */
-
- unsigned int phase; /* current processing phase */
-
- struct mad_pcm pcm; /* PCM output */
-};
-
-/* single channel PCM selector */
-enum {
- MAD_PCM_CHANNEL_SINGLE = 0
-};
-
-/* dual channel PCM selector */
-enum {
- MAD_PCM_CHANNEL_DUAL_1 = 0,
- MAD_PCM_CHANNEL_DUAL_2 = 1
-};
-
-/* stereo PCM selector */
-enum {
- MAD_PCM_CHANNEL_STEREO_LEFT = 0,
- MAD_PCM_CHANNEL_STEREO_RIGHT = 1
-};
-
-void mad_synth_init(struct mad_synth *);
-
-# define mad_synth_finish(synth) /* nothing */
-
-void mad_synth_mute(struct mad_synth *);
-
-void mad_synth_frame(struct mad_synth *, struct mad_frame const *);
-
-# endif
diff --git a/libmad/src/timer.c b/libmad/src/timer.c
deleted file mode 100644
index 4b909ab..0000000
--- a/libmad/src/timer.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: timer.c,v 1.18 2004/01/23 09:41:33 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdio.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "timer.h"
-
-mad_timer_t const mad_timer_zero = { 0, 0 };
-
-/*
- * NAME: timer->compare()
- * DESCRIPTION: indicate relative order of two timers
- */
-int mad_timer_compare(mad_timer_t timer1, mad_timer_t timer2)
-{
- signed long diff;
-
- diff = timer1.seconds - timer2.seconds;
- if (diff < 0)
- return -1;
- else if (diff > 0)
- return +1;
-
- diff = timer1.fraction - timer2.fraction;
- if (diff < 0)
- return -1;
- else if (diff > 0)
- return +1;
-
- return 0;
-}
-
-/*
- * NAME: timer->negate()
- * DESCRIPTION: invert the sign of a timer
- */
-void mad_timer_negate(mad_timer_t *timer)
-{
- timer->seconds = -timer->seconds;
-
- if (timer->fraction) {
- timer->seconds -= 1;
- timer->fraction = MAD_TIMER_RESOLUTION - timer->fraction;
- }
-}
-
-/*
- * NAME: timer->abs()
- * DESCRIPTION: return the absolute value of a timer
- */
-mad_timer_t mad_timer_abs(mad_timer_t timer)
-{
- if (timer.seconds < 0)
- mad_timer_negate(&timer);
-
- return timer;
-}
-
-/*
- * NAME: reduce_timer()
- * DESCRIPTION: carry timer fraction into seconds
- */
-static
-void reduce_timer(mad_timer_t *timer)
-{
- timer->seconds += timer->fraction / MAD_TIMER_RESOLUTION;
- timer->fraction %= MAD_TIMER_RESOLUTION;
-}
-
-/*
- * NAME: gcd()
- * DESCRIPTION: compute greatest common denominator
- */
-static
-unsigned long gcd(unsigned long num1, unsigned long num2)
-{
- unsigned long tmp;
-
- while (num2) {
- tmp = num2;
- num2 = num1 % num2;
- num1 = tmp;
- }
-
- return num1;
-}
-
-/*
- * NAME: reduce_rational()
- * DESCRIPTION: convert rational expression to lowest terms
- */
-static
-void reduce_rational(unsigned long *numer, unsigned long *denom)
-{
- unsigned long factor;
-
- factor = gcd(*numer, *denom);
-
- assert(factor != 0);
-
- *numer /= factor;
- *denom /= factor;
-}
-
-/*
- * NAME: scale_rational()
- * DESCRIPTION: solve numer/denom == ?/scale avoiding overflowing
- */
-static
-unsigned long scale_rational(unsigned long numer, unsigned long denom,
- unsigned long scale)
-{
- reduce_rational(&numer, &denom);
- reduce_rational(&scale, &denom);
-
- assert(denom != 0);
-
- if (denom < scale)
- return numer * (scale / denom) + numer * (scale % denom) / denom;
- if (denom < numer)
- return scale * (numer / denom) + scale * (numer % denom) / denom;
-
- return numer * scale / denom;
-}
-
-/*
- * NAME: timer->set()
- * DESCRIPTION: set timer to specific (positive) value
- */
-void mad_timer_set(mad_timer_t *timer, unsigned long seconds,
- unsigned long numer, unsigned long denom)
-{
- timer->seconds = seconds;
- if (numer >= denom && denom > 0) {
- timer->seconds += numer / denom;
- numer %= denom;
- }
-
- switch (denom) {
- case 0:
- case 1:
- timer->fraction = 0;
- break;
-
- case MAD_TIMER_RESOLUTION:
- timer->fraction = numer;
- break;
-
- case 1000:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 1000);
- break;
-
- case 8000:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 8000);
- break;
-
- case 11025:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 11025);
- break;
-
- case 12000:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 12000);
- break;
-
- case 16000:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 16000);
- break;
-
- case 22050:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 22050);
- break;
-
- case 24000:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 24000);
- break;
-
- case 32000:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 32000);
- break;
-
- case 44100:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 44100);
- break;
-
- case 48000:
- timer->fraction = numer * (MAD_TIMER_RESOLUTION / 48000);
- break;
-
- default:
- timer->fraction = scale_rational(numer, denom, MAD_TIMER_RESOLUTION);
- break;
- }
-
- if (timer->fraction >= MAD_TIMER_RESOLUTION)
- reduce_timer(timer);
-}
-
-/*
- * NAME: timer->add()
- * DESCRIPTION: add one timer to another
- */
-void mad_timer_add(mad_timer_t *timer, mad_timer_t incr)
-{
- timer->seconds += incr.seconds;
- timer->fraction += incr.fraction;
-
- if (timer->fraction >= MAD_TIMER_RESOLUTION)
- reduce_timer(timer);
-}
-
-/*
- * NAME: timer->multiply()
- * DESCRIPTION: multiply a timer by a scalar value
- */
-void mad_timer_multiply(mad_timer_t *timer, signed long scalar)
-{
- mad_timer_t addend;
- unsigned long factor;
-
- factor = scalar;
- if (scalar < 0) {
- factor = -scalar;
- mad_timer_negate(timer);
- }
-
- addend = *timer;
- *timer = mad_timer_zero;
-
- while (factor) {
- if (factor & 1)
- mad_timer_add(timer, addend);
-
- mad_timer_add(&addend, addend);
- factor >>= 1;
- }
-}
-
-/*
- * NAME: timer->count()
- * DESCRIPTION: return timer value in selected units
- */
-signed long mad_timer_count(mad_timer_t timer, enum mad_units units)
-{
- switch (units) {
- case MAD_UNITS_HOURS:
- return timer.seconds / 60 / 60;
-
- case MAD_UNITS_MINUTES:
- return timer.seconds / 60;
-
- case MAD_UNITS_SECONDS:
- return timer.seconds;
-
- case MAD_UNITS_DECISECONDS:
- case MAD_UNITS_CENTISECONDS:
- case MAD_UNITS_MILLISECONDS:
-
- case MAD_UNITS_8000_HZ:
- case MAD_UNITS_11025_HZ:
- case MAD_UNITS_12000_HZ:
- case MAD_UNITS_16000_HZ:
- case MAD_UNITS_22050_HZ:
- case MAD_UNITS_24000_HZ:
- case MAD_UNITS_32000_HZ:
- case MAD_UNITS_44100_HZ:
- case MAD_UNITS_48000_HZ:
-
- case MAD_UNITS_24_FPS:
- case MAD_UNITS_25_FPS:
- case MAD_UNITS_30_FPS:
- case MAD_UNITS_48_FPS:
- case MAD_UNITS_50_FPS:
- case MAD_UNITS_60_FPS:
- case MAD_UNITS_75_FPS:
- return timer.seconds * (signed long) units +
- (signed long) scale_rational(timer.fraction, MAD_TIMER_RESOLUTION,
- units);
-
- case MAD_UNITS_23_976_FPS:
- case MAD_UNITS_24_975_FPS:
- case MAD_UNITS_29_97_FPS:
- case MAD_UNITS_47_952_FPS:
- case MAD_UNITS_49_95_FPS:
- case MAD_UNITS_59_94_FPS:
- return (mad_timer_count(timer, -units) + 1) * 1000 / 1001;
- }
-
- /* unsupported units */
- return 0;
-}
-
-/*
- * NAME: timer->fraction()
- * DESCRIPTION: return fractional part of timer in arbitrary terms
- */
-unsigned long mad_timer_fraction(mad_timer_t timer, unsigned long denom)
-{
- timer = mad_timer_abs(timer);
-
- switch (denom) {
- case 0:
- return timer.fraction ?
- MAD_TIMER_RESOLUTION / timer.fraction : MAD_TIMER_RESOLUTION + 1;
-
- case MAD_TIMER_RESOLUTION:
- return timer.fraction;
-
- default:
- return scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, denom);
- }
-}
-
-/*
- * NAME: timer->string()
- * DESCRIPTION: write a string representation of a timer using a template
- */
-void mad_timer_string(mad_timer_t timer,
- char *dest, char const *format, enum mad_units units,
- enum mad_units fracunits, unsigned long subparts)
-{
- unsigned long hours, minutes, seconds, sub;
- unsigned int frac;
-
- timer = mad_timer_abs(timer);
-
- seconds = timer.seconds;
- frac = sub = 0;
-
- switch (fracunits) {
- case MAD_UNITS_HOURS:
- case MAD_UNITS_MINUTES:
- case MAD_UNITS_SECONDS:
- break;
-
- case MAD_UNITS_DECISECONDS:
- case MAD_UNITS_CENTISECONDS:
- case MAD_UNITS_MILLISECONDS:
-
- case MAD_UNITS_8000_HZ:
- case MAD_UNITS_11025_HZ:
- case MAD_UNITS_12000_HZ:
- case MAD_UNITS_16000_HZ:
- case MAD_UNITS_22050_HZ:
- case MAD_UNITS_24000_HZ:
- case MAD_UNITS_32000_HZ:
- case MAD_UNITS_44100_HZ:
- case MAD_UNITS_48000_HZ:
-
- case MAD_UNITS_24_FPS:
- case MAD_UNITS_25_FPS:
- case MAD_UNITS_30_FPS:
- case MAD_UNITS_48_FPS:
- case MAD_UNITS_50_FPS:
- case MAD_UNITS_60_FPS:
- case MAD_UNITS_75_FPS:
- {
- unsigned long denom;
-
- denom = MAD_TIMER_RESOLUTION / fracunits;
-
- frac = timer.fraction / denom;
- sub = scale_rational(timer.fraction % denom, denom, subparts);
- }
- break;
-
- case MAD_UNITS_23_976_FPS:
- case MAD_UNITS_24_975_FPS:
- case MAD_UNITS_29_97_FPS:
- case MAD_UNITS_47_952_FPS:
- case MAD_UNITS_49_95_FPS:
- case MAD_UNITS_59_94_FPS:
- /* drop-frame encoding */
- /* N.B. this is only well-defined for MAD_UNITS_29_97_FPS */
- {
- unsigned long frame, cycle, d, m;
-
- frame = mad_timer_count(timer, fracunits);
-
- cycle = -fracunits * 60 * 10 - (10 - 1) * 2;
-
- d = frame / cycle;
- m = frame % cycle;
- frame += (10 - 1) * 2 * d;
- if (m > 2)
- frame += 2 * ((m - 2) / (cycle / 10));
-
- frac = frame % -fracunits;
- seconds = frame / -fracunits;
- }
- break;
- }
-
- switch (units) {
- case MAD_UNITS_HOURS:
- minutes = seconds / 60;
- hours = minutes / 60;
-
- sprintf(dest, format,
- hours,
- (unsigned int) (minutes % 60),
- (unsigned int) (seconds % 60),
- frac, sub);
- break;
-
- case MAD_UNITS_MINUTES:
- minutes = seconds / 60;
-
- sprintf(dest, format,
- minutes,
- (unsigned int) (seconds % 60),
- frac, sub);
- break;
-
- case MAD_UNITS_SECONDS:
- sprintf(dest, format,
- seconds,
- frac, sub);
- break;
-
- case MAD_UNITS_23_976_FPS:
- case MAD_UNITS_24_975_FPS:
- case MAD_UNITS_29_97_FPS:
- case MAD_UNITS_47_952_FPS:
- case MAD_UNITS_49_95_FPS:
- case MAD_UNITS_59_94_FPS:
- if (fracunits < 0) {
- /* not yet implemented */
- sub = 0;
- }
-
- /* fall through */
-
- case MAD_UNITS_DECISECONDS:
- case MAD_UNITS_CENTISECONDS:
- case MAD_UNITS_MILLISECONDS:
-
- case MAD_UNITS_8000_HZ:
- case MAD_UNITS_11025_HZ:
- case MAD_UNITS_12000_HZ:
- case MAD_UNITS_16000_HZ:
- case MAD_UNITS_22050_HZ:
- case MAD_UNITS_24000_HZ:
- case MAD_UNITS_32000_HZ:
- case MAD_UNITS_44100_HZ:
- case MAD_UNITS_48000_HZ:
-
- case MAD_UNITS_24_FPS:
- case MAD_UNITS_25_FPS:
- case MAD_UNITS_30_FPS:
- case MAD_UNITS_48_FPS:
- case MAD_UNITS_50_FPS:
- case MAD_UNITS_60_FPS:
- case MAD_UNITS_75_FPS:
- sprintf(dest, format, mad_timer_count(timer, units), sub);
- break;
- }
-}
diff --git a/libmad/src/timer.h b/libmad/src/timer.h
deleted file mode 100644
index eb4542b..0000000
--- a/libmad/src/timer.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: timer.h,v 1.16 2004/01/23 09:41:33 rob Exp $
- */
-
-# ifndef LIBMAD_TIMER_H
-# define LIBMAD_TIMER_H
-
-typedef struct {
- signed long seconds; /* whole seconds */
- unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */
-} mad_timer_t;
-
-extern mad_timer_t const mad_timer_zero;
-
-# define MAD_TIMER_RESOLUTION 352800000UL
-
-enum mad_units {
- MAD_UNITS_HOURS = -2,
- MAD_UNITS_MINUTES = -1,
- MAD_UNITS_SECONDS = 0,
-
- /* metric units */
-
- MAD_UNITS_DECISECONDS = 10,
- MAD_UNITS_CENTISECONDS = 100,
- MAD_UNITS_MILLISECONDS = 1000,
-
- /* audio sample units */
-
- MAD_UNITS_8000_HZ = 8000,
- MAD_UNITS_11025_HZ = 11025,
- MAD_UNITS_12000_HZ = 12000,
-
- MAD_UNITS_16000_HZ = 16000,
- MAD_UNITS_22050_HZ = 22050,
- MAD_UNITS_24000_HZ = 24000,
-
- MAD_UNITS_32000_HZ = 32000,
- MAD_UNITS_44100_HZ = 44100,
- MAD_UNITS_48000_HZ = 48000,
-
- /* video frame/field units */
-
- MAD_UNITS_24_FPS = 24,
- MAD_UNITS_25_FPS = 25,
- MAD_UNITS_30_FPS = 30,
- MAD_UNITS_48_FPS = 48,
- MAD_UNITS_50_FPS = 50,
- MAD_UNITS_60_FPS = 60,
-
- /* CD audio frames */
-
- MAD_UNITS_75_FPS = 75,
-
- /* video drop-frame units */
-
- MAD_UNITS_23_976_FPS = -24,
- MAD_UNITS_24_975_FPS = -25,
- MAD_UNITS_29_97_FPS = -30,
- MAD_UNITS_47_952_FPS = -48,
- MAD_UNITS_49_95_FPS = -50,
- MAD_UNITS_59_94_FPS = -60
-};
-
-# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero))
-
-int mad_timer_compare(mad_timer_t, mad_timer_t);
-
-# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero)
-
-void mad_timer_negate(mad_timer_t *);
-mad_timer_t mad_timer_abs(mad_timer_t);
-
-void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long);
-void mad_timer_add(mad_timer_t *, mad_timer_t);
-void mad_timer_multiply(mad_timer_t *, signed long);
-
-signed long mad_timer_count(mad_timer_t, enum mad_units);
-unsigned long mad_timer_fraction(mad_timer_t, unsigned long);
-void mad_timer_string(mad_timer_t, char *, char const *,
- enum mad_units, enum mad_units, unsigned long);
-
-# endif
diff --git a/libmad/src/version.c b/libmad/src/version.c
deleted file mode 100644
index e643fa7..0000000
--- a/libmad/src/version.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: version.c,v 1.15 2004/01/23 09:41:33 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include "version.h"
-
-char const mad_version[] = "MPEG Audio Decoder " MAD_VERSION;
-char const mad_copyright[] = "Copyright (C) " MAD_PUBLISHYEAR " " MAD_AUTHOR;
-char const mad_author[] = MAD_AUTHOR " <" MAD_EMAIL ">";
-
-char const mad_build[] = ""
-# if defined(DEBUG)
- "DEBUG "
-# elif defined(NDEBUG)
- "NDEBUG "
-# endif
-
-# if defined(EXPERIMENTAL)
- "EXPERIMENTAL "
-# endif
-
-# if defined(FPM_64BIT)
- "FPM_64BIT "
-# elif defined(FPM_INTEL)
- "FPM_INTEL "
-# elif defined(FPM_ARM)
- "FPM_ARM "
-# elif defined(FPM_MIPS)
- "FPM_MIPS "
-# elif defined(FPM_SPARC)
- "FPM_SPARC "
-# elif defined(FPM_PPC)
- "FPM_PPC "
-# elif defined(FPM_DEFAULT)
- "FPM_DEFAULT "
-# endif
-
-# if defined(ASO_IMDCT)
- "ASO_IMDCT "
-# endif
-# if defined(ASO_INTERLEAVE1)
- "ASO_INTERLEAVE1 "
-# endif
-# if defined(ASO_INTERLEAVE2)
- "ASO_INTERLEAVE2 "
-# endif
-# if defined(ASO_ZEROCHECK)
- "ASO_ZEROCHECK "
-# endif
-
-# if defined(OPT_SPEED)
- "OPT_SPEED "
-# elif defined(OPT_ACCURACY)
- "OPT_ACCURACY "
-# endif
-
-# if defined(OPT_SSO)
- "OPT_SSO "
-# endif
-
-# if defined(OPT_DCTO) /* never defined here */
- "OPT_DCTO "
-# endif
-
-# if defined(OPT_STRICT)
- "OPT_STRICT "
-# endif
-;
diff --git a/libmad/src/version.h b/libmad/src/version.h
deleted file mode 100644
index d215d4c..0000000
--- a/libmad/src/version.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * libmad - MPEG audio decoder library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: version.h,v 1.26 2004/01/23 09:41:33 rob Exp $
- */
-
-# ifndef LIBMAD_VERSION_H
-# define LIBMAD_VERSION_H
-
-# define MAD_VERSION_MAJOR 0
-# define MAD_VERSION_MINOR 15
-# define MAD_VERSION_PATCH 1
-# define MAD_VERSION_EXTRA " (beta)"
-
-# define MAD_VERSION_STRINGIZE(str) #str
-# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num)
-
-# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \
- MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \
- MAD_VERSION_STRING(MAD_VERSION_PATCH) \
- MAD_VERSION_EXTRA
-
-# define MAD_PUBLISHYEAR "2000-2004"
-# define MAD_AUTHOR "Underbit Technologies, Inc."
-# define MAD_EMAIL "info@underbit.com"
-
-extern char const mad_version[];
-extern char const mad_copyright[];
-extern char const mad_author[];
-extern char const mad_build[];
-
-# endif
diff --git a/pianobar/resources/pianobar.ico b/pianobar/resources/pianobar.ico
new file mode 100644
index 0000000..2ec5aa5
--- /dev/null
+++ b/pianobar/resources/pianobar.ico
Binary files differ
diff --git a/pianobar/resources/pianobar.rc b/pianobar/resources/pianobar.rc
new file mode 100644
index 0000000..fe31bfa
--- /dev/null
+++ b/pianobar/resources/pianobar.rc
@@ -0,0 +1,36 @@
+#include "../src/src/config.h"
+
+MAINICON ICON "pianobar.ico"
+
+1 VERSIONINFO
+FILEVERSION 1,0,0,0
+//PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_BUILD,VERSION_REV
+FILEFLAGSMASK 0X3FL
+FILEFLAGS 0L
+FILEOS 0X40004L
+FILETYPE 0X1
+FILESUBTYPE 0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "Comments", "Ported to Windows by Micha Cicho <thedmd@interia.pl>"
+ //VALUE "FileVersion", BUILD_VERSION
+ VALUE "ProductVersion", VERSION
+#ifdef _DEBUG
+ VALUE "OriginalFilename", PACKAGE "-debug.exe"
+#else
+ VALUE "OriginalFilename", PACKAGE ".exe"
+#endif
+ VALUE "FileDescription", "Pandora Radio Client"
+ VALUE "LegalCopyright", "Copyright (C) 2011-2015, Lars-Dominik Braun <lars@6xq.net>"
+ VALUE "ProductName", "pianobar - Pandora Radio Client"
+ VALUE "PrivateBuild", "Micha Cicho <thedmd@interia.pl>"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 0x04B0
+ END
+END
diff --git a/polarssl/polarssl.vcxproj b/polarssl/polarssl.vcxproj
deleted file mode 100644
index 8928310..0000000
--- a/polarssl/polarssl.vcxproj
+++ /dev/null
@@ -1,271 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}</ProjectGuid>
- <RootNamespace>polarssl</RootNamespace>
- <Keyword>Win32Proj</Keyword>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>NotSet</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v110_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>NotSet</CharacterSet>
- <PlatformToolset>v110_xp</PlatformToolset>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)build\temp\lib\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)build\temp\lib\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)build\temp\obj\$(ProjectName)\$(Configuration)\</IntDir>
- <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
- <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
- <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
- <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)-mt-debug</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)-mt</TargetName>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <WholeProgramOptimization>false</WholeProgramOptimization>
- <AdditionalIncludeDirectories>$(SolutionDir)compatibility;$(ProjectDir)src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;BUILDING_CYASSL;NO_HC128;NO_PSK;NO_FILESYSTEM;DEBUG_CYASSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>false</MinimalRebuild>
- <ExceptionHandling>
- </ExceptionHandling>
- <BasicRuntimeChecks>Default</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>OldStyle</DebugInformationFormat>
- </ClCompile>
- <Lib>
- </Lib>
- <PostBuildEvent>
- <Command>xcopy "$(ProjectDir)src\include\polarssl\aes.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\arc4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\asn1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\asn1write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\base64.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\bignum.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\bn_mul.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\camellia.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\certs.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\cipher.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\cipher_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\config.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\ctr_drbg.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\debug.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\des.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\dhm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\entropy.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\entropy_poll.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\error.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\gcm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\havege.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md5.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\net.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\openssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\padlock.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\pem.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\pkcs11.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\rsa.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\sha1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\sha2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\sha4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\ssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\timing.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\version.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\x509.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\x509write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\xtea.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D</Command>
- </PostBuildEvent>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
- <IntrinsicFunctions>false</IntrinsicFunctions>
- <WholeProgramOptimization>false</WholeProgramOptimization>
- <AdditionalIncludeDirectories>$(SolutionDir)compatibility;$(ProjectDir)src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;BUILDING_CYASSL;NO_HC128;NO_PSK;NO_FILESYSTEM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>false</MinimalRebuild>
- <ExceptionHandling>
- </ExceptionHandling>
- <BasicRuntimeChecks>Default</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>
- </DebugInformationFormat>
- </ClCompile>
- <Lib>
- </Lib>
- <PostBuildEvent>
- <Command>xcopy "$(ProjectDir)src\include\polarssl\aes.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\arc4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\asn1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\asn1write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\base64.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\bignum.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\bn_mul.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\camellia.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\certs.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\cipher.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\cipher_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\config.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\ctr_drbg.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\debug.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\des.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\dhm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\entropy.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\entropy_poll.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\error.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\gcm.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\havege.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md_wrap.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\md5.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\net.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\openssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\padlock.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\pem.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\pkcs11.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\rsa.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\sha1.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\sha2.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\sha4.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\ssl.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\timing.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\version.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\x509.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\x509write.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D
-xcopy "$(ProjectDir)src\include\polarssl\xtea.h" "$(SolutionDir)build\temp\include\polarssl\" /I /Y /D</Command>
- </PostBuildEvent>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="src\include\polarssl\aes.h" />
- <ClInclude Include="src\include\polarssl\arc4.h" />
- <ClInclude Include="src\include\polarssl\asn1.h" />
- <ClInclude Include="src\include\polarssl\asn1write.h" />
- <ClInclude Include="src\include\polarssl\base64.h" />
- <ClInclude Include="src\include\polarssl\bignum.h" />
- <ClInclude Include="src\include\polarssl\bn_mul.h" />
- <ClInclude Include="src\include\polarssl\camellia.h" />
- <ClInclude Include="src\include\polarssl\certs.h" />
- <ClInclude Include="src\include\polarssl\cipher.h" />
- <ClInclude Include="src\include\polarssl\cipher_wrap.h" />
- <ClInclude Include="src\include\polarssl\config.h" />
- <ClInclude Include="src\include\polarssl\ctr_drbg.h" />
- <ClInclude Include="src\include\polarssl\debug.h" />
- <ClInclude Include="src\include\polarssl\des.h" />
- <ClInclude Include="src\include\polarssl\dhm.h" />
- <ClInclude Include="src\include\polarssl\entropy.h" />
- <ClInclude Include="src\include\polarssl\entropy_poll.h" />
- <ClInclude Include="src\include\polarssl\error.h" />
- <ClInclude Include="src\include\polarssl\gcm.h" />
- <ClInclude Include="src\include\polarssl\havege.h" />
- <ClInclude Include="src\include\polarssl\md.h" />
- <ClInclude Include="src\include\polarssl\md2.h" />
- <ClInclude Include="src\include\polarssl\md4.h" />
- <ClInclude Include="src\include\polarssl\md5.h" />
- <ClInclude Include="src\include\polarssl\md_wrap.h" />
- <ClInclude Include="src\include\polarssl\net.h" />
- <ClInclude Include="src\include\polarssl\openssl.h" />
- <ClInclude Include="src\include\polarssl\padlock.h" />
- <ClInclude Include="src\include\polarssl\pem.h" />
- <ClInclude Include="src\include\polarssl\pkcs11.h" />
- <ClInclude Include="src\include\polarssl\rsa.h" />
- <ClInclude Include="src\include\polarssl\sha1.h" />
- <ClInclude Include="src\include\polarssl\sha2.h" />
- <ClInclude Include="src\include\polarssl\sha4.h" />
- <ClInclude Include="src\include\polarssl\ssl.h" />
- <ClInclude Include="src\include\polarssl\timing.h" />
- <ClInclude Include="src\include\polarssl\version.h" />
- <ClInclude Include="src\include\polarssl\x509.h" />
- <ClInclude Include="src\include\polarssl\x509write.h" />
- <ClInclude Include="src\include\polarssl\xtea.h" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\library\aes.c" />
- <ClCompile Include="src\library\arc4.c" />
- <ClCompile Include="src\library\asn1parse.c" />
- <ClCompile Include="src\library\asn1write.c" />
- <ClCompile Include="src\library\base64.c" />
- <ClCompile Include="src\library\bignum.c" />
- <ClCompile Include="src\library\camellia.c" />
- <ClCompile Include="src\library\certs.c" />
- <ClCompile Include="src\library\cipher.c" />
- <ClCompile Include="src\library\cipher_wrap.c" />
- <ClCompile Include="src\library\ctr_drbg.c" />
- <ClCompile Include="src\library\debug.c" />
- <ClCompile Include="src\library\des.c" />
- <ClCompile Include="src\library\dhm.c" />
- <ClCompile Include="src\library\entropy.c" />
- <ClCompile Include="src\library\entropy_poll.c" />
- <ClCompile Include="src\library\error.c" />
- <ClCompile Include="src\library\gcm.c" />
- <ClCompile Include="src\library\havege.c" />
- <ClCompile Include="src\library\md.c" />
- <ClCompile Include="src\library\md2.c" />
- <ClCompile Include="src\library\md4.c" />
- <ClCompile Include="src\library\md5.c" />
- <ClCompile Include="src\library\md_wrap.c" />
- <ClCompile Include="src\library\net.c" />
- <ClCompile Include="src\library\padlock.c" />
- <ClCompile Include="src\library\pem.c" />
- <ClCompile Include="src\library\pkcs11.c" />
- <ClCompile Include="src\library\rsa.c" />
- <ClCompile Include="src\library\sha1.c" />
- <ClCompile Include="src\library\sha2.c" />
- <ClCompile Include="src\library\sha4.c" />
- <ClCompile Include="src\library\ssl_cli.c" />
- <ClCompile Include="src\library\ssl_srv.c" />
- <ClCompile Include="src\library\ssl_tls.c" />
- <ClCompile Include="src\library\timing.c" />
- <ClCompile Include="src\library\version.c" />
- <ClCompile Include="src\library\x509parse.c" />
- <ClCompile Include="src\library\x509write.c" />
- <ClCompile Include="src\library\xtea.c" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/polarssl/polarssl.vcxproj.filters b/polarssl/polarssl.vcxproj.filters
deleted file mode 100644
index 8c5076d..0000000
--- a/polarssl/polarssl.vcxproj.filters
+++ /dev/null
@@ -1,258 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="include">
- <UniqueIdentifier>{93cd31ac-6f98-4ce9-a880-42c25c8d340d}</UniqueIdentifier>
- </Filter>
- <Filter Include="src">
- <UniqueIdentifier>{6040e80f-2dd1-4f7a-8b5b-53587ddc714d}</UniqueIdentifier>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\include\polarssl\aes.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\arc4.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\asn1.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\asn1write.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\base64.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\bignum.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\bn_mul.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\camellia.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\certs.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\cipher.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\cipher_wrap.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\config.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\ctr_drbg.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\debug.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\des.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\dhm.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\entropy.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\entropy_poll.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\error.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\gcm.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\havege.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\md.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\md2.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\md4.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\md5.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\md_wrap.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\net.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\openssl.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\padlock.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\pem.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\pkcs11.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\rsa.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\sha1.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\sha2.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\sha4.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\ssl.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\timing.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\version.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\x509.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\x509write.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\include\polarssl\xtea.h">
- <Filter>include</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\library\aes.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\arc4.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\asn1parse.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\asn1write.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\base64.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\bignum.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\camellia.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\certs.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\cipher.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\cipher_wrap.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\ctr_drbg.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\debug.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\des.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\dhm.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\entropy.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\entropy_poll.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\error.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\gcm.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\havege.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\md.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\md2.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\md4.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\md5.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\md_wrap.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\net.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\padlock.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\pem.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\pkcs11.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\rsa.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\sha1.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\sha2.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\sha4.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\ssl_cli.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\ssl_srv.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\ssl_tls.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\timing.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\version.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\x509parse.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\x509write.c">
- <Filter>src</Filter>
- </ClCompile>
- <ClCompile Include="src\library\xtea.c">
- <Filter>src</Filter>
- </ClCompile>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/polarssl/src/LICENSE b/polarssl/src/LICENSE
deleted file mode 100644
index d511905..0000000
--- a/polarssl/src/LICENSE
+++ /dev/null
@@ -1,339 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/polarssl/src/include/polarssl/aes.h b/polarssl/src/include/polarssl/aes.h
deleted file mode 100644
index 80fd6d9..0000000
--- a/polarssl/src/include/polarssl/aes.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * \file aes.h
- *
- * \brief AES block cipher
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_AES_H
-#define POLARSSL_AES_H
-
-#include <string.h>
-
-#define AES_ENCRYPT 1
-#define AES_DECRYPT 0
-
-#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
-#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
-
-/**
- * \brief AES context structure
- */
-typedef struct
-{
- int nr; /*!< number of rounds */
- unsigned long *rk; /*!< AES round keys */
- unsigned long buf[68]; /*!< unaligned data */
-}
-aes_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief AES key schedule (encryption)
- *
- * \param ctx AES context to be initialized
- * \param key encryption key
- * \param keysize must be 128, 192 or 256
- *
- * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
- */
-int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
-
-/**
- * \brief AES key schedule (decryption)
- *
- * \param ctx AES context to be initialized
- * \param key decryption key
- * \param keysize must be 128, 192 or 256
- *
- * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
- */
-int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
-
-/**
- * \brief AES-ECB block encryption/decryption
- *
- * \param ctx AES context
- * \param mode AES_ENCRYPT or AES_DECRYPT
- * \param input 16-byte input block
- * \param output 16-byte output block
- *
- * \return 0 if successful
- */
-int aes_crypt_ecb( aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] );
-
-/**
- * \brief AES-CBC buffer encryption/decryption
- * Length should be a multiple of the block
- * size (16 bytes)
- *
- * \param ctx AES context
- * \param mode AES_ENCRYPT or AES_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
- */
-int aes_crypt_cbc( aes_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief AES-CFB128 buffer encryption/decryption.
- *
- * Note: Due to the nature of CFB you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * both
- * \param ctx AES context
- * \param mode AES_ENCRYPT or AES_DECRYPT
- * \param length length of the input data
- * \param iv_off offset in IV (updated after use)
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if successful
- */
-int aes_crypt_cfb128( aes_context *ctx,
- int mode,
- size_t length,
- size_t *iv_off,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output );
-
-/*
- * \brief AES-CTR buffer encryption/decryption
- *
- * Warning: You have to keep the maximum use of your counter in mind!
- *
- * Note: Due to the nature of CTR you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * \param length The length of the data
- * \param nc_off The offset in the current stream_block (for resuming
- * within current cipher stream). The offset pointer to
- * should be 0 at the start of a stream.
- * \param nonce_counter The 128-bit nonce and counter.
- * \param stream_block The saved stream-block for resuming. Is overwritten
- * by the function.
- * \param input The input data stream
- * \param output The output data stream
- *
- * \return 0 if successful
- */
-int aes_crypt_ctr( aes_context *ctx,
- size_t length,
- size_t *nc_off,
- unsigned char nonce_counter[16],
- unsigned char stream_block[16],
- const unsigned char *input,
- unsigned char *output );
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int aes_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* aes.h */
diff --git a/polarssl/src/include/polarssl/arc4.h b/polarssl/src/include/polarssl/arc4.h
deleted file mode 100644
index 48ad60b..0000000
--- a/polarssl/src/include/polarssl/arc4.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * \file arc4.h
- *
- * \brief The ARCFOUR stream cipher
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_ARC4_H
-#define POLARSSL_ARC4_H
-
-#include <string.h>
-
-/**
- * \brief ARC4 context structure
- */
-typedef struct
-{
- int x; /*!< permutation index */
- int y; /*!< permutation index */
- unsigned char m[256]; /*!< permutation table */
-}
-arc4_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief ARC4 key schedule
- *
- * \param ctx ARC4 context to be initialized
- * \param key the secret key
- * \param keylen length of the key
- */
-void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen );
-
-/**
- * \brief ARC4 cipher function
- *
- * \param ctx ARC4 context
- * \param length length of the input data
- * \param input buffer holding the input data
- * \param output buffer for the output data
- *
- * \return 0 if successful
- */
-int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
- unsigned char *output );
-
-/*
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int arc4_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* arc4.h */
diff --git a/polarssl/src/include/polarssl/asn1.h b/polarssl/src/include/polarssl/asn1.h
deleted file mode 100644
index 893292d..0000000
--- a/polarssl/src/include/polarssl/asn1.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/**
- * \file asn1.h
- *
- * \brief Generic ASN.1 parsing
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_ASN1_H
-#define POLARSSL_ASN1_H
-
-#include "config.h"
-
-#if defined(POLARSSL_BIGNUM_C)
-#include "bignum.h"
-#endif
-
-#include <string.h>
-
-/**
- * \addtogroup asn1_module
- * \{
- */
-
-/**
- * \name ASN1 Error codes
- * These error codes are OR'ed to X509 error codes for
- * higher error granularity.
- * ASN1 is a standard to specify data structures.
- * \{
- */
-#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */
-#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */
-#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */
-#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */
-#define POLARSSL_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */
-#define POLARSSL_ERR_ASN1_MALLOC_FAILED -0x006A /**< Memory allocation failed */
-#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */
-
-/* \} name */
-
-/**
- * \name DER constants
- * These constants comply with DER encoded the ANS1 type tags.
- * DER encoding uses hexadecimal representation.
- * An example DER sequence is:\n
- * - 0x02 -- tag indicating INTEGER
- * - 0x01 -- length in octets
- * - 0x05 -- value
- * Such sequences are typically read into \c ::x509_buf.
- * \{
- */
-#define ASN1_BOOLEAN 0x01
-#define ASN1_INTEGER 0x02
-#define ASN1_BIT_STRING 0x03
-#define ASN1_OCTET_STRING 0x04
-#define ASN1_NULL 0x05
-#define ASN1_OID 0x06
-#define ASN1_UTF8_STRING 0x0C
-#define ASN1_SEQUENCE 0x10
-#define ASN1_SET 0x11
-#define ASN1_PRINTABLE_STRING 0x13
-#define ASN1_T61_STRING 0x14
-#define ASN1_IA5_STRING 0x16
-#define ASN1_UTC_TIME 0x17
-#define ASN1_GENERALIZED_TIME 0x18
-#define ASN1_UNIVERSAL_STRING 0x1C
-#define ASN1_BMP_STRING 0x1E
-#define ASN1_PRIMITIVE 0x00
-#define ASN1_CONSTRUCTED 0x20
-#define ASN1_CONTEXT_SPECIFIC 0x80
-/* \} name */
-/* \} addtogroup asn1_module */
-
-/** Returns the size of the binary string, without the trailing \\0 */
-#define OID_SIZE(x) (sizeof(x) - 1)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \name Functions to parse ASN.1 data structures
- * \{
- */
-
-/**
- * Type-length-value structure that allows for ASN1 using DER.
- */
-typedef struct _asn1_buf
-{
- int tag; /**< ASN1 type, e.g. ASN1_UTF8_STRING. */
- size_t len; /**< ASN1 length, e.g. in octets. */
- unsigned char *p; /**< ASN1 data, e.g. in ASCII. */
-}
-asn1_buf;
-
-/**
- * Container for ASN1 bit strings.
- */
-typedef struct _asn1_bitstring
-{
- size_t len; /**< ASN1 length, e.g. in octets. */
- unsigned char unused_bits; /**< Number of unused bits at the end of the string */
- unsigned char *p; /**< Raw ASN1 data for the bit string */
-}
-asn1_bitstring;
-
-/**
- * Container for a sequence of ASN.1 items
- */
-typedef struct _asn1_sequence
-{
- asn1_buf buf; /**< Buffer containing the given ASN.1 item. */
- struct _asn1_sequence *next; /**< The next entry in the sequence. */
-}
-asn1_sequence;
-
-/**
- * Get the length of an ASN.1 element.
- * Updates the pointer to immediately behind the length.
- *
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param len The variable that will receive the value
- *
- * \return 0 if successful, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching
- * end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is
- * unparseable.
- */
-int asn1_get_len( unsigned char **p,
- const unsigned char *end,
- size_t *len );
-
-/**
- * Get the tag and length of the tag. Check for the requested tag.
- * Updates the pointer to immediately behind the tag and length.
- *
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param len The variable that will receive the length
- * \param tag The expected tag
- *
- * \return 0 if successful, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did
- * not match requested tag, or another specific ASN.1 error code.
- */
-int asn1_get_tag( unsigned char **p,
- const unsigned char *end,
- size_t *len, int tag );
-
-/**
- * Retrieve a boolean ASN.1 tag and its value.
- * Updates the pointer to immediately behind the full tag.
- *
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param val The variable that will receive the value
- *
- * \return 0 if successful or a specific ASN.1 error code.
- */
-int asn1_get_bool( unsigned char **p,
- const unsigned char *end,
- int *val );
-
-/**
- * Retrieve an integer ASN.1 tag and its value.
- * Updates the pointer to immediately behind the full tag.
- *
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param val The variable that will receive the value
- *
- * \return 0 if successful or a specific ASN.1 error code.
- */
-int asn1_get_int( unsigned char **p,
- const unsigned char *end,
- int *val );
-
-/**
- * Retrieve a bitstring ASN.1 tag and its value.
- * Updates the pointer to immediately behind the full tag.
- *
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param bs The variable that will receive the value
- *
- * \return 0 if successful or a specific ASN.1 error code.
- */
-int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
- asn1_bitstring *bs);
-
-/**
- * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
- * Updated the pointer to immediately behind the full sequence tag.
- *
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param cur First variable in the chain to fill
- * \param tag Type of sequence
- *
- * \return 0 if successful or a specific ASN.1 error code.
- */
-int asn1_get_sequence_of( unsigned char **p,
- const unsigned char *end,
- asn1_sequence *cur,
- int tag);
-
-#if defined(POLARSSL_BIGNUM_C)
-/**
- * Retrieve a MPI value from an integer ASN.1 tag.
- * Updates the pointer to immediately behind the full tag.
- *
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param X The MPI that will receive the value
- *
- * \return 0 if successful or a specific ASN.1 or MPI error code.
- */
-int asn1_get_mpi( unsigned char **p,
- const unsigned char *end,
- mpi *X );
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* asn1.h */
diff --git a/polarssl/src/include/polarssl/asn1write.h b/polarssl/src/include/polarssl/asn1write.h
deleted file mode 100644
index 52b9baa..0000000
--- a/polarssl/src/include/polarssl/asn1write.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * \file asn1write.h
- *
- * \brief ASN.1 buffer writing functionality
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_ASN1_WRITE_H
-#define POLARSSL_ASN1_WRITE_H
-
-#include "asn1.h"
-
-#define ASN1_CHK_ADD(g, f) if( ( ret = f ) < 0 ) return( ret ); else g += ret
-
-int asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
-int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag );
-int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X );
-int asn1_write_null( unsigned char **p, unsigned char *start );
-int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid );
-int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, char *algorithm_oid );
-int asn1_write_int( unsigned char **p, unsigned char *start, int val );
-int asn1_write_printable_string( unsigned char **p, unsigned char *start,
- char *text );
-int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
- char *text );
-
-#endif /* POLARSSL_ASN1_WRITE_H */
diff --git a/polarssl/src/include/polarssl/base64.h b/polarssl/src/include/polarssl/base64.h
deleted file mode 100644
index 883215d..0000000
--- a/polarssl/src/include/polarssl/base64.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * \file base64.h
- *
- * \brief RFC 1521 base64 encoding/decoding
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_BASE64_H
-#define POLARSSL_BASE64_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */
-#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Encode a buffer into base64 format
- *
- * \param dst destination buffer
- * \param dlen size of the buffer
- * \param src source buffer
- * \param slen amount of data to be encoded
- *
- * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
- * *dlen is always updated to reflect the amount
- * of data that has (or would have) been written.
- *
- * \note Call this function with *dlen = 0 to obtain the
- * required buffer size in *dlen
- */
-int base64_encode( unsigned char *dst, size_t *dlen,
- const unsigned char *src, size_t slen );
-
-/**
- * \brief Decode a base64-formatted buffer
- *
- * \param dst destination buffer
- * \param dlen size of the buffer
- * \param src source buffer
- * \param slen amount of data to be decoded
- *
- * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
- * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not
- * correct. *dlen is always updated to reflect the amount
- * of data that has (or would have) been written.
- *
- * \note Call this function with *dlen = 0 to obtain the
- * required buffer size in *dlen
- */
-int base64_decode( unsigned char *dst, size_t *dlen,
- const unsigned char *src, size_t slen );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int base64_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* base64.h */
diff --git a/polarssl/src/include/polarssl/bignum.h b/polarssl/src/include/polarssl/bignum.h
deleted file mode 100644
index ad03308..0000000
--- a/polarssl/src/include/polarssl/bignum.h
+++ /dev/null
@@ -1,632 +0,0 @@
-/**
- * \file bignum.h
- *
- * \brief Multi-precision integer library
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_BIGNUM_H
-#define POLARSSL_BIGNUM_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include "config.h"
-
-#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
-#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
-#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
-#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */
-#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
-#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
-#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
-#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */
-
-#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
-
-/*
- * Maximum size MPIs are allowed to grow to in number of limbs.
- */
-#define POLARSSL_MPI_MAX_LIMBS 10000
-
-/*
- * Maximum window size used for modular exponentiation. Default: 6
- * Minimum value: 1. Maximum value: 6.
- *
- * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used
- * for the sliding window calculation. (So 64 by default)
- *
- * Reduction in size, reduces speed.
- */
-#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
-
-/*
- * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
- * ( Default: 512 bytes => 4096 bits )
- *
- * Note: Calculations can results temporarily in larger MPIs. So the number
- * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher.
- */
-#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */
-#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */
-
-/*
- * When reading from files with mpi_read_file() the buffer should have space
- * for a (short) label, the MPI (in the provided radix), the newline
- * characters and the '\0'.
- *
- * By default we assume at least a 10 char label, a minimum radix of 10
- * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
- */
-#define POLARSSL_MPI_READ_BUFFER_SIZE 1250
-
-/*
- * Define the base integer type, architecture-wise
- */
-#if defined(POLARSSL_HAVE_INT8)
-typedef signed char t_sint;
-typedef unsigned char t_uint;
-typedef unsigned short t_udbl;
-#else
-#if defined(POLARSSL_HAVE_INT16)
-typedef signed short t_sint;
-typedef unsigned short t_uint;
-typedef unsigned long t_udbl;
-#else
- typedef signed long t_sint;
- typedef unsigned long t_uint;
- #if defined(_MSC_VER) && defined(_M_IX86)
- typedef unsigned __int64 t_udbl;
- #else
- #if defined(__GNUC__) && ( \
- defined(__amd64__) || defined(__x86_64__) || \
- defined(__ppc64__) || defined(__powerpc64__) || \
- defined(__ia64__) || defined(__alpha__) || \
- (defined(__sparc__) && defined(__arch64__)) || \
- defined(__s390x__) )
- typedef unsigned int t_udbl __attribute__((mode(TI)));
- #define POLARSSL_HAVE_LONGLONG
- #else
- #if defined(POLARSSL_HAVE_LONGLONG)
- typedef unsigned long long t_udbl;
- #endif
- #endif
- #endif
-#endif
-#endif
-
-/**
- * \brief MPI structure
- */
-typedef struct
-{
- int s; /*!< integer sign */
- size_t n; /*!< total # of limbs */
- t_uint *p; /*!< pointer to limbs */
-}
-mpi;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Initialize one MPI
- *
- * \param X One MPI to initialize.
- */
-void mpi_init( mpi *X );
-
-/**
- * \brief Unallocate one MPI
- *
- * \param X One MPI to unallocate.
- */
-void mpi_free( mpi *X );
-
-/**
- * \brief Enlarge to the specified number of limbs
- *
- * \param X MPI to grow
- * \param nblimbs The target number of limbs
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_grow( mpi *X, size_t nblimbs );
-
-/**
- * \brief Copy the contents of Y into X
- *
- * \param X Destination MPI
- * \param Y Source MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_copy( mpi *X, const mpi *Y );
-
-/**
- * \brief Swap the contents of X and Y
- *
- * \param X First MPI value
- * \param Y Second MPI value
- */
-void mpi_swap( mpi *X, mpi *Y );
-
-/**
- * \brief Set value from integer
- *
- * \param X MPI to set
- * \param z Value to use
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_lset( mpi *X, t_sint z );
-
-/*
- * \brief Get a specific bit from X
- *
- * \param X MPI to use
- * \param pos Zero-based index of the bit in X
- *
- * \return Either a 0 or a 1
- */
-int mpi_get_bit( mpi *X, size_t pos );
-
-/*
- * \brief Set a bit of X to a specific value of 0 or 1
- *
- * \note Will grow X if necessary to set a bit to 1 in a not yet
- * existing limb. Will not grow if bit should be set to 0
- *
- * \param X MPI to use
- * \param pos Zero-based index of the bit in X
- * \param val The value to set the bit to (0 or 1)
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
- */
-int mpi_set_bit( mpi *X, size_t pos, unsigned char val );
-
-/**
- * \brief Return the number of least significant bits
- *
- * \param X MPI to use
- */
-size_t mpi_lsb( const mpi *X );
-
-/**
- * \brief Return the number of most significant bits
- *
- * \param X MPI to use
- */
-size_t mpi_msb( const mpi *X );
-
-/**
- * \brief Return the total size in bytes
- *
- * \param X MPI to use
- */
-size_t mpi_size( const mpi *X );
-
-/**
- * \brief Import from an ASCII string
- *
- * \param X Destination MPI
- * \param radix Input numeric base
- * \param s Null-terminated string buffer
- *
- * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
- */
-int mpi_read_string( mpi *X, int radix, const char *s );
-
-/**
- * \brief Export into an ASCII string
- *
- * \param X Source MPI
- * \param radix Output numeric base
- * \param s String buffer
- * \param slen String buffer size
- *
- * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code.
- * *slen is always updated to reflect the amount
- * of data that has (or would have) been written.
- *
- * \note Call this function with *slen = 0 to obtain the
- * minimum required buffer size in *slen.
- */
-int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );
-
-/**
- * \brief Read X from an opened file
- *
- * \param X Destination MPI
- * \param radix Input numeric base
- * \param fin Input file handle
- *
- * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if
- * the file read buffer is too small or a
- * POLARSSL_ERR_MPI_XXX error code
- */
-int mpi_read_file( mpi *X, int radix, FILE *fin );
-
-/**
- * \brief Write X into an opened file, or stdout if fout is NULL
- *
- * \param p Prefix, can be NULL
- * \param X Source MPI
- * \param radix Output numeric base
- * \param fout Output file handle (can be NULL)
- *
- * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
- *
- * \note Set fout == NULL to print X on the console.
- */
-int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
-
-/**
- * \brief Import X from unsigned binary data, big endian
- *
- * \param X Destination MPI
- * \param buf Input buffer
- * \param buflen Input buffer size
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
-
-/**
- * \brief Export X into unsigned binary data, big endian
- *
- * \param X Source MPI
- * \param buf Output buffer
- * \param buflen Output buffer size
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
- */
-int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen );
-
-/**
- * \brief Left-shift: X <<= count
- *
- * \param X MPI to shift
- * \param count Amount to shift
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_shift_l( mpi *X, size_t count );
-
-/**
- * \brief Right-shift: X >>= count
- *
- * \param X MPI to shift
- * \param count Amount to shift
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_shift_r( mpi *X, size_t count );
-
-/**
- * \brief Compare unsigned values
- *
- * \param X Left-hand MPI
- * \param Y Right-hand MPI
- *
- * \return 1 if |X| is greater than |Y|,
- * -1 if |X| is lesser than |Y| or
- * 0 if |X| is equal to |Y|
- */
-int mpi_cmp_abs( const mpi *X, const mpi *Y );
-
-/**
- * \brief Compare signed values
- *
- * \param X Left-hand MPI
- * \param Y Right-hand MPI
- *
- * \return 1 if X is greater than Y,
- * -1 if X is lesser than Y or
- * 0 if X is equal to Y
- */
-int mpi_cmp_mpi( const mpi *X, const mpi *Y );
-
-/**
- * \brief Compare signed values
- *
- * \param X Left-hand MPI
- * \param z The integer value to compare to
- *
- * \return 1 if X is greater than z,
- * -1 if X is lesser than z or
- * 0 if X is equal to z
- */
-int mpi_cmp_int( const mpi *X, t_sint z );
-
-/**
- * \brief Unsigned addition: X = |A| + |B|
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief Unsigned substraction: X = |A| - |B|
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
- */
-int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief Signed addition: X = A + B
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief Signed substraction: X = A - B
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief Signed addition: X = A + b
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param b The integer value to add
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_add_int( mpi *X, const mpi *A, t_sint b );
-
-/**
- * \brief Signed substraction: X = A - b
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param b The integer value to subtract
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_sub_int( mpi *X, const mpi *A, t_sint b );
-
-/**
- * \brief Baseline multiplication: X = A * B
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief Baseline multiplication: X = A * b
- * Note: b is an unsigned integer type, thus
- * Negative values of b are ignored.
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param b The integer value to multiply with
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_mul_int( mpi *X, const mpi *A, t_sint b );
-
-/**
- * \brief Division by mpi: A = Q * B + R
- *
- * \param Q Destination MPI for the quotient
- * \param R Destination MPI for the rest value
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
- *
- * \note Either Q or R can be NULL.
- */
-int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
-
-/**
- * \brief Division by int: A = Q * b + R
- *
- * \param Q Destination MPI for the quotient
- * \param R Destination MPI for the rest value
- * \param A Left-hand MPI
- * \param b Integer to divide by
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
- *
- * \note Either Q or R can be NULL.
- */
-int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b );
-
-/**
- * \brief Modulo: R = A mod B
- *
- * \param R Destination MPI for the rest value
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
- * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
- */
-int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
-
-/**
- * \brief Modulo: r = A mod b
- *
- * \param r Destination t_uint
- * \param A Left-hand MPI
- * \param b Integer to divide by
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
- * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
- */
-int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
-
-/**
- * \brief Sliding-window exponentiation: X = A^E mod N
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param E Exponent MPI
- * \param N Modular MPI
- * \param _RR Speed-up MPI used for recalculations
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
- *
- * \note _RR is used to avoid re-computing R*R mod N across
- * multiple calls, which speeds up things a bit. It can
- * be set to NULL if the extra performance is unneeded.
- */
-int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
-
-/**
- * \brief Fill an MPI X with size bytes of random
- *
- * \param X Destination MPI
- * \param size Size in bytes
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_fill_random( mpi *X, size_t size,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
-
-/**
- * \brief Greatest common divisor: G = gcd(A, B)
- *
- * \param G Destination MPI
- * \param A Left-hand MPI
- * \param B Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- */
-int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
-
-/**
- * \brief Modular inverse: X = A^-1 mod N
- *
- * \param X Destination MPI
- * \param A Left-hand MPI
- * \param N Right-hand MPI
- *
- * \return 0 if successful,
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
- POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
- */
-int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
-
-/**
- * \brief Miller-Rabin primality test
- *
- * \param X MPI to check
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- *
- * \return 0 if successful (probably prime),
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
- */
-int mpi_is_prime( mpi *X,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
-
-/**
- * \brief Prime number generation
- *
- * \param X Destination MPI
- * \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS )
- * \param dh_flag If 1, then (X-1)/2 will be prime too
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- *
- * \return 0 if successful (probably prime),
- * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
- */
-int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int mpi_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* bignum.h */
diff --git a/polarssl/src/include/polarssl/bn_mul.h b/polarssl/src/include/polarssl/bn_mul.h
deleted file mode 100644
index a6a2c65..0000000
--- a/polarssl/src/include/polarssl/bn_mul.h
+++ /dev/null
@@ -1,742 +0,0 @@
-/**
- * \file bn_mul.h
- *
- * \brief Multi-precision integer library
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * Multiply source vector [s] with b, add result
- * to destination vector [d] and set carry c.
- *
- * Currently supports:
- *
- * . IA-32 (386+) . AMD64 / EM64T
- * . IA-32 (SSE2) . Motorola 68000
- * . PowerPC, 32-bit . MicroBlaze
- * . PowerPC, 64-bit . TriCore
- * . SPARC v8 . ARM v3+
- * . Alpha . MIPS32
- * . C, longlong . C, generic
- */
-#ifndef POLARSSL_BN_MUL_H
-#define POLARSSL_BN_MUL_H
-
-#include "bignum.h"
-
-#if defined(POLARSSL_HAVE_ASM)
-
-#if defined(__GNUC__)
-#if defined(__i386__)
-
-#define MULADDC_INIT \
- asm( " \
- movl %%ebx, %0; \
- movl %5, %%esi; \
- movl %6, %%edi; \
- movl %7, %%ecx; \
- movl %8, %%ebx; \
- "
-
-#define MULADDC_CORE \
- " \
- lodsl; \
- mull %%ebx; \
- addl %%ecx, %%eax; \
- adcl $0, %%edx; \
- addl (%%edi), %%eax; \
- adcl $0, %%edx; \
- movl %%edx, %%ecx; \
- stosl; \
- "
-
-#if defined(POLARSSL_HAVE_SSE2)
-
-#define MULADDC_HUIT \
- " \
- movd %%ecx, %%mm1; \
- movd %%ebx, %%mm0; \
- movd (%%edi), %%mm3; \
- paddq %%mm3, %%mm1; \
- movd (%%esi), %%mm2; \
- pmuludq %%mm0, %%mm2; \
- movd 4(%%esi), %%mm4; \
- pmuludq %%mm0, %%mm4; \
- movd 8(%%esi), %%mm6; \
- pmuludq %%mm0, %%mm6; \
- movd 12(%%esi), %%mm7; \
- pmuludq %%mm0, %%mm7; \
- paddq %%mm2, %%mm1; \
- movd 4(%%edi), %%mm3; \
- paddq %%mm4, %%mm3; \
- movd 8(%%edi), %%mm5; \
- paddq %%mm6, %%mm5; \
- movd 12(%%edi), %%mm4; \
- paddq %%mm4, %%mm7; \
- movd %%mm1, (%%edi); \
- movd 16(%%esi), %%mm2; \
- pmuludq %%mm0, %%mm2; \
- psrlq $32, %%mm1; \
- movd 20(%%esi), %%mm4; \
- pmuludq %%mm0, %%mm4; \
- paddq %%mm3, %%mm1; \
- movd 24(%%esi), %%mm6; \
- pmuludq %%mm0, %%mm6; \
- movd %%mm1, 4(%%edi); \
- psrlq $32, %%mm1; \
- movd 28(%%esi), %%mm3; \
- pmuludq %%mm0, %%mm3; \
- paddq %%mm5, %%mm1; \
- movd 16(%%edi), %%mm5; \
- paddq %%mm5, %%mm2; \
- movd %%mm1, 8(%%edi); \
- psrlq $32, %%mm1; \
- paddq %%mm7, %%mm1; \
- movd 20(%%edi), %%mm5; \
- paddq %%mm5, %%mm4; \
- movd %%mm1, 12(%%edi); \
- psrlq $32, %%mm1; \
- paddq %%mm2, %%mm1; \
- movd 24(%%edi), %%mm5; \
- paddq %%mm5, %%mm6; \
- movd %%mm1, 16(%%edi); \
- psrlq $32, %%mm1; \
- paddq %%mm4, %%mm1; \
- movd 28(%%edi), %%mm5; \
- paddq %%mm5, %%mm3; \
- movd %%mm1, 20(%%edi); \
- psrlq $32, %%mm1; \
- paddq %%mm6, %%mm1; \
- movd %%mm1, 24(%%edi); \
- psrlq $32, %%mm1; \
- paddq %%mm3, %%mm1; \
- movd %%mm1, 28(%%edi); \
- addl $32, %%edi; \
- addl $32, %%esi; \
- psrlq $32, %%mm1; \
- movd %%mm1, %%ecx; \
- "
-
-#define MULADDC_STOP \
- " \
- emms; \
- movl %4, %%ebx; \
- movl %%ecx, %1; \
- movl %%edi, %2; \
- movl %%esi, %3; \
- " \
- : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
- : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
- : "eax", "ecx", "edx", "esi", "edi" \
- );
-
-#else
-
-#define MULADDC_STOP \
- " \
- movl %4, %%ebx; \
- movl %%ecx, %1; \
- movl %%edi, %2; \
- movl %%esi, %3; \
- " \
- : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
- : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
- : "eax", "ecx", "edx", "esi", "edi" \
- );
-#endif /* SSE2 */
-#endif /* i386 */
-
-#if defined(__amd64__) || defined (__x86_64__)
-
-#define MULADDC_INIT \
- asm( "movq %0, %%rsi " :: "m" (s)); \
- asm( "movq %0, %%rdi " :: "m" (d)); \
- asm( "movq %0, %%rcx " :: "m" (c)); \
- asm( "movq %0, %%rbx " :: "m" (b)); \
- asm( "xorq %r8, %r8 " );
-
-#define MULADDC_CORE \
- asm( "movq (%rsi),%rax " ); \
- asm( "mulq %rbx " ); \
- asm( "addq $8, %rsi " ); \
- asm( "addq %rcx, %rax " ); \
- asm( "movq %r8, %rcx " ); \
- asm( "adcq $0, %rdx " ); \
- asm( "nop " ); \
- asm( "addq %rax, (%rdi) " ); \
- asm( "adcq %rdx, %rcx " ); \
- asm( "addq $8, %rdi " );
-
-#define MULADDC_STOP \
- asm( "movq %%rcx, %0 " : "=m" (c)); \
- asm( "movq %%rdi, %0 " : "=m" (d)); \
- asm( "movq %%rsi, %0 " : "=m" (s) :: \
- "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
-
-#endif /* AMD64 */
-
-#if defined(__mc68020__) || defined(__mcpu32__)
-
-#define MULADDC_INIT \
- asm( "movl %0, %%a2 " :: "m" (s)); \
- asm( "movl %0, %%a3 " :: "m" (d)); \
- asm( "movl %0, %%d3 " :: "m" (c)); \
- asm( "movl %0, %%d2 " :: "m" (b)); \
- asm( "moveq #0, %d0 " );
-
-#define MULADDC_CORE \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d4:%d1 " ); \
- asm( "addl %d3, %d1 " ); \
- asm( "addxl %d0, %d4 " ); \
- asm( "moveq #0, %d3 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "addxl %d4, %d3 " );
-
-#define MULADDC_STOP \
- asm( "movl %%d3, %0 " : "=m" (c)); \
- asm( "movl %%a3, %0 " : "=m" (d)); \
- asm( "movl %%a2, %0 " : "=m" (s) :: \
- "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
-
-#define MULADDC_HUIT \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d4:%d1 " ); \
- asm( "addxl %d3, %d1 " ); \
- asm( "addxl %d0, %d4 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d3:%d1 " ); \
- asm( "addxl %d4, %d1 " ); \
- asm( "addxl %d0, %d3 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d4:%d1 " ); \
- asm( "addxl %d3, %d1 " ); \
- asm( "addxl %d0, %d4 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d3:%d1 " ); \
- asm( "addxl %d4, %d1 " ); \
- asm( "addxl %d0, %d3 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d4:%d1 " ); \
- asm( "addxl %d3, %d1 " ); \
- asm( "addxl %d0, %d4 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d3:%d1 " ); \
- asm( "addxl %d4, %d1 " ); \
- asm( "addxl %d0, %d3 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d4:%d1 " ); \
- asm( "addxl %d3, %d1 " ); \
- asm( "addxl %d0, %d4 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "movel %a2@+, %d1 " ); \
- asm( "mulul %d2, %d3:%d1 " ); \
- asm( "addxl %d4, %d1 " ); \
- asm( "addxl %d0, %d3 " ); \
- asm( "addl %d1, %a3@+ " ); \
- asm( "addxl %d0, %d3 " );
-
-#endif /* MC68000 */
-
-#if defined(__powerpc__) || defined(__ppc__)
-#if defined(__powerpc64__) || defined(__ppc64__)
-
-#if defined(__MACH__) && defined(__APPLE__)
-
-#define MULADDC_INIT \
- asm( "ld r3, %0 " :: "m" (s)); \
- asm( "ld r4, %0 " :: "m" (d)); \
- asm( "ld r5, %0 " :: "m" (c)); \
- asm( "ld r6, %0 " :: "m" (b)); \
- asm( "addi r3, r3, -8 " ); \
- asm( "addi r4, r4, -8 " ); \
- asm( "addic r5, r5, 0 " );
-
-#define MULADDC_CORE \
- asm( "ldu r7, 8(r3) " ); \
- asm( "mulld r8, r7, r6 " ); \
- asm( "mulhdu r9, r7, r6 " ); \
- asm( "adde r8, r8, r5 " ); \
- asm( "ld r7, 8(r4) " ); \
- asm( "addze r5, r9 " ); \
- asm( "addc r8, r8, r7 " ); \
- asm( "stdu r8, 8(r4) " );
-
-#define MULADDC_STOP \
- asm( "addze r5, r5 " ); \
- asm( "addi r4, r4, 8 " ); \
- asm( "addi r3, r3, 8 " ); \
- asm( "std r5, %0 " : "=m" (c)); \
- asm( "std r4, %0 " : "=m" (d)); \
- asm( "std r3, %0 " : "=m" (s) :: \
- "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
-
-#define MULADDC_INIT \
- asm( "ld %%r3, %0 " :: "m" (s)); \
- asm( "ld %%r4, %0 " :: "m" (d)); \
- asm( "ld %%r5, %0 " :: "m" (c)); \
- asm( "ld %%r6, %0 " :: "m" (b)); \
- asm( "addi %r3, %r3, -8 " ); \
- asm( "addi %r4, %r4, -8 " ); \
- asm( "addic %r5, %r5, 0 " );
-
-#define MULADDC_CORE \
- asm( "ldu %r7, 8(%r3) " ); \
- asm( "mulld %r8, %r7, %r6 " ); \
- asm( "mulhdu %r9, %r7, %r6 " ); \
- asm( "adde %r8, %r8, %r5 " ); \
- asm( "ld %r7, 8(%r4) " ); \
- asm( "addze %r5, %r9 " ); \
- asm( "addc %r8, %r8, %r7 " ); \
- asm( "stdu %r8, 8(%r4) " );
-
-#define MULADDC_STOP \
- asm( "addze %r5, %r5 " ); \
- asm( "addi %r4, %r4, 8 " ); \
- asm( "addi %r3, %r3, 8 " ); \
- asm( "std %%r5, %0 " : "=m" (c)); \
- asm( "std %%r4, %0 " : "=m" (d)); \
- asm( "std %%r3, %0 " : "=m" (s) :: \
- "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#endif
-
-#else /* PPC32 */
-
-#if defined(__MACH__) && defined(__APPLE__)
-
-#define MULADDC_INIT \
- asm( "lwz r3, %0 " :: "m" (s)); \
- asm( "lwz r4, %0 " :: "m" (d)); \
- asm( "lwz r5, %0 " :: "m" (c)); \
- asm( "lwz r6, %0 " :: "m" (b)); \
- asm( "addi r3, r3, -4 " ); \
- asm( "addi r4, r4, -4 " ); \
- asm( "addic r5, r5, 0 " );
-
-#define MULADDC_CORE \
- asm( "lwzu r7, 4(r3) " ); \
- asm( "mullw r8, r7, r6 " ); \
- asm( "mulhwu r9, r7, r6 " ); \
- asm( "adde r8, r8, r5 " ); \
- asm( "lwz r7, 4(r4) " ); \
- asm( "addze r5, r9 " ); \
- asm( "addc r8, r8, r7 " ); \
- asm( "stwu r8, 4(r4) " );
-
-#define MULADDC_STOP \
- asm( "addze r5, r5 " ); \
- asm( "addi r4, r4, 4 " ); \
- asm( "addi r3, r3, 4 " ); \
- asm( "stw r5, %0 " : "=m" (c)); \
- asm( "stw r4, %0 " : "=m" (d)); \
- asm( "stw r3, %0 " : "=m" (s) :: \
- "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
-
-#define MULADDC_INIT \
- asm( "lwz %%r3, %0 " :: "m" (s)); \
- asm( "lwz %%r4, %0 " :: "m" (d)); \
- asm( "lwz %%r5, %0 " :: "m" (c)); \
- asm( "lwz %%r6, %0 " :: "m" (b)); \
- asm( "addi %r3, %r3, -4 " ); \
- asm( "addi %r4, %r4, -4 " ); \
- asm( "addic %r5, %r5, 0 " );
-
-#define MULADDC_CORE \
- asm( "lwzu %r7, 4(%r3) " ); \
- asm( "mullw %r8, %r7, %r6 " ); \
- asm( "mulhwu %r9, %r7, %r6 " ); \
- asm( "adde %r8, %r8, %r5 " ); \
- asm( "lwz %r7, 4(%r4) " ); \
- asm( "addze %r5, %r9 " ); \
- asm( "addc %r8, %r8, %r7 " ); \
- asm( "stwu %r8, 4(%r4) " );
-
-#define MULADDC_STOP \
- asm( "addze %r5, %r5 " ); \
- asm( "addi %r4, %r4, 4 " ); \
- asm( "addi %r3, %r3, 4 " ); \
- asm( "stw %%r5, %0 " : "=m" (c)); \
- asm( "stw %%r4, %0 " : "=m" (d)); \
- asm( "stw %%r3, %0 " : "=m" (s) :: \
- "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#endif
-
-#endif /* PPC32 */
-#endif /* PPC64 */
-
-#if defined(__sparc__)
-
-#define MULADDC_INIT \
- asm( "ld %0, %%o0 " :: "m" (s)); \
- asm( "ld %0, %%o1 " :: "m" (d)); \
- asm( "ld %0, %%o2 " :: "m" (c)); \
- asm( "ld %0, %%o3 " :: "m" (b));
-
-#define MULADDC_CORE \
- asm( "ld [%o0], %o4 " ); \
- asm( "inc 4, %o0 " ); \
- asm( "ld [%o1], %o5 " ); \
- asm( "umul %o3, %o4, %o4 " ); \
- asm( "addcc %o4, %o2, %o4 " ); \
- asm( "rd %y, %g1 " ); \
- asm( "addx %g1, 0, %g1 " ); \
- asm( "addcc %o4, %o5, %o4 " ); \
- asm( "st %o4, [%o1] " ); \
- asm( "addx %g1, 0, %o2 " ); \
- asm( "inc 4, %o1 " );
-
-#define MULADDC_STOP \
- asm( "st %%o2, %0 " : "=m" (c)); \
- asm( "st %%o1, %0 " : "=m" (d)); \
- asm( "st %%o0, %0 " : "=m" (s) :: \
- "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
-
-#endif /* SPARCv8 */
-
-#if defined(__microblaze__) || defined(microblaze)
-
-#define MULADDC_INIT \
- asm( "lwi r3, %0 " :: "m" (s)); \
- asm( "lwi r4, %0 " :: "m" (d)); \
- asm( "lwi r5, %0 " :: "m" (c)); \
- asm( "lwi r6, %0 " :: "m" (b)); \
- asm( "andi r7, r6, 0xffff" ); \
- asm( "bsrli r6, r6, 16 " );
-
-#define MULADDC_CORE \
- asm( "lhui r8, r3, 0 " ); \
- asm( "addi r3, r3, 2 " ); \
- asm( "lhui r9, r3, 0 " ); \
- asm( "addi r3, r3, 2 " ); \
- asm( "mul r10, r9, r6 " ); \
- asm( "mul r11, r8, r7 " ); \
- asm( "mul r12, r9, r7 " ); \
- asm( "mul r13, r8, r6 " ); \
- asm( "bsrli r8, r10, 16 " ); \
- asm( "bsrli r9, r11, 16 " ); \
- asm( "add r13, r13, r8 " ); \
- asm( "add r13, r13, r9 " ); \
- asm( "bslli r10, r10, 16 " ); \
- asm( "bslli r11, r11, 16 " ); \
- asm( "add r12, r12, r10 " ); \
- asm( "addc r13, r13, r0 " ); \
- asm( "add r12, r12, r11 " ); \
- asm( "addc r13, r13, r0 " ); \
- asm( "lwi r10, r4, 0 " ); \
- asm( "add r12, r12, r10 " ); \
- asm( "addc r13, r13, r0 " ); \
- asm( "add r12, r12, r5 " ); \
- asm( "addc r5, r13, r0 " ); \
- asm( "swi r12, r4, 0 " ); \
- asm( "addi r4, r4, 4 " );
-
-#define MULADDC_STOP \
- asm( "swi r5, %0 " : "=m" (c)); \
- asm( "swi r4, %0 " : "=m" (d)); \
- asm( "swi r3, %0 " : "=m" (s) :: \
- "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
- "r9", "r10", "r11", "r12", "r13" );
-
-#endif /* MicroBlaze */
-
-#if defined(__tricore__)
-
-#define MULADDC_INIT \
- asm( "ld.a %%a2, %0 " :: "m" (s)); \
- asm( "ld.a %%a3, %0 " :: "m" (d)); \
- asm( "ld.w %%d4, %0 " :: "m" (c)); \
- asm( "ld.w %%d1, %0 " :: "m" (b)); \
- asm( "xor %d5, %d5 " );
-
-#define MULADDC_CORE \
- asm( "ld.w %d0, [%a2+] " ); \
- asm( "madd.u %e2, %e4, %d0, %d1 " ); \
- asm( "ld.w %d0, [%a3] " ); \
- asm( "addx %d2, %d2, %d0 " ); \
- asm( "addc %d3, %d3, 0 " ); \
- asm( "mov %d4, %d3 " ); \
- asm( "st.w [%a3+], %d2 " );
-
-#define MULADDC_STOP \
- asm( "st.w %0, %%d4 " : "=m" (c)); \
- asm( "st.a %0, %%a3 " : "=m" (d)); \
- asm( "st.a %0, %%a2 " : "=m" (s) :: \
- "d0", "d1", "e2", "d4", "a2", "a3" );
-
-#endif /* TriCore */
-
-#if defined(__arm__)
-
-#if !defined(__thumb__)
-
-#define MULADDC_INIT \
- asm( "ldr r0, %0 " :: "m" (s)); \
- asm( "ldr r1, %0 " :: "m" (d)); \
- asm( "ldr r2, %0 " :: "m" (c)); \
- asm( "ldr r3, %0 " :: "m" (b));
-
-#define MULADDC_CORE \
- asm( "ldr r4, [r0], #4 " ); \
- asm( "mov r5, #0 " ); \
- asm( "ldr r6, [r1] " ); \
- asm( "umlal r2, r5, r3, r4 " ); \
- asm( "adds r7, r6, r2 " ); \
- asm( "adc r2, r5, #0 " ); \
- asm( "str r7, [r1], #4 " );
-
-#define MULADDC_STOP \
- asm( "str r2, %0 " : "=m" (c)); \
- asm( "str r1, %0 " : "=m" (d)); \
- asm( "str r0, %0 " : "=m" (s) :: \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
-
-#endif /* Thumb */
-
-#endif /* ARMv3 */
-
-#if defined(__alpha__)
-
-#define MULADDC_INIT \
- asm( "ldq $1, %0 " :: "m" (s)); \
- asm( "ldq $2, %0 " :: "m" (d)); \
- asm( "ldq $3, %0 " :: "m" (c)); \
- asm( "ldq $4, %0 " :: "m" (b));
-
-#define MULADDC_CORE \
- asm( "ldq $6, 0($1) " ); \
- asm( "addq $1, 8, $1 " ); \
- asm( "mulq $6, $4, $7 " ); \
- asm( "umulh $6, $4, $6 " ); \
- asm( "addq $7, $3, $7 " ); \
- asm( "cmpult $7, $3, $3 " ); \
- asm( "ldq $5, 0($2) " ); \
- asm( "addq $7, $5, $7 " ); \
- asm( "cmpult $7, $5, $5 " ); \
- asm( "stq $7, 0($2) " ); \
- asm( "addq $2, 8, $2 " ); \
- asm( "addq $6, $3, $3 " ); \
- asm( "addq $5, $3, $3 " );
-
-#define MULADDC_STOP \
- asm( "stq $3, %0 " : "=m" (c)); \
- asm( "stq $2, %0 " : "=m" (d)); \
- asm( "stq $1, %0 " : "=m" (s) :: \
- "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
-
-#endif /* Alpha */
-
-#if defined(__mips__)
-
-#define MULADDC_INIT \
- asm( "lw $10, %0 " :: "m" (s)); \
- asm( "lw $11, %0 " :: "m" (d)); \
- asm( "lw $12, %0 " :: "m" (c)); \
- asm( "lw $13, %0 " :: "m" (b));
-
-#define MULADDC_CORE \
- asm( "lw $14, 0($10) " ); \
- asm( "multu $13, $14 " ); \
- asm( "addi $10, $10, 4 " ); \
- asm( "mflo $14 " ); \
- asm( "mfhi $9 " ); \
- asm( "addu $14, $12, $14 " ); \
- asm( "lw $15, 0($11) " ); \
- asm( "sltu $12, $14, $12 " ); \
- asm( "addu $15, $14, $15 " ); \
- asm( "sltu $14, $15, $14 " ); \
- asm( "addu $12, $12, $9 " ); \
- asm( "sw $15, 0($11) " ); \
- asm( "addu $12, $12, $14 " ); \
- asm( "addi $11, $11, 4 " );
-
-#define MULADDC_STOP \
- asm( "sw $12, %0 " : "=m" (c)); \
- asm( "sw $11, %0 " : "=m" (d)); \
- asm( "sw $10, %0 " : "=m" (s) :: \
- "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
-
-#endif /* MIPS */
-#endif /* GNUC */
-
-#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
-
-#define MULADDC_INIT \
- __asm mov esi, s \
- __asm mov edi, d \
- __asm mov ecx, c \
- __asm mov ebx, b
-
-#define MULADDC_CORE \
- __asm lodsd \
- __asm mul ebx \
- __asm add eax, ecx \
- __asm adc edx, 0 \
- __asm add eax, [edi] \
- __asm adc edx, 0 \
- __asm mov ecx, edx \
- __asm stosd
-
-#if defined(POLARSSL_HAVE_SSE2)
-
-#define EMIT __asm _emit
-
-#define MULADDC_HUIT \
- EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
- EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
- EMIT 0x0F EMIT 0x6E EMIT 0x1F \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
- EMIT 0x0F EMIT 0x6E EMIT 0x16 \
- EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
- EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
- EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
- EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
- EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
- EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
- EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
- EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
- EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
- EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
- EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
- EMIT 0x0F EMIT 0x7E EMIT 0x0F \
- EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
- EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
- EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
- EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
- EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
- EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
- EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
- EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
- EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
- EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
- EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
- EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
- EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
- EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
- EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
- EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
- EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
- EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
- EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
- EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
- EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
- EMIT 0x0F EMIT 0x7E EMIT 0xC9
-
-#define MULADDC_STOP \
- EMIT 0x0F EMIT 0x77 \
- __asm mov c, ecx \
- __asm mov d, edi \
- __asm mov s, esi \
-
-#else
-
-#define MULADDC_STOP \
- __asm mov c, ecx \
- __asm mov d, edi \
- __asm mov s, esi \
-
-#endif /* SSE2 */
-#endif /* MSVC */
-
-#endif /* POLARSSL_HAVE_ASM */
-
-#if !defined(MULADDC_CORE)
-#if defined(POLARSSL_HAVE_LONGLONG)
-
-#define MULADDC_INIT \
-{ \
- t_udbl r; \
- t_uint r0, r1;
-
-#define MULADDC_CORE \
- r = *(s++) * (t_udbl) b; \
- r0 = r; \
- r1 = r >> biL; \
- r0 += c; r1 += (r0 < c); \
- r0 += *d; r1 += (r0 < *d); \
- c = r1; *(d++) = r0;
-
-#define MULADDC_STOP \
-}
-
-#else
-#define MULADDC_INIT \
-{ \
- t_uint s0, s1, b0, b1; \
- t_uint r0, r1, rx, ry; \
- b0 = ( b << biH ) >> biH; \
- b1 = ( b >> biH );
-
-#define MULADDC_CORE \
- s0 = ( *s << biH ) >> biH; \
- s1 = ( *s >> biH ); s++; \
- rx = s0 * b1; r0 = s0 * b0; \
- ry = s1 * b0; r1 = s1 * b1; \
- r1 += ( rx >> biH ); \
- r1 += ( ry >> biH ); \
- rx <<= biH; ry <<= biH; \
- r0 += rx; r1 += (r0 < rx); \
- r0 += ry; r1 += (r0 < ry); \
- r0 += c; r1 += (r0 < c); \
- r0 += *d; r1 += (r0 < *d); \
- c = r1; *(d++) = r0;
-
-#define MULADDC_STOP \
-}
-
-#endif /* C (generic) */
-#endif /* C (longlong) */
-
-#endif /* bn_mul.h */
diff --git a/polarssl/src/include/polarssl/camellia.h b/polarssl/src/include/polarssl/camellia.h
deleted file mode 100644
index b2b1294..0000000
--- a/polarssl/src/include/polarssl/camellia.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * \file camellia.h
- *
- * \brief Camellia block cipher
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_CAMELLIA_H
-#define POLARSSL_CAMELLIA_H
-
-#include <string.h>
-
-#ifdef _MSC_VER
-#include <basetsd.h>
-typedef UINT32 uint32_t;
-#else
-#include <inttypes.h>
-#endif
-
-#define CAMELLIA_ENCRYPT 1
-#define CAMELLIA_DECRYPT 0
-
-#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */
-#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
-
-/**
- * \brief CAMELLIA context structure
- */
-typedef struct
-{
- int nr; /*!< number of rounds */
- uint32_t rk[68]; /*!< CAMELLIA round keys */
-}
-camellia_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief CAMELLIA key schedule (encryption)
- *
- * \param ctx CAMELLIA context to be initialized
- * \param key encryption key
- * \param keysize must be 128, 192 or 256
- *
- * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
- */
-int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
-
-/**
- * \brief CAMELLIA key schedule (decryption)
- *
- * \param ctx CAMELLIA context to be initialized
- * \param key decryption key
- * \param keysize must be 128, 192 or 256
- *
- * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
- */
-int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
-
-/**
- * \brief CAMELLIA-ECB block encryption/decryption
- *
- * \param ctx CAMELLIA context
- * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
- * \param input 16-byte input block
- * \param output 16-byte output block
- *
- * \return 0 if successful
- */
-int camellia_crypt_ecb( camellia_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] );
-
-/**
- * \brief CAMELLIA-CBC buffer encryption/decryption
- * Length should be a multiple of the block
- * size (16 bytes)
- *
- * \param ctx CAMELLIA context
- * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
- */
-int camellia_crypt_cbc( camellia_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief CAMELLIA-CFB128 buffer encryption/decryption
- *
- * Note: Due to the nature of CFB you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT.
- *
- * \param ctx CAMELLIA context
- * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
- * \param length length of the input data
- * \param iv_off offset in IV (updated after use)
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
- */
-int camellia_crypt_cfb128( camellia_context *ctx,
- int mode,
- size_t length,
- size_t *iv_off,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output );
-
-/*
- * \brief CAMELLIA-CTR buffer encryption/decryption
- *
- * Warning: You have to keep the maximum use of your counter in mind!
- *
- * Note: Due to the nature of CTR you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIA_DECRYPT.
- *
- * \param length The length of the data
- * \param nc_off The offset in the current stream_block (for resuming
- * within current cipher stream). The offset pointer to
- * should be 0 at the start of a stream.
- * \param nonce_counter The 128-bit nonce and counter.
- * \param stream_block The saved stream-block for resuming. Is overwritten
- * by the function.
- * \param input The input data stream
- * \param output The output data stream
- *
- * \return 0 if successful
- */
-int camellia_crypt_ctr( camellia_context *ctx,
- size_t length,
- size_t *nc_off,
- unsigned char nonce_counter[16],
- unsigned char stream_block[16],
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int camellia_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* camellia.h */
diff --git a/polarssl/src/include/polarssl/certs.h b/polarssl/src/include/polarssl/certs.h
deleted file mode 100644
index 5399e32..0000000
--- a/polarssl/src/include/polarssl/certs.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * \file certs.h
- *
- * \brief Sample certificates and DHM parameters for testing
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_CERTS_H
-#define POLARSSL_CERTS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern const char test_ca_crt[];
-extern const char test_ca_key[];
-extern const char test_ca_pwd[];
-extern const char test_srv_crt[];
-extern const char test_srv_key[];
-extern const char test_cli_crt[];
-extern const char test_cli_key[];
-extern const char test_dhm_params[];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* certs.h */
diff --git a/polarssl/src/include/polarssl/cipher.h b/polarssl/src/include/polarssl/cipher.h
deleted file mode 100644
index 9605066..0000000
--- a/polarssl/src/include/polarssl/cipher.h
+++ /dev/null
@@ -1,459 +0,0 @@
-/**
- * \file cipher.h
- *
- * \brief Generic cipher wrapper.
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef POLARSSL_CIPHER_H
-#define POLARSSL_CIPHER_H
-
-#include <string.h>
-
-#if defined(_MSC_VER) && !defined(inline)
-#define inline _inline
-#else
-#if defined(__ARMCC_VERSION) && !defined(inline)
-#define inline __inline
-#endif /* __ARMCC_VERSION */
-#endif /*_MSC_VER */
-
-#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */
-#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */
-#define POLARSSL_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */
-#define POLARSSL_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */
-#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
-
-typedef enum {
- POLARSSL_CIPHER_ID_NONE = 0,
- POLARSSL_CIPHER_ID_NULL,
- POLARSSL_CIPHER_ID_AES,
- POLARSSL_CIPHER_ID_DES,
- POLARSSL_CIPHER_ID_3DES,
- POLARSSL_CIPHER_ID_CAMELLIA,
-} cipher_id_t;
-
-typedef enum {
- POLARSSL_CIPHER_NONE = 0,
- POLARSSL_CIPHER_NULL,
- POLARSSL_CIPHER_AES_128_CBC,
- POLARSSL_CIPHER_AES_192_CBC,
- POLARSSL_CIPHER_AES_256_CBC,
- POLARSSL_CIPHER_AES_128_CFB128,
- POLARSSL_CIPHER_AES_192_CFB128,
- POLARSSL_CIPHER_AES_256_CFB128,
- POLARSSL_CIPHER_AES_128_CTR,
- POLARSSL_CIPHER_AES_192_CTR,
- POLARSSL_CIPHER_AES_256_CTR,
- POLARSSL_CIPHER_CAMELLIA_128_CBC,
- POLARSSL_CIPHER_CAMELLIA_192_CBC,
- POLARSSL_CIPHER_CAMELLIA_256_CBC,
- POLARSSL_CIPHER_CAMELLIA_128_CFB128,
- POLARSSL_CIPHER_CAMELLIA_192_CFB128,
- POLARSSL_CIPHER_CAMELLIA_256_CFB128,
- POLARSSL_CIPHER_CAMELLIA_128_CTR,
- POLARSSL_CIPHER_CAMELLIA_192_CTR,
- POLARSSL_CIPHER_CAMELLIA_256_CTR,
- POLARSSL_CIPHER_DES_CBC,
- POLARSSL_CIPHER_DES_EDE_CBC,
- POLARSSL_CIPHER_DES_EDE3_CBC
-} cipher_type_t;
-
-typedef enum {
- POLARSSL_MODE_NONE = 0,
- POLARSSL_MODE_NULL,
- POLARSSL_MODE_CBC,
- POLARSSL_MODE_CFB128,
- POLARSSL_MODE_OFB,
- POLARSSL_MODE_CTR,
-} cipher_mode_t;
-
-typedef enum {
- POLARSSL_OPERATION_NONE = -1,
- POLARSSL_DECRYPT = 0,
- POLARSSL_ENCRYPT,
-} operation_t;
-
-enum {
- /** Undefined key length */
- POLARSSL_KEY_LENGTH_NONE = 0,
- /** Key length, in bits (including parity), for DES keys */
- POLARSSL_KEY_LENGTH_DES = 64,
- /** Key length, in bits (including parity), for DES in two key EDE */
- POLARSSL_KEY_LENGTH_DES_EDE = 128,
- /** Key length, in bits (including parity), for DES in three-key EDE */
- POLARSSL_KEY_LENGTH_DES_EDE3 = 192,
- /** Maximum length of any IV, in bytes */
- POLARSSL_MAX_IV_LENGTH = 16,
-};
-
-/**
- * Base cipher information. The non-mode specific functions and values.
- */
-typedef struct {
-
- /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */
- cipher_id_t cipher;
-
- /** Encrypt using CBC */
- int (*cbc_func)( void *ctx, operation_t mode, size_t length, unsigned char *iv,
- const unsigned char *input, unsigned char *output );
-
- /** Encrypt using CFB128 */
- int (*cfb128_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off,
- unsigned char *iv, const unsigned char *input, unsigned char *output );
-
- /** Encrypt using CTR */
- int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter,
- unsigned char *stream_block, const unsigned char *input, unsigned char *output );
-
- /** Set key for encryption purposes */
- int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length);
-
- /** Set key for decryption purposes */
- int (*setkey_dec_func)( void *ctx, const unsigned char *key, unsigned int key_length);
-
- /** Allocate a new context */
- void * (*ctx_alloc_func)( void );
-
- /** Free the given context */
- void (*ctx_free_func)( void *ctx );
-
-} cipher_base_t;
-
-/**
- * Cipher information. Allows cipher functions to be called in a generic way.
- */
-typedef struct {
- /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */
- cipher_type_t type;
-
- /** Cipher mode (e.g. POLARSSL_MODE_CBC) */
- cipher_mode_t mode;
-
- /** Cipher key length, in bits (default length for variable sized ciphers)
- * (Includes parity bits for ciphers like DES) */
- unsigned int key_length;
-
- /** Name of the cipher */
- const char * name;
-
- /** IV size, in bytes */
- unsigned int iv_size;
-
- /** block size, in bytes */
- unsigned int block_size;
-
- /** Base cipher information and functions */
- const cipher_base_t *base;
-
-} cipher_info_t;
-
-/**
- * Generic cipher context.
- */
-typedef struct {
- /** Information about the associated cipher */
- const cipher_info_t *cipher_info;
-
- /** Key length to use */
- int key_length;
-
- /** Operation that the context's key has been initialised for */
- operation_t operation;
-
- /** Buffer for data that hasn't been encrypted yet */
- unsigned char unprocessed_data[POLARSSL_MAX_IV_LENGTH];
-
- /** Number of bytes that still need processing */
- size_t unprocessed_len;
-
- /** Current IV or NONCE_COUNTER for CTR-mode */
- unsigned char iv[POLARSSL_MAX_IV_LENGTH];
-
- /** Cipher-specific context */
- void *cipher_ctx;
-} cipher_context_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Returns the list of ciphers supported by the generic cipher module.
- *
- * \return a statically allocated array of ciphers, the last entry
- * is 0.
- */
-const int *cipher_list( void );
-
-/**
- * \brief Returns the cipher information structure associated
- * with the given cipher name.
- *
- * \param cipher_name Name of the cipher to search for.
- *
- * \return the cipher information structure associated with the
- * given cipher_name, or NULL if not found.
- */
-const cipher_info_t *cipher_info_from_string( const char *cipher_name );
-
-/**
- * \brief Returns the cipher information structure associated
- * with the given cipher type.
- *
- * \param cipher_type Type of the cipher to search for.
- *
- * \return the cipher information structure associated with the
- * given cipher_type, or NULL if not found.
- */
-const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type );
-
-/**
- * \brief Initialises and fills the cipher context structure with
- * the appropriate values.
- *
- * \param ctx context to initialise. May not be NULL.
- * \param cipher_info cipher to use.
- *
- * \return \c 0 on success,
- * \c POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
- * \c POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the
- * cipher-specific context failed.
- */
-int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info );
-
-/**
- * \brief Free the cipher-specific context of ctx. Freeing ctx
- * itself remains the responsibility of the caller.
- *
- * \param ctx Free the cipher-specific context
- *
- * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
- * parameter verification fails.
- */
-int cipher_free_ctx( cipher_context_t *ctx );
-
-/**
- * \brief Returns the block size of the given cipher.
- *
- * \param ctx cipher's context. Must have been initialised.
- *
- * \return size of the cipher's blocks, or 0 if ctx has not been
- * initialised.
- */
-static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx )
-{
- if( NULL == ctx || NULL == ctx->cipher_info )
- return 0;
-
- return ctx->cipher_info->block_size;
-}
-
-/**
- * \brief Returns the mode of operation for the cipher.
- * (e.g. POLARSSL_MODE_CBC)
- *
- * \param ctx cipher's context. Must have been initialised.
- *
- * \return mode of operation, or POLARSSL_MODE_NONE if ctx
- * has not been initialised.
- */
-static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx )
-{
- if( NULL == ctx || NULL == ctx->cipher_info )
- return POLARSSL_MODE_NONE;
-
- return ctx->cipher_info->mode;
-}
-
-/**
- * \brief Returns the size of the cipher's IV.
- *
- * \param ctx cipher's context. Must have been initialised.
- *
- * \return size of the cipher's IV, or 0 if ctx has not been
- * initialised.
- */
-static inline int cipher_get_iv_size( const cipher_context_t *ctx )
-{
- if( NULL == ctx || NULL == ctx->cipher_info )
- return 0;
-
- return ctx->cipher_info->iv_size;
-}
-
-/**
- * \brief Returns the type of the given cipher.
- *
- * \param ctx cipher's context. Must have been initialised.
- *
- * \return type of the cipher, or POLARSSL_CIPHER_NONE if ctx has
- * not been initialised.
- */
-static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx )
-{
- if( NULL == ctx || NULL == ctx->cipher_info )
- return 0;
-
- return ctx->cipher_info->type;
-}
-
-/**
- * \brief Returns the name of the given cipher, as a string.
- *
- * \param ctx cipher's context. Must have been initialised.
- *
- * \return name of the cipher, or NULL if ctx was not initialised.
- */
-static inline const char *cipher_get_name( const cipher_context_t *ctx )
-{
- if( NULL == ctx || NULL == ctx->cipher_info )
- return 0;
-
- return ctx->cipher_info->name;
-}
-
-/**
- * \brief Returns the key length of the cipher.
- *
- * \param ctx cipher's context. Must have been initialised.
- *
- * \return cipher's key length, in bits, or
- * POLARSSL_KEY_LENGTH_NONE if ctx has not been
- * initialised.
- */
-static inline int cipher_get_key_size ( const cipher_context_t *ctx )
-{
- if( NULL == ctx )
- return POLARSSL_KEY_LENGTH_NONE;
-
- return ctx->key_length;
-}
-
-/**
- * \brief Returns the operation of the given cipher.
- *
- * \param ctx cipher's context. Must have been initialised.
- *
- * \return operation (POLARSSL_ENCRYPT or POLARSSL_DECRYPT),
- * or POLARSSL_OPERATION_NONE if ctx has not been
- * initialised.
- */
-static inline operation_t cipher_get_operation( const cipher_context_t *ctx )
-{
- if( NULL == ctx || NULL == ctx->cipher_info )
- return POLARSSL_OPERATION_NONE;
-
- return ctx->operation;
-}
-
-/**
- * \brief Set the key to use with the given context.
- *
- * \param ctx generic cipher context. May not be NULL. Must have been
- * initialised using cipher_context_from_type or
- * cipher_context_from_string.
- * \param key The key to use.
- * \param key_length key length to use, in bits.
- * \param operation Operation that the key will be used for, either
- * POLARSSL_ENCRYPT or POLARSSL_DECRYPT.
- *
- * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
- * parameter verification fails or a cipher specific
- * error code.
- */
-int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int key_length,
- const operation_t operation );
-
-/**
- * \brief Reset the given context, setting the IV to iv
- *
- * \param ctx generic cipher context
- * \param iv IV to use or NONCE_COUNTER in the case of a CTR-mode cipher
- *
- * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
- * if parameter verification fails.
- */
-int cipher_reset( cipher_context_t *ctx, const unsigned char *iv );
-
-/**
- * \brief Generic cipher update function. Encrypts/decrypts
- * using the given cipher context. Writes as many block
- * size'd blocks of data as possible to output. Any data
- * that cannot be written immediately will either be added
- * to the next block, or flushed when cipher_final is
- * called.
- *
- * \param ctx generic cipher context
- * \param input buffer holding the input data
- * \param ilen length of the input data
- * \param output buffer for the output data. Should be able to hold at
- * least ilen + block_size. Cannot be the same buffer as
- * input!
- * \param olen length of the output data, will be filled with the
- * actual number of bytes written.
- *
- * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
- * parameter verification fails,
- * POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an
- * unsupported mode for a cipher or a cipher specific
- * error code.
- */
-int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
- unsigned char *output, size_t *olen );
-
-/**
- * \brief Generic cipher finalisation function. If data still
- * needs to be flushed from an incomplete block, data
- * contained within it will be padded with the size of
- * the last block, and written to the output buffer.
- *
- * \param ctx Generic cipher context
- * \param output buffer to write data to. Needs block_size data available.
- * \param olen length of the data written to the output buffer.
- *
- * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
- * parameter verification fails,
- * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
- * expected a full block but was not provided one,
- * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding
- * while decrypting or a cipher specific error code.
- */
-int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen);
-
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int cipher_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* POLARSSL_MD_H */
diff --git a/polarssl/src/include/polarssl/cipher_wrap.h b/polarssl/src/include/polarssl/cipher_wrap.h
deleted file mode 100644
index e81c11d..0000000
--- a/polarssl/src/include/polarssl/cipher_wrap.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * \file cipher_wrap.h
- *
- * \brief Cipher wrappers.
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_CIPHER_WRAP_H
-#define POLARSSL_CIPHER_WRAP_H
-
-#include "config.h"
-#include "cipher.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(POLARSSL_AES_C)
-
-extern const cipher_info_t aes_128_cbc_info;
-extern const cipher_info_t aes_192_cbc_info;
-extern const cipher_info_t aes_256_cbc_info;
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
-extern const cipher_info_t aes_128_cfb128_info;
-extern const cipher_info_t aes_192_cfb128_info;
-extern const cipher_info_t aes_256_cfb128_info;
-#endif /* POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-extern const cipher_info_t aes_128_ctr_info;
-extern const cipher_info_t aes_192_ctr_info;
-extern const cipher_info_t aes_256_ctr_info;
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-#endif /* defined(POLARSSL_AES_C) */
-
-#if defined(POLARSSL_CAMELLIA_C)
-
-extern const cipher_info_t camellia_128_cbc_info;
-extern const cipher_info_t camellia_192_cbc_info;
-extern const cipher_info_t camellia_256_cbc_info;
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
-extern const cipher_info_t camellia_128_cfb128_info;
-extern const cipher_info_t camellia_192_cfb128_info;
-extern const cipher_info_t camellia_256_cfb128_info;
-#endif /* POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-extern const cipher_info_t camellia_128_ctr_info;
-extern const cipher_info_t camellia_192_ctr_info;
-extern const cipher_info_t camellia_256_ctr_info;
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-#endif /* defined(POLARSSL_CAMELLIA_C) */
-
-#if defined(POLARSSL_DES_C)
-
-extern const cipher_info_t des_cbc_info;
-extern const cipher_info_t des_ede_cbc_info;
-extern const cipher_info_t des_ede3_cbc_info;
-
-#endif /* defined(POLARSSL_DES_C) */
-
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-extern const cipher_info_t null_cipher_info;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* POLARSSL_CIPHER_WRAP_H */
diff --git a/polarssl/src/include/polarssl/config.h b/polarssl/src/include/polarssl/config.h
deleted file mode 100644
index 4e27446..0000000
--- a/polarssl/src/include/polarssl/config.h
+++ /dev/null
@@ -1,744 +0,0 @@
-/**
- * \file config.h
- *
- * \brief Configuration options (set of defines)
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * This set of compile-time options may be used to enable
- * or disable features selectively, and reduce the global
- * memory footprint.
- */
-#ifndef POLARSSL_CONFIG_H
-#define POLARSSL_CONFIG_H
-
-#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
-#define _CRT_SECURE_NO_DEPRECATE 1
-#endif
-
-/**
- * \name SECTION: System support
- *
- * This section sets system specific settings.
- * \{
- */
-
-/**
- * \def POLARSSL_HAVE_INT8
- *
- * The system uses 8-bit wide native integers.
- *
- * Uncomment if native integers are 8-bit wide.
-#define POLARSSL_HAVE_INT8
- */
-
-/**
- * \def POLARSSL_HAVE_INT16
- *
- * The system uses 16-bit wide native integers.
- *
- * Uncomment if native integers are 16-bit wide.
-#define POLARSSL_HAVE_INT16
- */
-
-/**
- * \def POLARSSL_HAVE_LONGLONG
- *
- * The compiler supports the use of long long.
- *
- * Uncomment if the compiler supports long long.
-#define POLARSSL_HAVE_LONGLONG
- */
-
-/**
- * \def POLARSSL_HAVE_ASM
- *
- * The compiler has support for asm()
- *
- * Uncomment to enable the use of assembly code.
- *
- * Requires support for asm() in compiler.
- *
- * Used in:
- * library/timing.c
- * library/padlock.c
- * include/polarssl/bn_mul.h
- *
- */
-#define POLARSSL_HAVE_ASM
-
-/**
- * \def POLARSSL_HAVE_SSE2
- *
- * CPI supports SSE2 instruction set.
- *
- * Uncomment if the CPU supports SSE2 (IA-32 specific).
- *
-#define POLARSSL_HAVE_SSE2
- */
-/* \} name */
-
-/**
- * \name SECTION: PolarSSL feature support
- *
- * This section sets support for features that are or are not needed
- * within the modules that are enabled.
- * \{
- */
-
-/**
- * \def POLARSSL_AES_ROM_TABLES
- *
- * Store the AES tables in ROM.
- *
- * Uncomment this macro to store the AES tables in ROM.
- *
-#define POLARSSL_AES_ROM_TABLES
- */
-
-/**
- * \def POLARSSL_CIPHER_MODE_CFB
- *
- * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
- */
-//#define POLARSSL_CIPHER_MODE_CFB
-
-/**
- * \def POLARSSL_CIPHER_MODE_CTR
- *
- * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
- */
-//#define POLARSSL_CIPHER_MODE_CTR
-
-/**
- * \def POLARSSL_CIPHER_NULL_CIPHER
- *
- * Enable NULL cipher.
- * Warning: Only do so when you know what you are doing. This allows for
- * encryption or channels without any security!
- *
- * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable
- * the following ciphersuites:
- * SSL_RSA_NULL_MD5
- * SSL_RSA_NULL_SHA
- * SSL_RSA_NULL_SHA256
- *
- * Uncomment this macro to enable the NULL cipher and ciphersuites
-#define POLARSSL_CIPHER_NULL_CIPHER
- */
-
-/**
- * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES
- *
- * Enable weak ciphersuites in SSL / TLS (like RC4_40)
- * Warning: Only do so when you know what you are doing. This allows for
- * channels without virtually no security at all!
- *
- * This enables the following ciphersuites:
- * SSL_RSA_DES_SHA
- * SSL_EDH_RSA_DES_SHA
- *
- * Uncomment this macro to enable weak ciphersuites
-#define POLARSSL_ENABLE_WEAK_CIPHERSUITES
- */
-
-/**
- * \def POLARSSL_GENPRIME
- *
- * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
- *
- * Enable the RSA prime-number generation code.
- */
-//#define POLARSSL_GENPRIME
-
-/**
- * \def POLARSSL_FS_IO
- *
- * Enable functions that use the filesystem.
- */
-//#define POLARSSL_FS_IO
-
-/**
- * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
- *
- * Do not add default entropy sources. These are the platform specific,
- * hardclock and HAVEGE based poll functions.
- *
- * This is useful to have more control over the added entropy sources in an
- * application.
- *
- * Uncomment this macro to prevent loading of default entropy functions.
-#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
- */
-
-/**
- * \def POLARSSL_NO_PLATFORM_ENTROPY
- *
- * Do not use built-in platform entropy functions.
- * This is useful if your platform does not support
- * standards like the /dev/urandom or Windows CryptoAPI.
- *
- * Uncomment this macro to disable the built-in platform entropy functions.
-#define POLARSSL_NO_PLATFORM_ENTROPY
- */
-
-/**
- * \def POLARSSL_PKCS1_V21
- *
- * Requires: POLARSSL_MD_C, POLARSSL_RSA_C
- *
- * Enable support for PKCS#1 v2.1 encoding.
- * This enables support for RSAES-OAEP and RSASSA-PSS operations.
- */
-//#define POLARSSL_PKCS1_V21
-
-/**
- * \def POLARSSL_RSA_NO_CRT
- *
- * Do not use the Chinese Remainder Theorem for the RSA private operation.
- *
- * Uncomment this macro to disable the use of CRT in RSA.
- *
-#define POLARSSL_RSA_NO_CRT
- */
-
-/**
- * \def POLARSSL_SELF_TEST
- *
- * Enable the checkup functions (*_self_test).
- */
-//#define POLARSSL_SELF_TEST
-
-/**
- * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
- *
- * If set, the X509 parser will not break-off when parsing an X509 certificate
- * and encountering an unknown critical extension.
- *
- * Uncomment to prevent an error.
- *
-#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
- */
-/* \} name */
-
-/**
- * \name SECTION: PolarSSL modules
- *
- * This section enables or disables entire modules in PolarSSL
- * \{
- */
-
-/**
- * \def POLARSSL_AES_C
- *
- * Enable the AES block cipher.
- *
- * Module: library/aes.c
- * Caller: library/ssl_tls.c
- * library/pem.c
- * library/ctr_drbg.c
- *
- * This module enables the following ciphersuites:
- * SSL_RSA_AES_128_SHA
- * SSL_RSA_AES_256_SHA
- * SSL_EDH_RSA_AES_256_SHA
- */
-#define POLARSSL_AES_C
-
-/**
- * \def POLARSSL_ARC4_C
- *
- * Enable the ARCFOUR stream cipher.
- *
- * Module: library/arc4.c
- * Caller: library/ssl_tls.c
- *
- * This module enables the following ciphersuites:
- * SSL_RSA_RC4_128_MD5
- * SSL_RSA_RC4_128_SHA
- */
-//#define POLARSSL_ARC4_C
-
-/**
- * \def POLARSSL_ASN1_PARSE_C
- *
- * Enable the generic ASN1 parser.
- *
- * Module: library/asn1.c
- * Caller: library/x509parse.c
- */
-#define POLARSSL_ASN1_PARSE_C
-
-/**
- * \def POLARSSL_ASN1_WRITE_C
- *
- * Enable the generic ASN1 writer.
- *
- * Module: library/asn1write.c
- */
-#define POLARSSL_ASN1_WRITE_C
-
-/**
- * \def POLARSSL_BASE64_C
- *
- * Enable the Base64 module.
- *
- * Module: library/base64.c
- * Caller: library/pem.c
- *
- * This module is required for PEM support (required by X.509).
- */
-//#define POLARSSL_BASE64_C
-
-/**
- * \def POLARSSL_BIGNUM_C
- *
- * Enable the multo-precision integer library.
- *
- * Module: library/bignum.c
- * Caller: library/dhm.c
- * library/rsa.c
- * library/ssl_tls.c
- * library/x509parse.c
- *
- * This module is required for RSA and DHM support.
- */
-#define POLARSSL_BIGNUM_C
-
-/**
- * \def POLARSSL_CAMELLIA_C
- *
- * Enable the Camellia block cipher.
- *
- * Module: library/camellia.c
- * Caller: library/ssl_tls.c
- *
- * This module enabled the following cipher suites:
- * SSL_RSA_CAMELLIA_128_SHA
- * SSL_RSA_CAMELLIA_256_SHA
- * SSL_EDH_RSA_CAMELLIA_256_SHA
- */
-//#define POLARSSL_CAMELLIA_C
-
-/**
- * \def POLARSSL_CERTS_C
- *
- * Enable the test certificates.
- *
- * Module: library/certs.c
- * Caller:
- *
- * This module is used for testing (ssl_client/server).
- */
-//#define POLARSSL_CERTS_C
-
-/**
- * \def POLARSSL_CIPHER_C
- *
- * Enable the generic cipher layer.
- *
- * Module: library/cipher.c
- * Caller:
- *
- * Uncomment to enable generic cipher wrappers.
- */
-//#define POLARSSL_CIPHER_C
-
-/**
- * \def POLARSSL_CTR_DRBG_C
- *
- * Enable the CTR_DRBG AES-256-based random generator
- *
- * Module: library/ctr_drbg.c
- * Caller:
- *
- * Requires: POLARSSL_AES_C
- *
- * This module provides the CTR_DRBG AES-256 random number generator.
- */
-#define POLARSSL_CTR_DRBG_C
-
-/**
- * \def POLARSSL_DEBUG_C
- *
- * Enable the debug functions.
- *
- * Module: library/debug.c
- * Caller: library/ssl_cli.c
- * library/ssl_srv.c
- * library/ssl_tls.c
- *
- * This module provides debugging functions.
- */
-//#define POLARSSL_DEBUG_C
-
-/**
- * \def POLARSSL_DES_C
- *
- * Enable the DES block cipher.
- *
- * Module: library/des.c
- * Caller: library/ssl_tls.c
- *
- * This module enables the following ciphersuites:
- * SSL_RSA_DES_168_SHA
- * SSL_EDH_RSA_DES_168_SHA
- */
-//#define POLARSSL_DES_C
-
-/**
- * \def POLARSSL_DHM_C
- *
- * Enable the Diffie-Hellman-Merkle key exchange.
- *
- * Module: library/dhm.c
- * Caller: library/ssl_cli.c
- * library/ssl_srv.c
- *
- * This module enables the following ciphersuites:
- * SSL_EDH_RSA_DES_168_SHA
- * SSL_EDH_RSA_AES_256_SHA
- * SSL_EDH_RSA_CAMELLIA_256_SHA
- */
-//#define POLARSSL_DHM_C
-
-/**
- * \def POLARSSL_ENTROPY_C
- *
- * Enable the platform-specific entropy code.
- *
- * Module: library/entropy.c
- * Caller:
- *
- * Requires: POLARSSL_SHA4_C
- *
- * This module provides a generic entropy pool
- */
-#define POLARSSL_ENTROPY_C
-
-/**
- * \def POLARSSL_ERROR_C
- *
- * Enable error code to error string conversion.
- *
- * Module: library/error.c
- * Caller:
- *
- * This module enables err_strerror().
- */
-#define POLARSSL_ERROR_C
-
-/**
- * \def POLARSSL_GCM_C
- *
- * Enable the Galois/Counter Mode (GCM) for AES
- *
- * Module: library/gcm.c
- *
- * Requires: POLARSSL_AES_C
- */
-//#define POLARSSL_GCM_C
-
-/**
- * \def POLARSSL_HAVEGE_C
- *
- * Enable the HAVEGE random generator.
- *
- * Module: library/havege.c
- * Caller:
- *
- * Requires: POLARSSL_TIMING_C
- *
- * This module enables the HAVEGE random number generator.
- */
-//#define POLARSSL_HAVEGE_C
-
-/**
- * \def POLARSSL_MD_C
- *
- * Enable the generic message digest layer.
- *
- * Module: library/md.c
- * Caller:
- *
- * Uncomment to enable generic message digest wrappers.
- */
-//#define POLARSSL_MD_C
-
-/**
- * \def POLARSSL_MD2_C
- *
- * Enable the MD2 hash algorithm
- *
- * Module: library/md2.c
- * Caller: library/x509parse.c
- *
- * Uncomment to enable support for (rare) MD2-signed X.509 certs.
- *
-#define POLARSSL_MD2_C
- */
-
-/**
- * \def POLARSSL_MD4_C
- *
- * Enable the MD4 hash algorithm
- *
- * Module: library/md4.c
- * Caller: library/x509parse.c
- *
- * Uncomment to enable support for (rare) MD4-signed X.509 certs.
- *
-#define POLARSSL_MD4_C
- */
-
-/**
- * \def POLARSSL_MD5_C
- *
- * Enable the MD5 hash algorithm
- *
- * Module: library/md5.c
- * Caller: library/ssl_tls.c
- * library/x509parse.c
- *
- * This module is required for SSL/TLS and X.509.
- */
-#define POLARSSL_MD5_C
-
-/**
- * \def POLARSSL_NET_C
- *
- * Enable the TCP/IP networking routines.
- *
- * Module: library/net.c
- * Caller:
- *
- * This module provides TCP/IP networking routines.
- */
-//#define POLARSSL_NET_C
-
-/**
- * \def POLARSSL_PADLOCK_C
- *
- * Enable VIA Padlock support on x86.
- *
- * Module: library/padlock.c
- * Caller: library/aes.c
- *
- * This modules adds support for the VIA PadLock on x86.
- */
-//#define POLARSSL_PADLOCK_C
-
-/**
- * \def POLARSSL_PEM_C
- *
- * Enable PEM decoding
- *
- * Module: library/pem.c
- * Caller: library/x509parse.c
- *
- * Requires: POLARSSL_BASE64_C
- *
- * This modules adds support for decoding PEM files.
- */
-//#define POLARSSL_PEM_C
-
-/**
- * \def POLARSSL_PKCS11_C
- *
- * Enable support for PKCS#11 smartcard support.
- *
- * Module: library/ssl_srv.c
- * Caller: library/ssl_cli.c
- * library/ssl_srv.c
- *
- * Requires: POLARSSL_SSL_TLS_C
- *
- * This module is required for SSL/TLS PKCS #11 smartcard support.
- * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
-#define POLARSSL_PKCS11_C
- */
-
-/**
- * \def POLARSSL_RSA_C
- *
- * Enable the RSA public-key cryptosystem.
- *
- * Module: library/rsa.c
- * Caller: library/ssl_cli.c
- * library/ssl_srv.c
- * library/ssl_tls.c
- * library/x509.c
- *
- * Requires: POLARSSL_BIGNUM_C
- *
- * This module is required for SSL/TLS and MD5-signed certificates.
- */
-#define POLARSSL_RSA_C
-
-/**
- * \def POLARSSL_SHA1_C
- *
- * Enable the SHA1 cryptographic hash algorithm.
- *
- * Module: library/sha1.c
- * Caller: library/ssl_cli.c
- * library/ssl_srv.c
- * library/ssl_tls.c
- * library/x509parse.c
- *
- * This module is required for SSL/TLS and SHA1-signed certificates.
- */
-#define POLARSSL_SHA1_C
-
-/**
- * \def POLARSSL_SHA2_C
- *
- * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
- *
- * Module: library/sha2.c
- * Caller: library/md_wrap.c
- * library/x509parse.c
- *
- * This module adds support for SHA-224 and SHA-256.
- */
-#define POLARSSL_SHA2_C
-
-/**
- * \def POLARSSL_SHA4_C
- *
- * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
- *
- * Module: library/sha4.c
- * Caller: library/md_wrap.c
- * library/x509parse.c
- *
- * This module adds support for SHA-384 and SHA-512.
- */
-#define POLARSSL_SHA4_C
-
-/**
- * \def POLARSSL_SSL_CLI_C
- *
- * Enable the SSL/TLS client code.
- *
- * Module: library/ssl_cli.c
- * Caller:
- *
- * Requires: POLARSSL_SSL_TLS_C
- *
- * This module is required for SSL/TLS client support.
- */
-#define POLARSSL_SSL_CLI_C
-
-/*
- * \def POLARSSL_SSL_SRV_C
- *
- * Enable the SSL/TLS server code.
- *
- * Module: library/ssl_srv.c
- * Caller:
- *
- * Requires: POLARSSL_SSL_TLS_C
- *
- * This module is required for SSL/TLS server support.
- */
-//#define POLARSSL_SSL_SRV_C
-
-/**
- * \def POLARSSL_SSL_TLS_C
- *
- * Enable the generic SSL/TLS code.
- *
- * Module: library/ssl_tls.c
- * Caller: library/ssl_cli.c
- * library/ssl_srv.c
- *
- * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C
- *
- * This module is required for SSL/TLS.
- */
-#define POLARSSL_SSL_TLS_C
-
-/**
- * \def POLARSSL_TIMING_C
- *
- * Enable the portable timing interface.
- *
- * Module: library/timing.c
- * Caller: library/havege.c
- *
- * This module is used by the HAVEGE random number generator.
- */
-//#define POLARSSL_TIMING_C
-
-/**
- * \def POLARSSL_VERSION_C
- *
- * Enable run-time version information.
- *
- * Module: library/version.c
- *
- * This module provides run-time version information.
- */
-#define POLARSSL_VERSION_C
-
-/**
- * \def POLARSSL_X509_PARSE_C
- *
- * Enable X.509 certificate parsing.
- *
- * Module: library/x509parse.c
- * Caller: library/ssl_cli.c
- * library/ssl_srv.c
- * library/ssl_tls.c
- *
- * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C
- *
- * This module is required for X.509 certificate parsing.
- */
-#define POLARSSL_X509_PARSE_C
-
-/**
- * \def POLARSSL_X509_WRITE_C
- *
- * Enable X.509 buffer writing.
- *
- * Module: library/x509write.c
- *
- * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
- *
- * This module is required for X.509 certificate request writing.
- */
-//#define POLARSSL_X509_WRITE_C
-
-/**
- * \def POLARSSL_XTEA_C
- *
- * Enable the XTEA block cipher.
- *
- * Module: library/xtea.c
- * Caller:
- */
-//#define POLARSSL_XTEA_C
-/* \} name */
-
-#endif /* config.h */
diff --git a/polarssl/src/include/polarssl/ctr_drbg.h b/polarssl/src/include/polarssl/ctr_drbg.h
deleted file mode 100644
index 83861a9..0000000
--- a/polarssl/src/include/polarssl/ctr_drbg.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/**
- * \file ctr_drbg.h
- *
- * \brief CTR_DRBG based on AES-256 (NIST SP 800-90)
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_CTR_DRBG_H
-#define POLARSSL_CTR_DRBG_H
-
-#include <string.h>
-
-#include "aes.h"
-
-#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
-#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */
-#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */
-#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */
-
-#define CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */
-#define CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */
-#define CTR_DRBG_KEYBITS ( CTR_DRBG_KEYSIZE * 8 )
-#define CTR_DRBG_SEEDLEN ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE )
- /**< The seed length (counter + AES key) */
-#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default */
-#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
-#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
-#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
-#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
-
-#define CTR_DRBG_PR_OFF 0 /**< No prediction resistance */
-#define CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief CTR_DRBG context structure
- */
-typedef struct
-{
- unsigned char counter[16]; /*!< counter (V) */
- int reseed_counter; /*!< reseed counter */
- int prediction_resistance; /*!< enable prediction resistance (Automatic
- reseed before every random generation) */
- size_t entropy_len; /*!< amount of entropy grabbed on each (re)seed */
- int reseed_interval; /*!< reseed interval */
-
- aes_context aes_ctx; /*!< AES context */
-
- /*
- * Callbacks (Entropy)
- */
- int (*f_entropy)(void *, unsigned char *, size_t);
-
- void *p_entropy; /*!< context for the entropy function */
-}
-ctr_drbg_context;
-
-/**
- * \brief CTR_DRBG initialization
- *
- * Note: Personalization data can be provided in addition to the more generic
- * entropy source to make this instantiation as unique as possible.
- *
- * \param ctx CTR_DRBG context to be initialized
- * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer
- * length)
- * \param p_entropy Entropy context
- * \param custom Personalization data (Device specific identifiers)
- * (Can be NULL)
- * \param len Length of personalization data
- *
- * \return 0 if successful, or
- * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
- */
-int ctr_drbg_init( ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t),
- void *p_entropy,
- const unsigned char *custom,
- size_t len );
-
-/**
- * \brief Enable / disable prediction resistance (Default: Off)
- *
- * Note: If enabled, entropy is used for ctx->entropy_len before each call!
- * Only use this if you have ample supply of good entropy!
- *
- * \param ctx CTR_DRBG context
- * \param resistance CTR_DRBG_PR_ON or CTR_DRBG_PR_OFF
- */
-void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx,
- int resistance );
-
-/**
- * \brief Set the amount of entropy grabbed on each (re)seed
- * (Default: CTR_DRBG_ENTROPY_LEN)
- *
- * \param ctx CTR_DRBG context
- * \param len Amount of entropy to grab
- */
-void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx,
- size_t len );
-
-/**
- * \brief Set the reseed interval
- * (Default: CTR_DRBG_RESEED_INTERVAL)
- *
- * \param ctx CTR_DRBG context
- * \param interval Reseed interval
- */
-void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx,
- int interval );
-
-/**
- * \brief CTR_DRBG reseeding (extracts data from entropy source)
- *
- * \param ctx CTR_DRBG context
- * \param additional Additional data to add to state (Can be NULL)
- * \param len Length of additional data
- *
- * \return 0 if successful, or
- * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
- */
-int ctr_drbg_reseed( ctr_drbg_context *ctx,
- const unsigned char *additional, size_t len );
-
-/**
- * \brief CTR_DRBG update state
- *
- * \param ctx CTR_DRBG context
- * \param additional Additional data to update state with
- * \param add_len Length of additional data
- */
-void ctr_drbg_update( ctr_drbg_context *ctx,
- const unsigned char *additional, size_t add_len );
-
-/**
- * \brief CTR_DRBG generate random with additional update input
- *
- * Note: Automatically reseeds if reseed_counter is reached.
- *
- * \param p_rng CTR_DRBG context
- * \param output Buffer to fill
- * \param output_len Length of the buffer
- * \param additional Additional data to update with (Can be NULL)
- * \param add_len Length of additional data
- *
- * \return 0 if successful, or
- * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
- * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
- */
-int ctr_drbg_random_with_add( void *p_rng,
- unsigned char *output, size_t output_len,
- const unsigned char *additional, size_t add_len );
-
-/**
- * \brief CTR_DRBG generate random
- *
- * Note: Automatically reseeds if reseed_counter is reached.
- *
- * \param p_rng CTR_DRBG context
- * \param output Buffer to fill
- * \param output_len Length of the buffer
- *
- * \return 0 if successful, or
- * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
- * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
- */
-int ctr_drbg_random( void *p_rng,
- unsigned char *output, size_t output_len );
-
-#if defined(POLARSSL_FS_IO)
-/**
- * \brief Write a seed file
- *
- * \param path Name of the file
- *
- * \return 0 if successful, 1 on file error, or
- * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
- */
-int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path );
-
-/**
- * \brief Read and update a seed file. Seed is added to this
- * instance
- *
- * \param path Name of the file
- *
- * \return 0 if successful, 1 on file error,
- * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
- * POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG
- */
-int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path );
-#endif
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int ctr_drbg_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ctr_drbg.h */
diff --git a/polarssl/src/include/polarssl/debug.h b/polarssl/src/include/polarssl/debug.h
deleted file mode 100644
index 511e926..0000000
--- a/polarssl/src/include/polarssl/debug.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * \file debug.h
- *
- * \brief Debug functions
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_DEBUG_H
-#define POLARSSL_DEBUG_H
-
-#include "config.h"
-#include "ssl.h"
-
-#if defined(POLARSSL_DEBUG_C)
-
-#define SSL_DEBUG_MSG( level, args ) \
- debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args );
-
-#define SSL_DEBUG_RET( level, text, ret ) \
- debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret );
-
-#define SSL_DEBUG_BUF( level, text, buf, len ) \
- debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len );
-
-#define SSL_DEBUG_MPI( level, text, X ) \
- debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X );
-
-#define SSL_DEBUG_CRT( level, text, crt ) \
- debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt );
-
-#else
-
-#define SSL_DEBUG_MSG( level, args ) do { } while( 0 )
-#define SSL_DEBUG_RET( level, text, ret ) do { } while( 0 )
-#define SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 )
-#define SSL_DEBUG_MPI( level, text, X ) do { } while( 0 )
-#define SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 )
-
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-char *debug_fmt( const char *format, ... );
-
-void debug_print_msg( const ssl_context *ssl, int level,
- const char *file, int line, const char *text );
-
-void debug_print_ret( const ssl_context *ssl, int level,
- const char *file, int line,
- const char *text, int ret );
-
-void debug_print_buf( const ssl_context *ssl, int level,
- const char *file, int line, const char *text,
- unsigned char *buf, size_t len );
-
-void debug_print_mpi( const ssl_context *ssl, int level,
- const char *file, int line,
- const char *text, const mpi *X );
-
-void debug_print_crt( const ssl_context *ssl, int level,
- const char *file, int line,
- const char *text, const x509_cert *crt );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* debug.h */
diff --git a/polarssl/src/include/polarssl/des.h b/polarssl/src/include/polarssl/des.h
deleted file mode 100644
index 653e68b..0000000
--- a/polarssl/src/include/polarssl/des.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/**
- * \file des.h
- *
- * \brief DES block cipher
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_DES_H
-#define POLARSSL_DES_H
-
-#include <string.h>
-
-#define DES_ENCRYPT 1
-#define DES_DECRYPT 0
-
-#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */
-
-#define DES_KEY_SIZE 8
-
-/**
- * \brief DES context structure
- */
-typedef struct
-{
- int mode; /*!< encrypt/decrypt */
- unsigned long sk[32]; /*!< DES subkeys */
-}
-des_context;
-
-/**
- * \brief Triple-DES context structure
- */
-typedef struct
-{
- int mode; /*!< encrypt/decrypt */
- unsigned long sk[96]; /*!< 3DES subkeys */
-}
-des3_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Set key parity on the given key to odd.
- *
- * DES keys are 56 bits long, but each byte is padded with
- * a parity bit to allow verification.
- *
- * \param key 8-byte secret key
- */
-void des_key_set_parity( unsigned char key[DES_KEY_SIZE] );
-
-/**
- * \brief Check that key parity on the given key is odd.
- *
- * DES keys are 56 bits long, but each byte is padded with
- * a parity bit to allow verification.
- *
- * \param key 8-byte secret key
- *
- * \return 0 is parity was ok, 1 if parity was not correct.
- */
-int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] );
-
-/**
- * \brief Check that key is not a weak or semi-weak DES key
- *
- * \param key 8-byte secret key
- *
- * \return 0 if no weak key was found, 1 if a weak key was identified.
- */
-int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] );
-
-/**
- * \brief DES key schedule (56-bit, encryption)
- *
- * \param ctx DES context to be initialized
- * \param key 8-byte secret key
- *
- * \return 0
- */
-int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
-
-/**
- * \brief DES key schedule (56-bit, decryption)
- *
- * \param ctx DES context to be initialized
- * \param key 8-byte secret key
- *
- * \return 0
- */
-int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
-
-/**
- * \brief Triple-DES key schedule (112-bit, encryption)
- *
- * \param ctx 3DES context to be initialized
- * \param key 16-byte secret key
- *
- * \return 0
- */
-int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
-
-/**
- * \brief Triple-DES key schedule (112-bit, decryption)
- *
- * \param ctx 3DES context to be initialized
- * \param key 16-byte secret key
- *
- * \return 0
- */
-int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
-
-/**
- * \brief Triple-DES key schedule (168-bit, encryption)
- *
- * \param ctx 3DES context to be initialized
- * \param key 24-byte secret key
- *
- * \return 0
- */
-int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
-
-/**
- * \brief Triple-DES key schedule (168-bit, decryption)
- *
- * \param ctx 3DES context to be initialized
- * \param key 24-byte secret key
- *
- * \return 0
- */
-int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
-
-/**
- * \brief DES-ECB block encryption/decryption
- *
- * \param ctx DES context
- * \param input 64-bit input block
- * \param output 64-bit output block
- *
- * \return 0 if successful
- */
-int des_crypt_ecb( des_context *ctx,
- const unsigned char input[8],
- unsigned char output[8] );
-
-/**
- * \brief DES-CBC buffer encryption/decryption
- *
- * \param ctx DES context
- * \param mode DES_ENCRYPT or DES_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- */
-int des_crypt_cbc( des_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[8],
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief 3DES-ECB block encryption/decryption
- *
- * \param ctx 3DES context
- * \param input 64-bit input block
- * \param output 64-bit output block
- *
- * \return 0 if successful
- */
-int des3_crypt_ecb( des3_context *ctx,
- const unsigned char input[8],
- unsigned char output[8] );
-
-/**
- * \brief 3DES-CBC buffer encryption/decryption
- *
- * \param ctx 3DES context
- * \param mode DES_ENCRYPT or DES_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH
- */
-int des3_crypt_cbc( des3_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[8],
- const unsigned char *input,
- unsigned char *output );
-
-/*
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int des_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* des.h */
diff --git a/polarssl/src/include/polarssl/dhm.h b/polarssl/src/include/polarssl/dhm.h
deleted file mode 100644
index 0c8dd55..0000000
--- a/polarssl/src/include/polarssl/dhm.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/**
- * \file dhm.h
- *
- * \brief Diffie-Hellman-Merkle key exchange
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_DHM_H
-#define POLARSSL_DHM_H
-
-#include "bignum.h"
-
-/*
- * DHM Error codes
- */
-#define POLARSSL_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */
-#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */
-#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */
-#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */
-#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */
-#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */
-
-/**
- * \brief DHM context structure
- */
-typedef struct
-{
- size_t len; /*!< size(P) in chars */
- mpi P; /*!< prime modulus */
- mpi G; /*!< generator */
- mpi X; /*!< secret value */
- mpi GX; /*!< self = G^X mod P */
- mpi GY; /*!< peer = G^Y mod P */
- mpi K; /*!< key = GY^X mod P */
- mpi RP; /*!< cached R^2 mod P */
-}
-dhm_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Parse the ServerKeyExchange parameters
- *
- * \param ctx DHM context
- * \param p &(start of input buffer)
- * \param end end of buffer
- *
- * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
- */
-int dhm_read_params( dhm_context *ctx,
- unsigned char **p,
- const unsigned char *end );
-
-/**
- * \brief Setup and write the ServerKeyExchange parameters
- *
- * \param ctx DHM context
- * \param x_size private value size in bytes
- * \param output destination buffer
- * \param olen number of chars written
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- *
- * \note This function assumes that ctx->P and ctx->G
- * have already been properly set (for example
- * using mpi_read_string or mpi_read_binary).
- *
- * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
- */
-int dhm_make_params( dhm_context *ctx, int x_size,
- unsigned char *output, size_t *olen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
-
-/**
- * \brief Import the peer's public value G^Y
- *
- * \param ctx DHM context
- * \param input input buffer
- * \param ilen size of buffer
- *
- * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
- */
-int dhm_read_public( dhm_context *ctx,
- const unsigned char *input, size_t ilen );
-
-/**
- * \brief Create own private value X and export G^X
- *
- * \param ctx DHM context
- * \param x_size private value size in bytes
- * \param output destination buffer
- * \param olen must be equal to ctx->P.len
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- *
- * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
- */
-int dhm_make_public( dhm_context *ctx, int x_size,
- unsigned char *output, size_t olen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
-
-/**
- * \brief Derive and export the shared secret (G^Y)^X mod P
- *
- * \param ctx DHM context
- * \param output destination buffer
- * \param olen number of chars written
- *
- * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
- */
-int dhm_calc_secret( dhm_context *ctx,
- unsigned char *output, size_t *olen );
-
-/*
- * \brief Free the components of a DHM key
- */
-void dhm_free( dhm_context *ctx );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int dhm_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/polarssl/src/include/polarssl/entropy.h b/polarssl/src/include/polarssl/entropy.h
deleted file mode 100644
index 53bce41..0000000
--- a/polarssl/src/include/polarssl/entropy.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * \file entropy.h
- *
- * \brief Entropy accumulator implementation
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_ENTROPY_H
-#define POLARSSL_ENTROPY_H
-
-#include <string.h>
-
-#include "config.h"
-
-#include "sha4.h"
-#if defined(POLARSSL_HAVEGE_C)
-#include "havege.h"
-#endif
-
-#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */
-#define POLARSSL_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */
-#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */
-
-#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
-#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
-#define ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */
-
-#define ENTROPY_SOURCE_MANUAL ENTROPY_MAX_SOURCES
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Entropy poll callback pointer
- *
- * \param data Callback-specific data pointer
- * \param output Data to fill
- * \param len Maximum size to provide
- * \param olen The actual amount of bytes put into the buffer (Can be 0)
- *
- * \return 0 if no critical failures occurred,
- * POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise
- */
-typedef int (*f_source_ptr)(void *, unsigned char *, size_t, size_t *);
-
-/**
- * \brief Entropy source state
- */
-typedef struct
-{
- f_source_ptr f_source; /**< The entropy source callback */
- void * p_source; /**< The callback data pointer */
- size_t size; /**< Amount received */
- size_t threshold; /**< Minimum level required before release */
-}
-source_state;
-
-/**
- * \brief Entropy context structure
- */
-typedef struct
-{
- sha4_context accumulator;
- int source_count;
- source_state source[ENTROPY_MAX_SOURCES];
-#if defined(POLARSSL_HAVEGE_C)
- havege_state havege_data;
-#endif
-}
-entropy_context;
-
-/**
- * \brief Initialize the context
- *
- * \param ctx Entropy context to initialize
- */
-void entropy_init( entropy_context *ctx );
-
-/**
- * \brief Adds an entropy source to poll
- *
- * \param ctx Entropy context
- * \param f_source Entropy function
- * \param p_source Function data
- * \param threshold Minimum required from source before entropy is released
- * ( with entropy_func() )
- *
- * \return 0 if successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES
- */
-int entropy_add_source( entropy_context *ctx,
- f_source_ptr f_source, void *p_source,
- size_t threshold );
-
-/**
- * \brief Trigger an extra gather poll for the accumulator
- *
- * \param ctx Entropy context
- *
- * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
- */
-int entropy_gather( entropy_context *ctx );
-
-/**
- * \brief Retrieve entropy from the accumulator (Max ENTROPY_BLOCK_SIZE)
- *
- * \param data Entropy context
- * \param output Buffer to fill
- * \param len Length of buffer
- *
- * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
- */
-int entropy_func( void *data, unsigned char *output, size_t len );
-
-/**
- * \brief Add data to the accumulator manually
- *
- * \param ctx Entropy context
- * \param data Data to add
- * \param len Length of data
- *
- * \return 0 if successful
- */
-int entropy_update_manual( entropy_context *ctx,
- const unsigned char *data, size_t len );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* entropy.h */
diff --git a/polarssl/src/include/polarssl/entropy_poll.h b/polarssl/src/include/polarssl/entropy_poll.h
deleted file mode 100644
index 0116598..0000000
--- a/polarssl/src/include/polarssl/entropy_poll.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * \file entropy_poll.h
- *
- * \brief Platform-specific and custom entropy polling functions
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_ENTROPY_POLL_H
-#define POLARSSL_ENTROPY_POLL_H
-
-#include <string.h>
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Default thresholds for built-in sources
- */
-#define ENTROPY_MIN_PLATFORM 128 /**< Minimum for platform source */
-#define ENTROPY_MIN_HAVEGE 128 /**< Minimum for HAVEGE */
-#define ENTROPY_MIN_HARDCLOCK 32 /**< Minimum for hardclock() */
-
-#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
-/**
- * \brief Platform-specific entropy poll callback
- */
-int platform_entropy_poll( void *data,
- unsigned char *output, size_t len, size_t *olen );
-#endif
-
-#if defined(POLARSSL_HAVEGE_C)
-/**
- * \brief HAVEGE based entropy poll callback
- *
- * Requires an HAVEGE state as its data pointer.
- */
-int havege_poll( void *data,
- unsigned char *output, size_t len, size_t *olen );
-#endif
-
-#if defined(POLARSSL_TIMING_C)
-/**
- * \brief hardclock-based entropy poll callback
- */
-int hardclock_poll( void *data,
- unsigned char *output, size_t len, size_t *olen );
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* entropy_poll.h */
diff --git a/polarssl/src/include/polarssl/error.h b/polarssl/src/include/polarssl/error.h
deleted file mode 100644
index f3514df..0000000
--- a/polarssl/src/include/polarssl/error.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * \file error.h
- *
- * \brief Error to string translation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_ERROR_H
-#define POLARSSL_ERROR_H
-
-/**
- * Error code layout.
- *
- * Currently we try to keep all error codes within the negative space of 16
- * bytes signed integers to support all platforms (-0x0000 - -0x8000). In
- * addition we'd like to give two layers of information on the error if
- * possible.
- *
- * For that purpose the error codes are segmented in the following manner:
- *
- * 16 bit error code bit-segmentation
- *
- * 1 bit - Intentionally not used
- * 3 bits - High level module ID
- * 5 bits - Module-dependent error code
- * 6 bits - Low level module errors
- * 1 bit - Intentionally not used
- *
- * Low-level module errors (0x007E-0x0002)
- *
- * Module Nr Codes assigned
- * MPI 7 0x0002-0x0010
- * GCM 2 0x0012-0x0014
- * AES 2 0x0020-0x0022
- * CAMELLIA 2 0x0024-0x0026
- * XTEA 1 0x0028-0x0028
- * BASE64 2 0x002A-0x002C
- * PADLOCK 1 0x0030-0x0030
- * DES 1 0x0032-0x0032
- * CTR_DBRG 3 0x0034-0x003A
- * ENTROPY 3 0x003C-0x0040
- * NET 11 0x0042-0x0056
- * ASN1 7 0x0060-0x006C
- * MD2 1 0x0070-0x0070
- * MD4 1 0x0072-0x0072
- * MD5 1 0x0074-0x0074
- * SHA1 1 0x0076-0x0076
- * SHA2 1 0x0078-0x0078
- * SHA4 1 0x007A-0x007A
- *
- * High-level module nr (3 bits - 0x1...-0x8...)
- * Name ID Nr of Errors
- * PEM 1 8
- * X509 2 21
- * DHM 3 6
- * RSA 4 9
- * MD 5 4
- * CIPHER 6 5
- * SSL 7 30
- *
- * Module dependent error code (5 bits 0x.08.-0x.F8.)
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Translate a PolarSSL error code into a string representation,
- * Result is truncated if necessary and always includes a terminating
- * null byte.
- *
- * \param errnum error code
- * \param buffer buffer to place representation in
- * \param buflen length of the buffer
- */
-void error_strerror( int errnum, char *buffer, size_t buflen );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* error.h */
diff --git a/polarssl/src/include/polarssl/gcm.h b/polarssl/src/include/polarssl/gcm.h
deleted file mode 100644
index 2f88c70..0000000
--- a/polarssl/src/include/polarssl/gcm.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- * \file gcm.h
- *
- * \brief Galois/Counter mode for AES
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_GCM_H
-#define POLARSSL_GCM_H
-
-#include "aes.h"
-
-#include <stdint.h>
-
-#define GCM_ENCRYPT 1
-#define GCM_DECRYPT 0
-
-#define POLARSSL_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
-#define POLARSSL_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
-
-/**
- * \brief GCM context structure
- */
-typedef struct {
- aes_context aes_ctx; /*!< AES context used */
- uint64_t HL[16]; /*!< Precalculated HTable */
- uint64_t HH[16]; /*!< Precalculated HTable */
-}
-gcm_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief GCM initialization (encryption)
- *
- * \param ctx GCM context to be initialized
- * \param key encryption key
- * \param keysize must be 128, 192 or 256
- *
- * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
- */
-int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize );
-
-/**
- * \brief GCM buffer encryption/decryption using AES
- *
- * \note On encryption, the output buffer can be the same as the input buffer.
- * On decryption, the output buffer cannot be the same as input buffer.
- * If buffers overlap, the output buffer must trail at least 8 bytes
- * behind the input buffer.
- *
- * \param ctx GCM context
- * \param mode GCM_ENCRYPT or GCM_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector
- * \param iv_len length of IV
- * \param add additional data
- * \param add_len length of additional data
- * \param input buffer holding the input data
- * \param output buffer for holding the output data
- * \param tag_len length of the tag to generate
- * \param tag buffer for holding the tag
- *
- * \return 0 if successful
- */
-int gcm_crypt_and_tag( gcm_context *ctx,
- int mode,
- size_t length,
- const unsigned char *iv,
- size_t iv_len,
- const unsigned char *add,
- size_t add_len,
- const unsigned char *input,
- unsigned char *output,
- size_t tag_len,
- unsigned char *tag );
-
-/**
- * \brief GCM buffer authenticated decryption using AES
- *
- * \note On decryption, the output buffer cannot be the same as input buffer.
- * If buffers overlap, the output buffer must trail at least 8 bytes
- * behind the input buffer.
- *
- * \param ctx GCM context
- * \param length length of the input data
- * \param iv initialization vector
- * \param iv_len length of IV
- * \param add additional data
- * \param add_len length of additional data
- * \param tag buffer holding the tag
- * \param tag_len length of the tag
- * \param input buffer holding the input data
- * \param output buffer for holding the output data
- *
- * \return 0 if successful and authenticated,
- * POLARSSL_ERR_GCM_AUTH_FAILED if tag does not match
- */
-int gcm_auth_decrypt( gcm_context *ctx,
- size_t length,
- const unsigned char *iv,
- size_t iv_len,
- const unsigned char *add,
- size_t add_len,
- const unsigned char *tag,
- size_t tag_len,
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int gcm_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* gcm.h */
diff --git a/polarssl/src/include/polarssl/havege.h b/polarssl/src/include/polarssl/havege.h
deleted file mode 100644
index 53c4f38..0000000
--- a/polarssl/src/include/polarssl/havege.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * \file havege.h
- *
- * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_HAVEGE_H
-#define POLARSSL_HAVEGE_H
-
-#include <string.h>
-
-#define COLLECT_SIZE 1024
-
-/**
- * \brief HAVEGE state structure
- */
-typedef struct
-{
- int PT1, PT2, offset[2];
- int pool[COLLECT_SIZE];
- int WALK[8192];
-}
-havege_state;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief HAVEGE initialization
- *
- * \param hs HAVEGE state to be initialized
- */
-void havege_init( havege_state *hs );
-
-/**
- * \brief HAVEGE rand function
- *
- * \param p_rng A HAVEGE state
- * \param output Buffer to fill
- * \param len Length of buffer
- *
- * \return 0
- */
-int havege_random( void *p_rng, unsigned char *output, size_t len );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* havege.h */
diff --git a/polarssl/src/include/polarssl/md.h b/polarssl/src/include/polarssl/md.h
deleted file mode 100644
index 88596cb..0000000
--- a/polarssl/src/include/polarssl/md.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/**
- * \file md.h
- *
- * \brief Generic message digest wrapper
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_MD_H
-#define POLARSSL_MD_H
-
-#include <string.h>
-
-#if defined(_MSC_VER) && !defined(inline)
-#define inline _inline
-#else
-#if defined(__ARMCC_VERSION) && !defined(inline)
-#define inline __inline
-#endif /* __ARMCC_VERSION */
-#endif /*_MSC_VER */
-
-#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */
-#define POLARSSL_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
-#define POLARSSL_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
-#define POLARSSL_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */
-
-typedef enum {
- POLARSSL_MD_NONE=0,
- POLARSSL_MD_MD2,
- POLARSSL_MD_MD4,
- POLARSSL_MD_MD5,
- POLARSSL_MD_SHA1,
- POLARSSL_MD_SHA224,
- POLARSSL_MD_SHA256,
- POLARSSL_MD_SHA384,
- POLARSSL_MD_SHA512,
-} md_type_t;
-
-#define POLARSSL_MD_MAX_SIZE 64 /* longest known is SHA512 */
-
-/**
- * Message digest information. Allows message digest functions to be called
- * in a generic way.
- */
-typedef struct {
- /** Digest identifier */
- md_type_t type;
-
- /** Name of the message digest */
- const char * name;
-
- /** Output length of the digest function */
- int size;
-
- /** Digest initialisation function */
- void (*starts_func)( void *ctx );
-
- /** Digest update function */
- void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
-
- /** Digest finalisation function */
- void (*finish_func)( void *ctx, unsigned char *output );
-
- /** Generic digest function */
- void (*digest_func)( const unsigned char *input, size_t ilen,
- unsigned char *output );
-
- /** Generic file digest function */
- int (*file_func)( const char *path, unsigned char *output );
-
- /** HMAC Initialisation function */
- void (*hmac_starts_func)( void *ctx, const unsigned char *key, size_t keylen );
-
- /** HMAC update function */
- void (*hmac_update_func)( void *ctx, const unsigned char *input, size_t ilen );
-
- /** HMAC finalisation function */
- void (*hmac_finish_func)( void *ctx, unsigned char *output);
-
- /** HMAC context reset function */
- void (*hmac_reset_func)( void *ctx );
-
- /** Generic HMAC function */
- void (*hmac_func)( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char *output );
-
- /** Allocate a new context */
- void * (*ctx_alloc_func)( void );
-
- /** Free the given context */
- void (*ctx_free_func)( void *ctx );
-
-} md_info_t;
-
-/**
- * Generic message digest context.
- */
-typedef struct {
- /** Information about the associated message digest */
- const md_info_t *md_info;
-
- /** Digest-specific context */
- void *md_ctx;
-} md_context_t;
-
-#define MD_CONTEXT_T_INIT { \
- NULL, /* md_info */ \
- NULL, /* md_ctx */ \
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Returns the list of digests supported by the generic digest module.
- *
- * \return a statically allocated array of digests, the last entry
- * is 0.
- */
-const int *md_list( void );
-
-/**
- * \brief Returns the message digest information associated with the
- * given digest name.
- *
- * \param md_name Name of the digest to search for.
- *
- * \return The message digest information associated with md_name or
- * NULL if not found.
- */
-const md_info_t *md_info_from_string( const char *md_name );
-
-/**
- * \brief Returns the message digest information associated with the
- * given digest type.
- *
- * \param md_type type of digest to search for.
- *
- * \return The message digest information associated with md_type or
- * NULL if not found.
- */
-const md_info_t *md_info_from_type( md_type_t md_type );
-
-/**
- * \brief Initialises and fills the message digest context structure with
- * the appropriate values.
- *
- * \param ctx context to initialise. May not be NULL. The
- * digest-specific context (ctx->md_ctx) must be NULL. It will
- * be allocated, and must be freed using md_free_ctx() later.
- * \param md_info message digest to use.
- *
- * \returns \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on
- * parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if
- * allocation of the digest-specific context failed.
- */
-int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
-
-/**
- * \brief Free the message-specific context of ctx. Freeing ctx itself
- * remains the responsibility of the caller.
- *
- * \param ctx Free the message-specific context
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_free_ctx( md_context_t *ctx );
-
-/**
- * \brief Returns the size of the message digest output.
- *
- * \param md_info message digest info
- *
- * \return size of the message digest output.
- */
-static inline unsigned char md_get_size( const md_info_t *md_info )
-{
- return md_info->size;
-}
-
-/**
- * \brief Returns the type of the message digest output.
- *
- * \param md_info message digest info
- *
- * \return type of the message digest output.
- */
-static inline md_type_t md_get_type( const md_info_t *md_info )
-{
- return md_info->type;
-}
-
-/**
- * \brief Returns the name of the message digest output.
- *
- * \param md_info message digest info
- *
- * \return name of the message digest output.
- */
-static inline const char *md_get_name( const md_info_t *md_info )
-{
- return md_info->name;
-}
-
-/**
- * \brief Set-up the given context for a new message digest
- *
- * \param ctx generic message digest context.
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_starts( md_context_t *ctx );
-
-/**
- * \brief Generic message digest process buffer
- *
- * \param ctx Generic message digest context
- * \param input buffer holding the datal
- * \param ilen length of the input data
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief Generic message digest final digest
- *
- * \param ctx Generic message digest context
- * \param output Generic message digest checksum result
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_finish( md_context_t *ctx, unsigned char *output );
-
-/**
- * \brief Output = message_digest( input buffer )
- *
- * \param md_info message digest info
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output Generic message digest checksum result
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
- unsigned char *output );
-
-/**
- * \brief Output = message_digest( file contents )
- *
- * \param md_info message digest info
- * \param path input file name
- * \param output generic message digest checksum result
- *
- * \return 0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen
- * failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed,
- * POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL.
- */
-int md_file( const md_info_t *md_info, const char *path, unsigned char *output );
-
-/**
- * \brief Generic HMAC context setup
- *
- * \param ctx HMAC context to be initialized
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen );
-
-/**
- * \brief Generic HMAC process buffer
- *
- * \param ctx HMAC context
- * \param input buffer holding the data
- * \param ilen length of the input data
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief Generic HMAC final digest
- *
- * \param ctx HMAC context
- * \param output Generic HMAC checksum result
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_hmac_finish( md_context_t *ctx, unsigned char *output);
-
-/**
- * \brief Generic HMAC context reset
- *
- * \param ctx HMAC context to be reset
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_hmac_reset( md_context_t *ctx );
-
-/**
- * \brief Output = Generic_HMAC( hmac key, input buffer )
- *
- * \param md_info message digest info
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output Generic HMAC-result
- *
- * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- * verification fails.
- */
-int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char *output );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* POLARSSL_MD_H */
diff --git a/polarssl/src/include/polarssl/md2.h b/polarssl/src/include/polarssl/md2.h
deleted file mode 100644
index 1f60470..0000000
--- a/polarssl/src/include/polarssl/md2.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/**
- * \file md2.h
- *
- * \brief MD2 message digest algorithm (hash function)
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_MD2_H
-#define POLARSSL_MD2_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_MD2_FILE_IO_ERROR -0x0070 /**< Read/write error in file. */
-
-/**
- * \brief MD2 context structure
- */
-typedef struct
-{
- unsigned char cksum[16]; /*!< checksum of the data block */
- unsigned char state[48]; /*!< intermediate digest state */
- unsigned char buffer[16]; /*!< data block being processed */
-
- unsigned char ipad[16]; /*!< HMAC: inner padding */
- unsigned char opad[16]; /*!< HMAC: outer padding */
- size_t left; /*!< amount of data in buffer */
-}
-md2_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief MD2 context setup
- *
- * \param ctx context to be initialized
- */
-void md2_starts( md2_context *ctx );
-
-/**
- * \brief MD2 process buffer
- *
- * \param ctx MD2 context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief MD2 final digest
- *
- * \param ctx MD2 context
- * \param output MD2 checksum result
- */
-void md2_finish( md2_context *ctx, unsigned char output[16] );
-
-/**
- * \brief Output = MD2( input buffer )
- *
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output MD2 checksum result
- */
-void md2( const unsigned char *input, size_t ilen, unsigned char output[16] );
-
-/**
- * \brief Output = MD2( file contents )
- *
- * \param path input file name
- * \param output MD2 checksum result
- *
- * \return 0 if successful, or POLARSSL_ERR_MD2_FILE_IO_ERROR
- */
-int md2_file( const char *path, unsigned char output[16] );
-
-/**
- * \brief MD2 HMAC context setup
- *
- * \param ctx HMAC context to be initialized
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- */
-void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen );
-
-/**
- * \brief MD2 HMAC process buffer
- *
- * \param ctx HMAC context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief MD2 HMAC final digest
- *
- * \param ctx HMAC context
- * \param output MD2 HMAC checksum result
- */
-void md2_hmac_finish( md2_context *ctx, unsigned char output[16] );
-
-/**
- * \brief MD2 HMAC context reset
- *
- * \param ctx HMAC context to be reset
- */
-void md2_hmac_reset( md2_context *ctx );
-
-/**
- * \brief Output = HMAC-MD2( hmac key, input buffer )
- *
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output HMAC-MD2 result
- */
-void md2_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[16] );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int md2_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* md2.h */
diff --git a/polarssl/src/include/polarssl/md4.h b/polarssl/src/include/polarssl/md4.h
deleted file mode 100644
index 2bd35ea..0000000
--- a/polarssl/src/include/polarssl/md4.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * \file md4.h
- *
- * \brief MD4 message digest algorithm (hash function)
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_MD4_H
-#define POLARSSL_MD4_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_MD4_FILE_IO_ERROR -0x0072 /**< Read/write error in file. */
-
-/**
- * \brief MD4 context structure
- */
-typedef struct
-{
- unsigned long total[2]; /*!< number of bytes processed */
- unsigned long state[4]; /*!< intermediate digest state */
- unsigned char buffer[64]; /*!< data block being processed */
-
- unsigned char ipad[64]; /*!< HMAC: inner padding */
- unsigned char opad[64]; /*!< HMAC: outer padding */
-}
-md4_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief MD4 context setup
- *
- * \param ctx context to be initialized
- */
-void md4_starts( md4_context *ctx );
-
-/**
- * \brief MD4 process buffer
- *
- * \param ctx MD4 context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief MD4 final digest
- *
- * \param ctx MD4 context
- * \param output MD4 checksum result
- */
-void md4_finish( md4_context *ctx, unsigned char output[16] );
-
-/**
- * \brief Output = MD4( input buffer )
- *
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output MD4 checksum result
- */
-void md4( const unsigned char *input, size_t ilen, unsigned char output[16] );
-
-/**
- * \brief Output = MD4( file contents )
- *
- * \param path input file name
- * \param output MD4 checksum result
- *
- * \return 0 if successful, or POLARSSL_ERR_MD4_FILE_IO_ERROR
- */
-int md4_file( const char *path, unsigned char output[16] );
-
-/**
- * \brief MD4 HMAC context setup
- *
- * \param ctx HMAC context to be initialized
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- */
-void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen );
-
-/**
- * \brief MD4 HMAC process buffer
- *
- * \param ctx HMAC context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief MD4 HMAC final digest
- *
- * \param ctx HMAC context
- * \param output MD4 HMAC checksum result
- */
-void md4_hmac_finish( md4_context *ctx, unsigned char output[16] );
-
-/**
- * \brief MD4 HMAC context reset
- *
- * \param ctx HMAC context to be reset
- */
-void md4_hmac_reset( md4_context *ctx );
-
-/**
- * \brief Output = HMAC-MD4( hmac key, input buffer )
- *
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output HMAC-MD4 result
- */
-void md4_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[16] );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int md4_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* md4.h */
diff --git a/polarssl/src/include/polarssl/md5.h b/polarssl/src/include/polarssl/md5.h
deleted file mode 100644
index 936e9c9..0000000
--- a/polarssl/src/include/polarssl/md5.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * \file md5.h
- *
- * \brief MD5 message digest algorithm (hash function)
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_MD5_H
-#define POLARSSL_MD5_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_MD5_FILE_IO_ERROR -0x0074 /**< Read/write error in file. */
-
-/**
- * \brief MD5 context structure
- */
-typedef struct
-{
- unsigned long total[2]; /*!< number of bytes processed */
- unsigned long state[4]; /*!< intermediate digest state */
- unsigned char buffer[64]; /*!< data block being processed */
-
- unsigned char ipad[64]; /*!< HMAC: inner padding */
- unsigned char opad[64]; /*!< HMAC: outer padding */
-}
-md5_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief MD5 context setup
- *
- * \param ctx context to be initialized
- */
-void md5_starts( md5_context *ctx );
-
-/**
- * \brief MD5 process buffer
- *
- * \param ctx MD5 context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief MD5 final digest
- *
- * \param ctx MD5 context
- * \param output MD5 checksum result
- */
-void md5_finish( md5_context *ctx, unsigned char output[16] );
-
-/**
- * \brief Output = MD5( input buffer )
- *
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output MD5 checksum result
- */
-void md5( const unsigned char *input, size_t ilen, unsigned char output[16] );
-
-/**
- * \brief Output = MD5( file contents )
- *
- * \param path input file name
- * \param output MD5 checksum result
- *
- * \return 0 if successful, or POLARSSL_ERR_MD5_FILE_IO_ERROR
- */
-int md5_file( const char *path, unsigned char output[16] );
-
-/**
- * \brief MD5 HMAC context setup
- *
- * \param ctx HMAC context to be initialized
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- */
-void md5_hmac_starts( md5_context *ctx,
- const unsigned char *key, size_t keylen );
-
-/**
- * \brief MD5 HMAC process buffer
- *
- * \param ctx HMAC context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void md5_hmac_update( md5_context *ctx,
- const unsigned char *input, size_t ilen );
-
-/**
- * \brief MD5 HMAC final digest
- *
- * \param ctx HMAC context
- * \param output MD5 HMAC checksum result
- */
-void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
-
-/**
- * \brief MD5 HMAC context reset
- *
- * \param ctx HMAC context to be reset
- */
-void md5_hmac_reset( md5_context *ctx );
-
-/**
- * \brief Output = HMAC-MD5( hmac key, input buffer )
- *
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output HMAC-MD5 result
- */
-void md5_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[16] );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int md5_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* md5.h */
diff --git a/polarssl/src/include/polarssl/md_wrap.h b/polarssl/src/include/polarssl/md_wrap.h
deleted file mode 100644
index 46849d0..0000000
--- a/polarssl/src/include/polarssl/md_wrap.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * \file md_wrap.h
- *
- * \brief Message digest wrappers.
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_MD_WRAP_H
-#define POLARSSL_MD_WRAP_H
-
-#include "config.h"
-#include "md.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(POLARSSL_MD2_C)
-extern const md_info_t md2_info;
-#endif
-#if defined(POLARSSL_MD4_C)
-extern const md_info_t md4_info;
-#endif
-#if defined(POLARSSL_MD5_C)
-extern const md_info_t md5_info;
-#endif
-#if defined(POLARSSL_SHA1_C)
-extern const md_info_t sha1_info;
-#endif
-#if defined(POLARSSL_SHA2_C)
-extern const md_info_t sha224_info;
-extern const md_info_t sha256_info;
-#endif
-#if defined(POLARSSL_SHA4_C)
-extern const md_info_t sha384_info;
-extern const md_info_t sha512_info;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* POLARSSL_MD_WRAP_H */
diff --git a/polarssl/src/include/polarssl/net.h b/polarssl/src/include/polarssl/net.h
deleted file mode 100644
index 88302ac..0000000
--- a/polarssl/src/include/polarssl/net.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * \file net.h
- *
- * \brief Network communication functions
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_NET_H
-#define POLARSSL_NET_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */
-#define POLARSSL_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */
-#define POLARSSL_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */
-#define POLARSSL_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */
-#define POLARSSL_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */
-#define POLARSSL_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */
-#define POLARSSL_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */
-#define POLARSSL_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */
-#define POLARSSL_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */
-#define POLARSSL_ERR_NET_WANT_READ -0x0052 /**< Connection requires a read call. */
-#define POLARSSL_ERR_NET_WANT_WRITE -0x0054 /**< Connection requires a write call. */
-
-#define POLARSSL_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Initiate a TCP connection with host:port
- *
- * \param fd Socket to use
- * \param host Host to connect to
- * \param port Port to connect to
- *
- * \return 0 if successful, or one of:
- * POLARSSL_ERR_NET_SOCKET_FAILED,
- * POLARSSL_ERR_NET_UNKNOWN_HOST,
- * POLARSSL_ERR_NET_CONNECT_FAILED
- */
-int net_connect( int *fd, const char *host, int port );
-
-/**
- * \brief Create a listening socket on bind_ip:port.
- * If bind_ip == NULL, all interfaces are binded.
- *
- * \param fd Socket to use
- * \param bind_ip IP to bind to, can be NULL
- * \param port Port number to use
- *
- * \return 0 if successful, or one of:
- * POLARSSL_ERR_NET_SOCKET_FAILED,
- * POLARSSL_ERR_NET_BIND_FAILED,
- * POLARSSL_ERR_NET_LISTEN_FAILED
- */
-int net_bind( int *fd, const char *bind_ip, int port );
-
-/**
- * \brief Accept a connection from a remote client
- *
- * \param bind_fd Relevant socket
- * \param client_fd Will contain the connected client socket
- * \param client_ip Will contain the client IP address
- *
- * \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or
- * POLARSSL_ERR_NET_WOULD_BLOCK is bind_fd was set to
- * non-blocking and accept() is blocking.
- */
-int net_accept( int bind_fd, int *client_fd, void *client_ip );
-
-/**
- * \brief Set the socket blocking
- *
- * \param fd Socket to set
- *
- * \return 0 if successful, or a non-zero error code
- */
-int net_set_block( int fd );
-
-/**
- * \brief Set the socket non-blocking
- *
- * \param fd Socket to set
- *
- * \return 0 if successful, or a non-zero error code
- */
-int net_set_nonblock( int fd );
-
-/**
- * \brief Portable usleep helper
- *
- * \param usec Amount of microseconds to sleep
- *
- * \note Real amount of time slept will not be less than
- * select()'s timeout granularity (typically, 10ms).
- */
-void net_usleep( unsigned long usec );
-
-/**
- * \brief Read at most 'len' characters. If no error occurs,
- * the actual amount read is returned.
- *
- * \param ctx Socket
- * \param buf The buffer to write to
- * \param len Maximum length of the buffer
- *
- * \return This function returns the number of bytes received,
- * or a non-zero error code; POLARSSL_ERR_NET_WANT_READ
- * indicates read() is blocking.
- */
-int net_recv( void *ctx, unsigned char *buf, size_t len );
-
-/**
- * \brief Write at most 'len' characters. If no error occurs,
- * the actual amount read is returned.
- *
- * \param ctx Socket
- * \param buf The buffer to read from
- * \param len The length of the buffer
- *
- * \return This function returns the number of bytes sent,
- * or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE
- * indicates write() is blocking.
- */
-int net_send( void *ctx, const unsigned char *buf, size_t len );
-
-/**
- * \brief Gracefully shutdown the connection
- *
- * \param fd The socket to close
- */
-void net_close( int fd );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* net.h */
diff --git a/polarssl/src/include/polarssl/openssl.h b/polarssl/src/include/polarssl/openssl.h
deleted file mode 100644
index 62609a2..0000000
--- a/polarssl/src/include/polarssl/openssl.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * \file openssl.h
- *
- * \brief OpenSSL wrapper (definitions, inline functions).
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * OpenSSL wrapper contributed by David Barett
- */
-#ifndef POLARSSL_OPENSSL_H
-#define POLARSSL_OPENSSL_H
-
-#include "aes.h"
-#include "md5.h"
-#include "rsa.h"
-#include "sha1.h"
-
-#define AES_SIZE 16
-#define AES_BLOCK_SIZE 16
-#define AES_KEY aes_context
-#define MD5_CTX md5_context
-#define SHA_CTX sha1_context
-
-#define SHA1_Init( CTX ) \
- sha1_starts( (CTX) )
-#define SHA1_Update( CTX, BUF, LEN ) \
- sha1_update( (CTX), (unsigned char *)(BUF), (LEN) )
-#define SHA1_Final( OUT, CTX ) \
- sha1_finish( (CTX), (OUT) )
-
-#define MD5_Init( CTX ) \
- md5_starts( (CTX) )
-#define MD5_Update( CTX, BUF, LEN ) \
- md5_update( (CTX), (unsigned char *)(BUF), (LEN) )
-#define MD5_Final( OUT, CTX ) \
- md5_finish( (CTX), (OUT) )
-
-#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \
- aes_setkey_enc( (CTX), (KEY), (KEYSIZE) )
-#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \
- aes_setkey_dec( (CTX), (KEY), (KEYSIZE) )
-#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \
- aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) )
-
-/*
- * RSA stuff follows. TODO: needs cleanup
- */
-inline int __RSA_Passthrough( void *output, void *input, int size )
-{
- memcpy( output, input, size );
- return size;
-}
-
-inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr,
- int len )
-{
- unsigned char *buffer = *(unsigned char **) bufptr;
- rsa_context *rsa;
-
- /*
- * Not a general-purpose parser: only parses public key from *exactly*
- * openssl genrsa -out privkey.pem 512 (or 1024)
- * openssl rsa -in privkey.pem -out privatekey.der -outform der
- * openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout
- *
- * TODO: make a general-purpose parse
- */
- if( ignore != 0 || ( len != 94 && len != 162 ) )
- return( 0 );
-
- rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) );
- if( rsa == NULL )
- return( 0 );
-
- memset( rsa, 0, sizeof( rsa_context ) );
-
- if( ( len == 94 &&
- mpi_read_binary( &rsa->N, &buffer[ 25], 64 ) == 0 &&
- mpi_read_binary( &rsa->E, &buffer[ 91], 3 ) == 0 ) ||
- ( len == 162 &&
- mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) &&
- mpi_read_binary( &rsa->E, &buffer[159], 3 ) == 0 )
- {
- /*
- * key read successfully
- */
- rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3;
- return( rsa );
- }
- else
- {
- memset( rsa, 0, sizeof( rsa_context ) );
- free( rsa );
- return( 0 );
- }
-}
-
-#define RSA rsa_context
-#define RSA_PKCS1_PADDING 1 /* ignored; always encrypt with this */
-#define RSA_size( CTX ) (CTX)->len
-#define RSA_free( CTX ) rsa_free( CTX )
-#define ERR_get_error( ) "ERR_get_error() not supported"
-#define RSA_blinding_off( IGNORE )
-
-#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */
-
-inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC, &outsize, input, output ) ) return outsize; else return -1; }
-inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; }
-inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC, size, input, output ) ) return RSA_size(key); else return -1; }
-inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; }
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* openssl.h */
diff --git a/polarssl/src/include/polarssl/padlock.h b/polarssl/src/include/polarssl/padlock.h
deleted file mode 100644
index ce13570..0000000
--- a/polarssl/src/include/polarssl/padlock.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * \file padlock.h
- *
- * \brief VIA PadLock ACE for HW encryption/decryption supported by some processors
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_PADLOCK_H
-#define POLARSSL_PADLOCK_H
-
-#include "aes.h"
-
-#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */
-
-#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
-
-#ifndef POLARSSL_HAVE_X86
-#define POLARSSL_HAVE_X86
-#endif
-
-#define PADLOCK_RNG 0x000C
-#define PADLOCK_ACE 0x00C0
-#define PADLOCK_PHE 0x0C00
-#define PADLOCK_PMM 0x3000
-
-#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15))
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief PadLock detection routine
- *
- * \param The feature to detect
- *
- * \return 1 if CPU has support for the feature, 0 otherwise
- */
-int padlock_supports( int feature );
-
-/**
- * \brief PadLock AES-ECB block en(de)cryption
- *
- * \param ctx AES context
- * \param mode AES_ENCRYPT or AES_DECRYPT
- * \param input 16-byte input block
- * \param output 16-byte output block
- *
- * \return 0 if success, 1 if operation failed
- */
-int padlock_xcryptecb( aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] );
-
-/**
- * \brief PadLock AES-CBC buffer en(de)cryption
- *
- * \param ctx AES context
- * \param mode AES_ENCRYPT or AES_DECRYPT
- * \param length length of the input data
- * \param iv initialization vector (updated after use)
- * \param input buffer holding the input data
- * \param output buffer holding the output data
- *
- * \return 0 if success, 1 if operation failed
- */
-int padlock_xcryptcbc( aes_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HAVE_X86 */
-
-#endif /* padlock.h */
diff --git a/polarssl/src/include/polarssl/pem.h b/polarssl/src/include/polarssl/pem.h
deleted file mode 100644
index 1505401..0000000
--- a/polarssl/src/include/polarssl/pem.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * \file pem.h
- *
- * \brief Privacy Enhanced Mail (PEM) decoding
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_PEM_H
-#define POLARSSL_PEM_H
-
-#include <string.h>
-
-/**
- * \name PEM Error codes
- * These error codes are returned in case of errors reading the
- * PEM data.
- * \{
- */
-#define POLARSSL_ERR_PEM_NO_HEADER_PRESENT -0x1080 /**< No PEM header found. */
-#define POLARSSL_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */
-#define POLARSSL_ERR_PEM_MALLOC_FAILED -0x1180 /**< Failed to allocate memory. */
-#define POLARSSL_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */
-#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */
-#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */
-#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */
-#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */
-/* \} name */
-
-/**
- * \brief PEM context structure
- */
-typedef struct
-{
- unsigned char *buf; /*!< buffer for decoded data */
- size_t buflen; /*!< length of the buffer */
- unsigned char *info; /*!< buffer for extra header information */
-}
-pem_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief PEM context setup
- *
- * \param ctx context to be initialized
- */
-void pem_init( pem_context *ctx );
-
-/**
- * \brief Read a buffer for PEM information and store the resulting
- * data into the specified context buffers.
- *
- * \param ctx context to use
- * \param header header string to seek and expect
- * \param footer footer string to seek and expect
- * \param data source data to look in
- * \param pwd password for decryption (can be NULL)
- * \param pwdlen length of password
- * \param use_len destination for total length used
- *
- * \return 0 on success, ior a specific PEM error code
- */
-int pem_read_buffer( pem_context *ctx, char *header, char *footer,
- const unsigned char *data,
- const unsigned char *pwd,
- size_t pwdlen, size_t *use_len );
-
-/**
- * \brief PEM context memory freeing
- *
- * \param ctx context to be freed
- */
-void pem_free( pem_context *ctx );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* pem.h */
diff --git a/polarssl/src/include/polarssl/pkcs11.h b/polarssl/src/include/polarssl/pkcs11.h
deleted file mode 100644
index a65a72e..0000000
--- a/polarssl/src/include/polarssl/pkcs11.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * \file pkcs11.h
- *
- * \brief Wrapper for PKCS#11 library libpkcs11-helper
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_PKCS11_H
-#define POLARSSL_PKCS11_H
-
-#include "config.h"
-
-#if defined(POLARSSL_PKCS11_C)
-
-#include "x509.h"
-
-#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
-
-/**
- * Context for PKCS #11 private keys.
- */
-typedef struct {
- pkcs11h_certificate_t pkcs11h_cert;
- int len;
-} pkcs11_context;
-
-/**
- * Fill in a PolarSSL certificate, based on the given PKCS11 helper certificate.
- *
- * \param cert X.509 certificate to fill
- * \param pkcs11h_cert PKCS #11 helper certificate
- *
- * \return 0 on success.
- */
-int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11h_cert );
-
-/**
- * Initialise a pkcs11_context, storing the given certificate. Note that the
- * pkcs11_context will take over control of the certificate, freeing it when
- * done.
- *
- * \param priv_key Private key structure to fill.
- * \param pkcs11_cert PKCS #11 helper certificate
- *
- * \return 0 on success
- */
-int pkcs11_priv_key_init( pkcs11_context *priv_key,
- pkcs11h_certificate_t pkcs11_cert );
-
-/**
- * Free the contents of the given private key context. Note that the structure
- * itself is not freed.
- *
- * \param priv_key Private key structure to cleanup
- */
-void pkcs11_priv_key_free( pkcs11_context *priv_key );
-
-/**
- * \brief Do an RSA private key decrypt, then remove the message padding
- *
- * \param ctx PKCS #11 context
- * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature
- * \param input buffer holding the encrypted data
- * \param output buffer that will hold the plaintext
- * \param olen will contain the plaintext length
- * \param output_max_len maximum length of the output buffer
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note The output buffer must be as large as the size
- * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
- * an error is thrown.
- */
-int pkcs11_decrypt( pkcs11_context *ctx,
- int mode, size_t *olen,
- const unsigned char *input,
- unsigned char *output,
- unsigned int output_max_len );
-
-/**
- * \brief Do a private RSA to sign a message digest
- *
- * \param ctx PKCS #11 context
- * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature
- * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
- * \param hashlen message digest length (for SIG_RSA_RAW only)
- * \param hash buffer holding the message digest
- * \param sig buffer that will hold the ciphertext
- *
- * \return 0 if the signing operation was successful,
- * or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note The "sig" buffer must be as large as the size
- * of ctx->N (eg. 128 bytes if RSA-1024 is used).
- */
-int pkcs11_sign( pkcs11_context *ctx,
- int mode,
- int hash_id,
- unsigned int hashlen,
- const unsigned char *hash,
- unsigned char *sig );
-
-#endif /* POLARSSL_PKCS11_C */
-
-#endif /* POLARSSL_PKCS11_H */
diff --git a/polarssl/src/include/polarssl/rsa.h b/polarssl/src/include/polarssl/rsa.h
deleted file mode 100644
index 513b037..0000000
--- a/polarssl/src/include/polarssl/rsa.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/**
- * \file rsa.h
- *
- * \brief The RSA public-key cryptosystem
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_RSA_H
-#define POLARSSL_RSA_H
-
-#include "bignum.h"
-
-/*
- * RSA Error codes
- */
-#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */
-#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */
-#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */
-#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */
-#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */
-#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */
-#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
-#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
-#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */
-
-/*
- * PKCS#1 constants
- */
-#define SIG_RSA_RAW 0
-#define SIG_RSA_MD2 2
-#define SIG_RSA_MD4 3
-#define SIG_RSA_MD5 4
-#define SIG_RSA_SHA1 5
-#define SIG_RSA_SHA224 14
-#define SIG_RSA_SHA256 11
-#define SIG_RSA_SHA384 12
-#define SIG_RSA_SHA512 13
-
-#define RSA_PUBLIC 0
-#define RSA_PRIVATE 1
-
-#define RSA_PKCS_V15 0
-#define RSA_PKCS_V21 1
-
-#define RSA_SIGN 1
-#define RSA_CRYPT 2
-
-#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30"
-#define ASN1_STR_NULL "\x05"
-#define ASN1_STR_OID "\x06"
-#define ASN1_STR_OCTET_STRING "\x04"
-
-#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
-#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a"
-#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
-
-#define OID_ISO_MEMBER_BODIES "\x2a"
-#define OID_ISO_IDENTIFIED_ORG "\x2b"
-
-/*
- * ISO Member bodies OID parts
- */
-#define OID_COUNTRY_US "\x86\x48"
-#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d"
-
-/*
- * ISO Identified organization OID parts
- */
-#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a"
-
-/*
- * DigestInfo ::= SEQUENCE {
- * digestAlgorithm DigestAlgorithmIdentifier,
- * digest Digest }
- *
- * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * Digest ::= OCTET STRING
- */
-#define ASN1_HASH_MDX \
-( \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \
- ASN1_STR_OID "\x08" \
- OID_DIGEST_ALG_MDX \
- ASN1_STR_NULL "\x00" \
- ASN1_STR_OCTET_STRING "\x10" \
-)
-
-#define ASN1_HASH_SHA1 \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \
- ASN1_STR_OID "\x05" \
- OID_HASH_ALG_SHA1 \
- ASN1_STR_NULL "\x00" \
- ASN1_STR_OCTET_STRING "\x14"
-
-#define ASN1_HASH_SHA1_ALT \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \
- ASN1_STR_OID "\x05" \
- OID_HASH_ALG_SHA1 \
- ASN1_STR_OCTET_STRING "\x14"
-
-#define ASN1_HASH_SHA2X \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \
- ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \
- ASN1_STR_OID "\x09" \
- OID_HASH_ALG_SHA2X \
- ASN1_STR_NULL "\x00" \
- ASN1_STR_OCTET_STRING "\x00"
-
-/**
- * \brief RSA context structure
- */
-typedef struct
-{
- int ver; /*!< always 0 */
- size_t len; /*!< size(N) in chars */
-
- mpi N; /*!< public modulus */
- mpi E; /*!< public exponent */
-
- mpi D; /*!< private exponent */
- mpi P; /*!< 1st prime factor */
- mpi Q; /*!< 2nd prime factor */
- mpi DP; /*!< D % (P - 1) */
- mpi DQ; /*!< D % (Q - 1) */
- mpi QP; /*!< 1 / (Q % P) */
-
- mpi RN; /*!< cached R^2 mod N */
- mpi RP; /*!< cached R^2 mod P */
- mpi RQ; /*!< cached R^2 mod Q */
-
- int padding; /*!< RSA_PKCS_V15 for 1.5 padding and
- RSA_PKCS_v21 for OAEP/PSS */
- int hash_id; /*!< Hash identifier of md_type_t as
- specified in the md.h header file
- for the EME-OAEP and EMSA-PSS
- encoding */
-}
-rsa_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief Initialize an RSA context
- *
- * \param ctx RSA context to be initialized
- * \param padding RSA_PKCS_V15 or RSA_PKCS_V21
- * \param hash_id RSA_PKCS_V21 hash identifier
- *
- * \note The hash_id parameter is actually ignored
- * when using RSA_PKCS_V15 padding.
- */
-void rsa_init( rsa_context *ctx,
- int padding,
- int hash_id);
-
-/**
- * \brief Generate an RSA keypair
- *
- * \param ctx RSA context that will hold the key
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- * \param nbits size of the public key in bits
- * \param exponent public exponent (e.g., 65537)
- *
- * \note rsa_init() must be called beforehand to setup
- * the RSA context.
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- */
-int rsa_gen_key( rsa_context *ctx,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng,
- unsigned int nbits, int exponent );
-
-/**
- * \brief Check a public RSA key
- *
- * \param ctx RSA context to be checked
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- */
-int rsa_check_pubkey( const rsa_context *ctx );
-
-/**
- * \brief Check a private RSA key
- *
- * \param ctx RSA context to be checked
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- */
-int rsa_check_privkey( const rsa_context *ctx );
-
-/**
- * \brief Do an RSA public key operation
- *
- * \param ctx RSA context
- * \param input input buffer
- * \param output output buffer
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note This function does NOT take care of message
- * padding. Also, be sure to set input[0] = 0 or assure that
- * input is smaller than N.
- *
- * \note The input and output buffers must be large
- * enough (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_public( rsa_context *ctx,
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief Do an RSA private key operation
- *
- * \param ctx RSA context
- * \param input input buffer
- * \param output output buffer
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note The input and output buffers must be large
- * enough (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_private( rsa_context *ctx,
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief Add the message padding, then do an RSA operation
- *
- * \param ctx RSA context
- * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
- * \param p_rng RNG parameter
- * \param mode RSA_PUBLIC or RSA_PRIVATE
- * \param ilen contains the plaintext length
- * \param input buffer holding the data to be encrypted
- * \param output buffer that will hold the ciphertext
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note The output buffer must be as large as the size
- * of ctx->N (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_pkcs1_encrypt( rsa_context *ctx,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng,
- int mode, size_t ilen,
- const unsigned char *input,
- unsigned char *output );
-
-/**
- * \brief Do an RSA operation, then remove the message padding
- *
- * \param ctx RSA context
- * \param mode RSA_PUBLIC or RSA_PRIVATE
- * \param olen will contain the plaintext length
- * \param input buffer holding the encrypted data
- * \param output buffer that will hold the plaintext
- * \param output_max_len maximum length of the output buffer
- *
- * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note The output buffer must be as large as the size
- * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
- * an error is thrown.
- */
-int rsa_pkcs1_decrypt( rsa_context *ctx,
- int mode, size_t *olen,
- const unsigned char *input,
- unsigned char *output,
- size_t output_max_len );
-
-/**
- * \brief Do a private RSA to sign a message digest
- *
- * \param ctx RSA context
- * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
- * \param p_rng RNG parameter
- * \param mode RSA_PUBLIC or RSA_PRIVATE
- * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
- * \param hashlen message digest length (for SIG_RSA_RAW only)
- * \param hash buffer holding the message digest
- * \param sig buffer that will hold the ciphertext
- *
- * \return 0 if the signing operation was successful,
- * or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note The "sig" buffer must be as large as the size
- * of ctx->N (eg. 128 bytes if RSA-1024 is used).
- *
- * \note In case of PKCS#1 v2.1 encoding keep in mind that
- * the hash_id in the RSA context is the one used for the
- * encoding. hash_id in the function call is the type of hash
- * that is encoded. According to RFC 3447 it is advised to
- * keep both hashes the same.
- */
-int rsa_pkcs1_sign( rsa_context *ctx,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng,
- int mode,
- int hash_id,
- unsigned int hashlen,
- const unsigned char *hash,
- unsigned char *sig );
-
-/**
- * \brief Do a public RSA and check the message digest
- *
- * \param ctx points to an RSA public key
- * \param mode RSA_PUBLIC or RSA_PRIVATE
- * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
- * \param hashlen message digest length (for SIG_RSA_RAW only)
- * \param hash buffer holding the message digest
- * \param sig buffer holding the ciphertext
- *
- * \return 0 if the verify operation was successful,
- * or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note The "sig" buffer must be as large as the size
- * of ctx->N (eg. 128 bytes if RSA-1024 is used).
- *
- * \note In case of PKCS#1 v2.1 encoding keep in mind that
- * the hash_id in the RSA context is the one used for the
- * verification. hash_id in the function call is the type of hash
- * that is verified. According to RFC 3447 it is advised to
- * keep both hashes the same.
- */
-int rsa_pkcs1_verify( rsa_context *ctx,
- int mode,
- int hash_id,
- unsigned int hashlen,
- const unsigned char *hash,
- unsigned char *sig );
-
-/**
- * \brief Free the components of an RSA key
- *
- * \param ctx RSA Context to free
- */
-void rsa_free( rsa_context *ctx );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int rsa_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* rsa.h */
diff --git a/polarssl/src/include/polarssl/sha1.h b/polarssl/src/include/polarssl/sha1.h
deleted file mode 100644
index 0d5e67e..0000000
--- a/polarssl/src/include/polarssl/sha1.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * \file sha1.h
- *
- * \brief SHA-1 cryptographic hash function
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_SHA1_H
-#define POLARSSL_SHA1_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
-
-/**
- * \brief SHA-1 context structure
- */
-typedef struct
-{
- unsigned long total[2]; /*!< number of bytes processed */
- unsigned long state[5]; /*!< intermediate digest state */
- unsigned char buffer[64]; /*!< data block being processed */
-
- unsigned char ipad[64]; /*!< HMAC: inner padding */
- unsigned char opad[64]; /*!< HMAC: outer padding */
-}
-sha1_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief SHA-1 context setup
- *
- * \param ctx context to be initialized
- */
-void sha1_starts( sha1_context *ctx );
-
-/**
- * \brief SHA-1 process buffer
- *
- * \param ctx SHA-1 context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief SHA-1 final digest
- *
- * \param ctx SHA-1 context
- * \param output SHA-1 checksum result
- */
-void sha1_finish( sha1_context *ctx, unsigned char output[20] );
-
-/**
- * \brief Output = SHA-1( input buffer )
- *
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output SHA-1 checksum result
- */
-void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
-
-/**
- * \brief Output = SHA-1( file contents )
- *
- * \param path input file name
- * \param output SHA-1 checksum result
- *
- * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
- */
-int sha1_file( const char *path, unsigned char output[20] );
-
-/**
- * \brief SHA-1 HMAC context setup
- *
- * \param ctx HMAC context to be initialized
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- */
-void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
-
-/**
- * \brief SHA-1 HMAC process buffer
- *
- * \param ctx HMAC context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief SHA-1 HMAC final digest
- *
- * \param ctx HMAC context
- * \param output SHA-1 HMAC checksum result
- */
-void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
-
-/**
- * \brief SHA-1 HMAC context reset
- *
- * \param ctx HMAC context to be reset
- */
-void sha1_hmac_reset( sha1_context *ctx );
-
-/**
- * \brief Output = HMAC-SHA-1( hmac key, input buffer )
- *
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output HMAC-SHA-1 result
- */
-void sha1_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[20] );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int sha1_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* sha1.h */
diff --git a/polarssl/src/include/polarssl/sha2.h b/polarssl/src/include/polarssl/sha2.h
deleted file mode 100644
index 811b0fd..0000000
--- a/polarssl/src/include/polarssl/sha2.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- * \file sha2.h
- *
- * \brief SHA-224 and SHA-256 cryptographic hash function
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_SHA2_H
-#define POLARSSL_SHA2_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */
-
-/**
- * \brief SHA-256 context structure
- */
-typedef struct
-{
- unsigned long total[2]; /*!< number of bytes processed */
- unsigned long state[8]; /*!< intermediate digest state */
- unsigned char buffer[64]; /*!< data block being processed */
-
- unsigned char ipad[64]; /*!< HMAC: inner padding */
- unsigned char opad[64]; /*!< HMAC: outer padding */
- int is224; /*!< 0 => SHA-256, else SHA-224 */
-}
-sha2_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief SHA-256 context setup
- *
- * \param ctx context to be initialized
- * \param is224 0 = use SHA256, 1 = use SHA224
- */
-void sha2_starts( sha2_context *ctx, int is224 );
-
-/**
- * \brief SHA-256 process buffer
- *
- * \param ctx SHA-256 context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief SHA-256 final digest
- *
- * \param ctx SHA-256 context
- * \param output SHA-224/256 checksum result
- */
-void sha2_finish( sha2_context *ctx, unsigned char output[32] );
-
-/**
- * \brief Output = SHA-256( input buffer )
- *
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output SHA-224/256 checksum result
- * \param is224 0 = use SHA256, 1 = use SHA224
- */
-void sha2( const unsigned char *input, size_t ilen,
- unsigned char output[32], int is224 );
-
-/**
- * \brief Output = SHA-256( file contents )
- *
- * \param path input file name
- * \param output SHA-224/256 checksum result
- * \param is224 0 = use SHA256, 1 = use SHA224
- *
- * \return 0 if successful, or POLARSSL_ERR_SHA2_FILE_IO_ERROR
- */
-int sha2_file( const char *path, unsigned char output[32], int is224 );
-
-/**
- * \brief SHA-256 HMAC context setup
- *
- * \param ctx HMAC context to be initialized
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param is224 0 = use SHA256, 1 = use SHA224
- */
-void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
- int is224 );
-
-/**
- * \brief SHA-256 HMAC process buffer
- *
- * \param ctx HMAC context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief SHA-256 HMAC final digest
- *
- * \param ctx HMAC context
- * \param output SHA-224/256 HMAC checksum result
- */
-void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] );
-
-/**
- * \brief SHA-256 HMAC context reset
- *
- * \param ctx HMAC context to be reset
- */
-void sha2_hmac_reset( sha2_context *ctx );
-
-/**
- * \brief Output = HMAC-SHA-256( hmac key, input buffer )
- *
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output HMAC-SHA-224/256 result
- * \param is224 0 = use SHA256, 1 = use SHA224
- */
-void sha2_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[32], int is224 );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int sha2_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* sha2.h */
diff --git a/polarssl/src/include/polarssl/sha4.h b/polarssl/src/include/polarssl/sha4.h
deleted file mode 100644
index dafebec..0000000
--- a/polarssl/src/include/polarssl/sha4.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * \file sha4.h
- *
- * \brief SHA-384 and SHA-512 cryptographic hash function
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_SHA4_H
-#define POLARSSL_SHA4_H
-
-#include <string.h>
-
-#define POLARSSL_ERR_SHA4_FILE_IO_ERROR -0x007A /**< Read/write error in file. */
-
-#if defined(_MSC_VER) || defined(__WATCOMC__)
- #define UL64(x) x##ui64
- #define long64 __int64
-#else
- #define UL64(x) x##ULL
- #define long64 long long
-#endif
-
-/**
- * \brief SHA-512 context structure
- */
-typedef struct
-{
- unsigned long64 total[2]; /*!< number of bytes processed */
- unsigned long64 state[8]; /*!< intermediate digest state */
- unsigned char buffer[128]; /*!< data block being processed */
-
- unsigned char ipad[128]; /*!< HMAC: inner padding */
- unsigned char opad[128]; /*!< HMAC: outer padding */
- int is384; /*!< 0 => SHA-512, else SHA-384 */
-}
-sha4_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief SHA-512 context setup
- *
- * \param ctx context to be initialized
- * \param is384 0 = use SHA512, 1 = use SHA384
- */
-void sha4_starts( sha4_context *ctx, int is384 );
-
-/**
- * \brief SHA-512 process buffer
- *
- * \param ctx SHA-512 context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief SHA-512 final digest
- *
- * \param ctx SHA-512 context
- * \param output SHA-384/512 checksum result
- */
-void sha4_finish( sha4_context *ctx, unsigned char output[64] );
-
-/**
- * \brief Output = SHA-512( input buffer )
- *
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output SHA-384/512 checksum result
- * \param is384 0 = use SHA512, 1 = use SHA384
- */
-void sha4( const unsigned char *input, size_t ilen,
- unsigned char output[64], int is384 );
-
-/**
- * \brief Output = SHA-512( file contents )
- *
- * \param path input file name
- * \param output SHA-384/512 checksum result
- * \param is384 0 = use SHA512, 1 = use SHA384
- *
- * \return 0 if successful, or POLARSSL_ERR_SHA4_FILE_IO_ERROR
- */
-int sha4_file( const char *path, unsigned char output[64], int is384 );
-
-/**
- * \brief SHA-512 HMAC context setup
- *
- * \param ctx HMAC context to be initialized
- * \param is384 0 = use SHA512, 1 = use SHA384
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- */
-void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
- int is384 );
-
-/**
- * \brief SHA-512 HMAC process buffer
- *
- * \param ctx HMAC context
- * \param input buffer holding the data
- * \param ilen length of the input data
- */
-void sha4_hmac_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
-
-/**
- * \brief SHA-512 HMAC final digest
- *
- * \param ctx HMAC context
- * \param output SHA-384/512 HMAC checksum result
- */
-void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] );
-
-/**
- * \brief SHA-512 HMAC context reset
- *
- * \param ctx HMAC context to be reset
- */
-void sha4_hmac_reset( sha4_context *ctx );
-
-/**
- * \brief Output = HMAC-SHA-512( hmac key, input buffer )
- *
- * \param key HMAC secret key
- * \param keylen length of the HMAC key
- * \param input buffer holding the data
- * \param ilen length of the input data
- * \param output HMAC-SHA-384/512 result
- * \param is384 0 = use SHA512, 1 = use SHA384
- */
-void sha4_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[64], int is384 );
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int sha4_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* sha4.h */
diff --git a/polarssl/src/include/polarssl/ssl.h b/polarssl/src/include/polarssl/ssl.h
deleted file mode 100644
index 4ac6f86..0000000
--- a/polarssl/src/include/polarssl/ssl.h
+++ /dev/null
@@ -1,766 +0,0 @@
-/**
- * \file ssl.h
- *
- * \brief SSL/TLS functions.
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_SSL_H
-#define POLARSSL_SSL_H
-
-#include <time.h>
-
-#include "net.h"
-#include "dhm.h"
-#include "rsa.h"
-#include "md5.h"
-#include "sha1.h"
-#include "sha2.h"
-#include "sha4.h"
-#include "x509.h"
-#include "config.h"
-
-#if defined(POLARSSL_PKCS11_C)
-#include "pkcs11.h"
-#endif
-
-#if defined(_MSC_VER) && !defined(inline)
-#define inline _inline
-#else
-#if defined(__ARMCC_VERSION) && !defined(inline)
-#define inline __inline
-#endif /* __ARMCC_VERSION */
-#endif /*_MSC_VER */
-
-/*
- * SSL Error codes
- */
-#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */
-#define POLARSSL_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */
-#define POLARSSL_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */
-#define POLARSSL_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */
-#define POLARSSL_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */
-#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */
-#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */
-#define POLARSSL_ERR_SSL_NO_SESSION_FOUND -0x7400 /**< No session to recover was found. */
-#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */
-#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message.*/
-#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */
-#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key is not set, but needed. */
-#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */
-#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */
-#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */
-#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */
-#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */
-#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM Read Public. */
-#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret. */
-#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */
-#define POLARSSL_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */
-#define POLARSSL_ERR_SSL_MALLOC_FAILED -0x7F00 /**< Memory allocation failed */
-
-/*
- * Various constants
- */
-#define SSL_MAJOR_VERSION_3 3
-#define SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */
-#define SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */
-#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */
-#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */
-
-#define SSL_IS_CLIENT 0
-#define SSL_IS_SERVER 1
-#define SSL_COMPRESS_NULL 0
-
-#define SSL_VERIFY_NONE 0
-#define SSL_VERIFY_OPTIONAL 1
-#define SSL_VERIFY_REQUIRED 2
-
-#define SSL_MAX_CONTENT_LEN 16384
-
-/*
- * Allow an extra 512 bytes for the record header
- * and encryption overhead (counter + MAC + padding).
- */
-#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + 512)
-
-/*
- * Supported ciphersuites
- */
-#define SSL_RSA_NULL_MD5 0x01 /**< Weak! */
-#define SSL_RSA_NULL_SHA 0x02 /**< Weak! */
-#define SSL_RSA_NULL_SHA256 0x3B /**< Weak! */
-#define SSL_RSA_DES_SHA 0x09 /**< Weak! Not in TLS 1.2 */
-#define SSL_EDH_RSA_DES_SHA 0x15 /**< Weak! Not in TLS 1.2 */
-
-#define SSL_RSA_RC4_128_MD5 0x04
-#define SSL_RSA_RC4_128_SHA 0x05
-
-#define SSL_RSA_DES_168_SHA 0x0A
-#define SSL_EDH_RSA_DES_168_SHA 0x16
-
-#define SSL_RSA_AES_128_SHA 0x2F
-#define SSL_EDH_RSA_AES_128_SHA 0x33
-#define SSL_RSA_AES_256_SHA 0x35
-#define SSL_EDH_RSA_AES_256_SHA 0x39
-#define SSL_RSA_AES_128_SHA256 0x3C /**< TLS 1.2 */
-#define SSL_RSA_AES_256_SHA256 0x3D /**< TLS 1.2 */
-#define SSL_EDH_RSA_AES_128_SHA256 0x67 /**< TLS 1.2 */
-#define SSL_EDH_RSA_AES_256_SHA256 0x6B /**< TLS 1.2 */
-
-#define SSL_RSA_CAMELLIA_128_SHA 0x41
-#define SSL_EDH_RSA_CAMELLIA_128_SHA 0x45
-#define SSL_RSA_CAMELLIA_256_SHA 0x84
-#define SSL_EDH_RSA_CAMELLIA_256_SHA 0x88
-#define SSL_RSA_CAMELLIA_128_SHA256 0xBA /**< TLS 1.2 */
-#define SSL_EDH_RSA_CAMELLIA_128_SHA256 0xBE /**< TLS 1.2 */
-#define SSL_RSA_CAMELLIA_256_SHA256 0xC0 /**< TLS 1.2 */
-#define SSL_EDH_RSA_CAMELLIA_256_SHA256 0xC4 /**< TLS 1.2 */
-
-#define SSL_RSA_AES_128_GCM_SHA256 0x9C
-#define SSL_RSA_AES_256_GCM_SHA384 0x9D
-#define SSL_EDH_RSA_AES_128_GCM_SHA256 0x9E
-#define SSL_EDH_RSA_AES_256_GCM_SHA384 0x9F
-
-/*
- * Supported Signature and Hash algorithms (For TLS 1.2)
- */
-#define SSL_HASH_NONE 0
-#define SSL_HASH_MD5 1
-#define SSL_HASH_SHA1 2
-#define SSL_HASH_SHA224 3
-#define SSL_HASH_SHA256 4
-#define SSL_HASH_SHA384 5
-#define SSL_HASH_SHA512 6
-
-#define SSL_SIG_RSA 1
-
-/*
- * Message, alert and handshake types
- */
-#define SSL_MSG_CHANGE_CIPHER_SPEC 20
-#define SSL_MSG_ALERT 21
-#define SSL_MSG_HANDSHAKE 22
-#define SSL_MSG_APPLICATION_DATA 23
-
-#define SSL_ALERT_LEVEL_WARNING 1
-#define SSL_ALERT_LEVEL_FATAL 2
-
-#define SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */
-#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */
-#define SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */
-#define SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */
-#define SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */
-#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */
-#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */
-#define SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */
-#define SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */
-#define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */
-#define SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */
-#define SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */
-#define SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */
-#define SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */
-#define SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */
-#define SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */
-#define SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */
-#define SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */
-#define SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */
-#define SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */
-#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */
-#define SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */
-#define SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */
-#define SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */
-#define SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */
-
-#define SSL_HS_HELLO_REQUEST 0
-#define SSL_HS_CLIENT_HELLO 1
-#define SSL_HS_SERVER_HELLO 2
-#define SSL_HS_CERTIFICATE 11
-#define SSL_HS_SERVER_KEY_EXCHANGE 12
-#define SSL_HS_CERTIFICATE_REQUEST 13
-#define SSL_HS_SERVER_HELLO_DONE 14
-#define SSL_HS_CERTIFICATE_VERIFY 15
-#define SSL_HS_CLIENT_KEY_EXCHANGE 16
-#define SSL_HS_FINISHED 20
-
-/*
- * TLS extensions
- */
-#define TLS_EXT_SERVERNAME 0
-#define TLS_EXT_SERVERNAME_HOSTNAME 0
-
-#define TLS_EXT_SIG_ALG 13
-
-/*
- * SSL state machine
- */
-typedef enum
-{
- SSL_HELLO_REQUEST,
- SSL_CLIENT_HELLO,
- SSL_SERVER_HELLO,
- SSL_SERVER_CERTIFICATE,
- SSL_SERVER_KEY_EXCHANGE,
- SSL_CERTIFICATE_REQUEST,
- SSL_SERVER_HELLO_DONE,
- SSL_CLIENT_CERTIFICATE,
- SSL_CLIENT_KEY_EXCHANGE,
- SSL_CERTIFICATE_VERIFY,
- SSL_CLIENT_CHANGE_CIPHER_SPEC,
- SSL_CLIENT_FINISHED,
- SSL_SERVER_CHANGE_CIPHER_SPEC,
- SSL_SERVER_FINISHED,
- SSL_FLUSH_BUFFERS,
- SSL_HANDSHAKE_OVER
-}
-ssl_states;
-
-typedef struct _ssl_session ssl_session;
-typedef struct _ssl_context ssl_context;
-
-/*
- * This structure is used for session resuming.
- */
-struct _ssl_session
-{
- time_t start; /*!< starting time */
- int ciphersuite; /*!< chosen ciphersuite */
- size_t length; /*!< session id length */
- unsigned char id[32]; /*!< session identifier */
- unsigned char master[48]; /*!< the master secret */
- ssl_session *next; /*!< next session entry */
-};
-
-struct _ssl_context
-{
- /*
- * Miscellaneous
- */
- int state; /*!< SSL handshake: current state */
-
- int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */
- int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */
-
- int max_major_ver; /*!< max. major version from client */
- int max_minor_ver; /*!< max. minor version from client */
-
- /*
- * Callbacks (RNG, debug, I/O, verification)
- */
- int (*f_rng)(void *, unsigned char *, size_t);
- void (*f_dbg)(void *, int, const char *);
- int (*f_recv)(void *, unsigned char *, size_t);
- int (*f_send)(void *, const unsigned char *, size_t);
- int (*f_vrfy)(void *, x509_cert *, int, int);
-
- void *p_rng; /*!< context for the RNG function */
- void *p_dbg; /*!< context for the debug function */
- void *p_recv; /*!< context for reading operations */
- void *p_send; /*!< context for writing operations */
- void *p_vrfy; /*!< context for verification */
-
- /*
- * Session layer
- */
- int resume; /*!< session resuming flag */
- int timeout; /*!< sess. expiration time */
- ssl_session *session; /*!< current session data */
- int (*s_get)(ssl_context *); /*!< (server) get callback */
- int (*s_set)(ssl_context *); /*!< (server) set callback */
-
- /*
- * Record layer (incoming data)
- */
- unsigned char *in_ctr; /*!< 64-bit incoming message counter */
- unsigned char *in_hdr; /*!< 5-byte record header (in_ctr+8) */
- unsigned char *in_msg; /*!< the message contents (in_hdr+5) */
- unsigned char *in_offt; /*!< read offset in application data */
-
- int in_msgtype; /*!< record header: message type */
- size_t in_msglen; /*!< record header: message length */
- size_t in_left; /*!< amount of data read so far */
-
- size_t in_hslen; /*!< current handshake message length */
- int nb_zero; /*!< # of 0-length encrypted messages */
-
- /*
- * Record layer (outgoing data)
- */
- unsigned char *out_ctr; /*!< 64-bit outgoing message counter */
- unsigned char *out_hdr; /*!< 5-byte record header (out_ctr+8) */
- unsigned char *out_msg; /*!< the message contents (out_hdr+5) */
-
- int out_msgtype; /*!< record header: message type */
- size_t out_msglen; /*!< record header: message length */
- size_t out_left; /*!< amount of data not yet written */
-
- /*
- * PKI layer
- */
- rsa_context *rsa_key; /*!< own RSA private key */
-#if defined(POLARSSL_PKCS11_C)
- pkcs11_context *pkcs11_key; /*!< own PKCS#11 RSA private key */
-#endif
- x509_cert *own_cert; /*!< own X.509 certificate */
- x509_cert *ca_chain; /*!< own trusted CA chain */
- x509_crl *ca_crl; /*!< trusted CA CRLs */
- x509_cert *peer_cert; /*!< peer X.509 cert chain */
- const char *peer_cn; /*!< expected peer CN */
-
- int endpoint; /*!< 0: client, 1: server */
- int authmode; /*!< verification mode */
- int client_auth; /*!< flag for client auth. */
- int verify_result; /*!< verification result */
-
- /*
- * Crypto layer
- */
- dhm_context dhm_ctx; /*!< DHM key exchange */
- unsigned char ctx_checksum[500]; /*!< Checksum context(s) */
-
- void (*update_checksum)(ssl_context *, unsigned char *, size_t);
- void (*calc_verify)(ssl_context *, unsigned char *);
- void (*calc_finished)(ssl_context *, unsigned char *, int);
- int (*tls_prf)(unsigned char *, size_t, char *,
- unsigned char *, size_t,
- unsigned char *, size_t);
-
- int do_crypt; /*!< en(de)cryption flag */
- int *ciphersuites; /*!< allowed ciphersuites */
- size_t pmslen; /*!< premaster length */
- unsigned int keylen; /*!< symmetric key length */
- size_t minlen; /*!< min. ciphertext length */
- size_t ivlen; /*!< IV length */
- size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */
- size_t maclen; /*!< MAC length */
-
- unsigned char randbytes[64]; /*!< random bytes */
- unsigned char premaster[256]; /*!< premaster secret */
-
- unsigned char iv_enc[16]; /*!< IV (encryption) */
- unsigned char iv_dec[16]; /*!< IV (decryption) */
-
- unsigned char mac_enc[32]; /*!< MAC (encryption) */
- unsigned char mac_dec[32]; /*!< MAC (decryption) */
-
- unsigned long ctx_enc[134]; /*!< encryption context */
- unsigned long ctx_dec[134]; /*!< decryption context */
-
- /*
- * TLS extensions
- */
- unsigned char *hostname;
- size_t hostname_len;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int ssl_default_ciphersuites[];
-
-/**
- * \brief Returns the list of ciphersuites supported by the SSL/TLS module.
- *
- * \return a statically allocated array of ciphersuites, the last
- * entry is 0.
- */
-static inline const int *ssl_list_ciphersuites( void )
-{
- return ssl_default_ciphersuites;
-}
-
-/**
- * \brief Return the name of the ciphersuite associated with the given
- * ID
- *
- * \param ciphersuite_id SSL ciphersuite ID
- *
- * \return a string containing the ciphersuite name
- */
-const char *ssl_get_ciphersuite_name( const int ciphersuite_id );
-
-/**
- * \brief Return the ID of the ciphersuite associated with the given
- * name
- *
- * \param ciphersuite_name SSL ciphersuite name
- *
- * \return the ID with the ciphersuite or 0 if not found
- */
-int ssl_get_ciphersuite_id( const char *ciphersuite_name );
-
-/**
- * \brief Initialize an SSL context
- *
- * \param ssl SSL context
- *
- * \return 0 if successful, or POLARSSL_ERR_SSL_MALLOC_FAILED if
- * memory allocation failed
- */
-int ssl_init( ssl_context *ssl );
-
-/**
- * \brief Reset an already initialized SSL context for re-use
- * while retaining application-set variables, function
- * pointers and data.
- *
- * \param ssl SSL context
- */
-void ssl_session_reset( ssl_context *ssl );
-
-/**
- * \brief Set the current endpoint type
- *
- * \param ssl SSL context
- * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER
- */
-void ssl_set_endpoint( ssl_context *ssl, int endpoint );
-
-/**
- * \brief Set the certificate verification mode
- *
- * \param ssl SSL context
- * \param authmode can be:
- *
- * SSL_VERIFY_NONE: peer certificate is not checked (default),
- * this is insecure and SHOULD be avoided.
- *
- * SSL_VERIFY_OPTIONAL: peer certificate is checked, however the
- * handshake continues even if verification failed;
- * ssl_get_verify_result() can be called after the
- * handshake is complete.
- *
- * SSL_VERIFY_REQUIRED: peer *must* present a valid certificate,
- * handshake is aborted if verification failed.
- */
-void ssl_set_authmode( ssl_context *ssl, int authmode );
-
-/**
- * \brief Set the verification callback (Optional).
- *
- * If set, the verification callback is called once for every
- * certificate in the chain. The verification function has the
- * following parameter: (void *parameter, x509_cert certificate,
- * int certifcate_depth, int preverify_ok). It should
- * return 0 on SUCCESS.
- *
- * \param ssl SSL context
- * \param f_vrfy verification function
- * \param p_vrfy verification parameter
- */
-void ssl_set_verify( ssl_context *ssl,
- int (*f_vrfy)(void *, x509_cert *, int, int),
- void *p_vrfy );
-
-/**
- * \brief Set the random number generator callback
- *
- * \param ssl SSL context
- * \param f_rng RNG function
- * \param p_rng RNG parameter
- */
-void ssl_set_rng( ssl_context *ssl,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng );
-
-/**
- * \brief Set the debug callback
- *
- * \param ssl SSL context
- * \param f_dbg debug function
- * \param p_dbg debug parameter
- */
-void ssl_set_dbg( ssl_context *ssl,
- void (*f_dbg)(void *, int, const char *),
- void *p_dbg );
-
-/**
- * \brief Set the underlying BIO read and write callbacks
- *
- * \param ssl SSL context
- * \param f_recv read callback
- * \param p_recv read parameter
- * \param f_send write callback
- * \param p_send write parameter
- */
-void ssl_set_bio( ssl_context *ssl,
- int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
- int (*f_send)(void *, const unsigned char *, size_t), void *p_send );
-
-/**
- * \brief Set the session callbacks (server-side only)
- *
- * \param ssl SSL context
- * \param s_get session get callback
- * \param s_set session set callback
- */
-void ssl_set_scb( ssl_context *ssl,
- int (*s_get)(ssl_context *),
- int (*s_set)(ssl_context *) );
-
-/**
- * \brief Set the session resuming flag, timeout and data
- *
- * \param ssl SSL context
- * \param resume if 0 (default), the session will not be resumed
- * \param timeout session timeout in seconds, or 0 (no timeout)
- * \param session session context
- */
-void ssl_set_session( ssl_context *ssl, int resume, int timeout,
- ssl_session *session );
-
-/**
- * \brief Set the list of allowed ciphersuites
- *
- * \param ssl SSL context
- * \param ciphersuites 0-terminated list of allowed ciphersuites
- */
-void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites );
-
-/**
- * \brief Set the data required to verify peer certificate
- *
- * \param ssl SSL context
- * \param ca_chain trusted CA chain
- * \param ca_crl trusted CA CRLs
- * \param peer_cn expected peer CommonName (or NULL)
- *
- * \note TODO: add two more parameters: depth and crl
- */
-void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
- x509_crl *ca_crl, const char *peer_cn );
-
-/**
- * \brief Set own certificate and private key
- *
- * \param ssl SSL context
- * \param own_cert own public certificate
- * \param rsa_key own private RSA key
- */
-void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
- rsa_context *rsa_key );
-
-#if defined(POLARSSL_PKCS11_C)
-/**
- * \brief Set own certificate and PKCS#11 private key
- *
- * \param ssl SSL context
- * \param own_cert own public certificate
- * \param pkcs11_key own PKCS#11 RSA key
- */
-void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert,
- pkcs11_context *pkcs11_key );
-#endif
-
-/**
- * \brief Set the Diffie-Hellman public P and G values,
- * read as hexadecimal strings (server-side only)
- *
- * \param ssl SSL context
- * \param dhm_P Diffie-Hellman-Merkle modulus
- * \param dhm_G Diffie-Hellman-Merkle generator
- *
- * \return 0 if successful
- */
-int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G );
-
-/**
- * \brief Set the Diffie-Hellman public P and G values,
- * read from existing context (server-side only)
- *
- * \param ssl SSL context
- * \param dhm_ctx Diffie-Hellman-Merkle context
- *
- * \return 0 if successful
- */
-int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
-
-/**
- * \brief Set hostname for ServerName TLS Extension
- *
- *
- * \param ssl SSL context
- * \param hostname the server hostname
- *
- * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED
- */
-int ssl_set_hostname( ssl_context *ssl, const char *hostname );
-
-/**
- * \brief Set the maximum supported version sent from the client side
- *
- * \param ssl SSL context
- * \param major Major version number (only SSL_MAJOR_VERSION_3 supported)
- * \param minor Minor version number (SSL_MINOR_VERSION_0,
- * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
- * SSL_MINOR_VERSION_3 supported)
- */
-void ssl_set_max_version( ssl_context *ssl, int major, int minor );
-
-/**
- * \brief Return the number of data bytes available to read
- *
- * \param ssl SSL context
- *
- * \return how many bytes are available in the read buffer
- */
-size_t ssl_get_bytes_avail( const ssl_context *ssl );
-
-/**
- * \brief Return the result of the certificate verification
- *
- * \param ssl SSL context
- *
- * \return 0 if successful, or a combination of:
- * BADCERT_EXPIRED
- * BADCERT_REVOKED
- * BADCERT_CN_MISMATCH
- * BADCERT_NOT_TRUSTED
- */
-int ssl_get_verify_result( const ssl_context *ssl );
-
-/**
- * \brief Return the name of the current ciphersuite
- *
- * \param ssl SSL context
- *
- * \return a string containing the ciphersuite name
- */
-const char *ssl_get_ciphersuite( const ssl_context *ssl );
-
-/**
- * \brief Return the current SSL version (SSLv3/TLSv1/etc)
- *
- * \param ssl SSL context
- *
- * \return a string containing the SSL version
- */
-const char *ssl_get_version( const ssl_context *ssl );
-
-/**
- * \brief Perform the SSL handshake
- *
- * \param ssl SSL context
- *
- * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ,
- * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
- */
-int ssl_handshake( ssl_context *ssl );
-
-/**
- * \brief Read at most 'len' application data bytes
- *
- * \param ssl SSL context
- * \param buf buffer that will hold the data
- * \param len how many bytes must be read
- *
- * \return This function returns the number of bytes read, 0 for EOF,
- * or a negative error code.
- */
-int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len );
-
-/**
- * \brief Write exactly 'len' application data bytes
- *
- * \param ssl SSL context
- * \param buf buffer holding the data
- * \param len how many bytes must be written
- *
- * \return This function returns the number of bytes written,
- * or a negative error code.
- *
- * \note When this function returns POLARSSL_ERR_NET_WANT_WRITE,
- * it must be called later with the *same* arguments,
- * until it returns a positive value.
- */
-int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len );
-
-/**
- * \brief Send an alert message
- *
- * \param ssl SSL context
- * \param level The alert level of the message
- * (SSL_ALERT_LEVEL_WARNING or SSL_ALERT_LEVEL_FATAL)
- * \param message The alert message (SSL_ALERT_MSG_*)
- *
- * \return 1 if successful, or a specific SSL error code.
- */
-int ssl_send_alert_message( ssl_context *ssl,
- unsigned char level,
- unsigned char message );
-/**
- * \brief Notify the peer that the connection is being closed
- *
- * \param ssl SSL context
- */
-int ssl_close_notify( ssl_context *ssl );
-
-/**
- * \brief Free an SSL context
- *
- * \param ssl SSL context
- */
-void ssl_free( ssl_context *ssl );
-
-/*
- * Internal functions (do not call directly)
- */
-int ssl_handshake_client( ssl_context *ssl );
-int ssl_handshake_server( ssl_context *ssl );
-
-int ssl_derive_keys( ssl_context *ssl );
-
-int ssl_read_record( ssl_context *ssl );
-/**
- * \return 0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or
- * another negative error code.
- */
-int ssl_fetch_input( ssl_context *ssl, size_t nb_want );
-
-int ssl_write_record( ssl_context *ssl );
-int ssl_flush_output( ssl_context *ssl );
-
-int ssl_parse_certificate( ssl_context *ssl );
-int ssl_write_certificate( ssl_context *ssl );
-
-int ssl_parse_change_cipher_spec( ssl_context *ssl );
-int ssl_write_change_cipher_spec( ssl_context *ssl );
-
-int ssl_parse_finished( ssl_context *ssl );
-int ssl_write_finished( ssl_context *ssl );
-
-void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite,
- unsigned char *input_buf, size_t len );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ssl.h */
diff --git a/polarssl/src/include/polarssl/timing.h b/polarssl/src/include/polarssl/timing.h
deleted file mode 100644
index 355c63c..0000000
--- a/polarssl/src/include/polarssl/timing.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * \file timing.h
- *
- * \brief Portable interface to the CPU cycle counter
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_TIMING_H
-#define POLARSSL_TIMING_H
-
-/**
- * \brief timer structure
- */
-struct hr_time
-{
- unsigned char opaque[32];
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern volatile int alarmed;
-
-/**
- * \brief Return the CPU cycle counter value
- */
-unsigned long hardclock( void );
-
-/**
- * \brief Return the elapsed time in milliseconds
- *
- * \param val points to a timer structure
- * \param reset if set to 1, the timer is restarted
- */
-unsigned long get_timer( struct hr_time *val, int reset );
-
-/**
- * \brief Setup an alarm clock
- *
- * \param seconds delay before the "alarmed" flag is set
- */
-void set_alarm( int seconds );
-
-/**
- * \brief Sleep for a certain amount of time
- *
- * \param milliseconds delay in milliseconds
- */
-void m_sleep( int milliseconds );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* timing.h */
diff --git a/polarssl/src/include/polarssl/version.h b/polarssl/src/include/polarssl/version.h
deleted file mode 100644
index 98eb0b3..0000000
--- a/polarssl/src/include/polarssl/version.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * \file version.h
- *
- * \brief Run-time version information
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * This set of compile-time defines and run-time variables can be used to
- * determine the version number of the PolarSSL library used.
- */
-#ifndef POLARSSL_VERSION_H
-#define POLARSSL_VERSION_H
-
-#include "config.h"
-
-/**
- * The version number x.y.z is split into three parts.
- * Major, Minor, Patchlevel
- */
-#define POLARSSL_VERSION_MAJOR 1
-#define POLARSSL_VERSION_MINOR 1
-#define POLARSSL_VERSION_PATCH 1
-
-/**
- * The single version number has the following structure:
- * MMNNPP00
- * Major version | Minor version | Patch version
- */
-#define POLARSSL_VERSION_NUMBER 0x01010100
-#define POLARSSL_VERSION_STRING "1.1.1"
-#define POLARSSL_VERSION_STRING_FULL "PolarSSL 1.1.1"
-
-#if defined(POLARSSL_VERSION_C)
-
-/**
- * Get the version number.
- *
- * \return The constructed version number in the format
- * MMNNPP00 (Major, Minor, Patch).
- */
-unsigned int version_get_number( void );
-
-/**
- * Get the version string ("x.y.z").
- *
- * \param string The string that will receive the value.
- * (Should be at least 9 bytes in size)
- */
-void version_get_string( char *string );
-
-/**
- * Get the full version string ("PolarSSL x.y.z").
- *
- * \param string The string that will receive the value.
- * (Should be at least 18 bytes in size)
- */
-void version_get_string_full( char *string );
-
-#endif /* POLARSSL_VERSION_C */
-
-#endif /* version.h */
diff --git a/polarssl/src/include/polarssl/x509.h b/polarssl/src/include/polarssl/x509.h
deleted file mode 100644
index 2cd883f..0000000
--- a/polarssl/src/include/polarssl/x509.h
+++ /dev/null
@@ -1,733 +0,0 @@
-/**
- * \file x509.h
- *
- * \brief X.509 certificate and private key decoding
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_X509_H
-#define POLARSSL_X509_H
-
-#include "asn1.h"
-#include "rsa.h"
-#include "dhm.h"
-
-/**
- * \addtogroup x509_module
- * \{
- */
-
-/**
- * \name X509 Error codes
- * \{
- */
-#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */
-#define POLARSSL_ERR_X509_CERT_INVALID_PEM -0x2100 /**< The PEM-encoded certificate contains invalid elements, e.g. invalid character. */
-#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT -0x2180 /**< The certificate format is invalid, e.g. different type expected. */
-#define POLARSSL_ERR_X509_CERT_INVALID_VERSION -0x2200 /**< The certificate version element is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY -0x2480 /**< The pubkey tag or value is invalid (only RSA is supported). */
-#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE -0x2500 /**< The signature tag or value invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS -0x2580 /**< The extension tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION -0x2600 /**< Certificate or CRL has an unsupported version number. */
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG -0x2680 /**< Signature algorithm (oid) is unsupported. */
-#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG -0x2700 /**< Key algorithm is unsupported (only RSA is supported). */
-#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH -0x2780 /**< Certificate signature algorithms do not match. (see \c ::x509_cert sig_oid) */
-#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x2800 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */
-#define POLARSSL_ERR_X509_KEY_INVALID_VERSION -0x2880 /**< Unsupported RSA key version */
-#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT -0x2900 /**< Invalid RSA key tag or value. */
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT -0x2980 /**< Format not recognized as DER or PEM. */
-#define POLARSSL_ERR_X509_INVALID_INPUT -0x2A00 /**< Input invalid. */
-#define POLARSSL_ERR_X509_MALLOC_FAILED -0x2A80 /**< Allocation of memory failed. */
-#define POLARSSL_ERR_X509_FILE_IO_ERROR -0x2B00 /**< Read/write of file failed. */
-/* \} name */
-
-
-/**
- * \name X509 Verify codes
- * \{
- */
-#define BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */
-#define BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */
-#define BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */
-#define BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */
-#define BADCRL_NOT_TRUSTED 0x10 /**< CRL is not correctly signed by the trusted CA. */
-#define BADCRL_EXPIRED 0x20 /**< CRL is expired. */
-#define BADCERT_MISSING 0x40 /**< Certificate was missing. */
-#define BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */
-/* \} name */
-/* \} addtogroup x509_module */
-
-/*
- * various object identifiers
- */
-#define X520_COMMON_NAME 3
-#define X520_COUNTRY 6
-#define X520_LOCALITY 7
-#define X520_STATE 8
-#define X520_ORGANIZATION 10
-#define X520_ORG_UNIT 11
-#define PKCS9_EMAIL 1
-
-#define X509_OUTPUT_DER 0x01
-#define X509_OUTPUT_PEM 0x02
-#define PEM_LINE_LENGTH 72
-#define X509_ISSUER 0x01
-#define X509_SUBJECT 0x02
-
-#define OID_X520 "\x55\x04"
-#define OID_CN OID_X520 "\x03"
-#define OID_COUNTRY OID_X520 "\x06"
-#define OID_LOCALITY OID_X520 "\x07"
-#define OID_STATE OID_X520 "\x08"
-#define OID_ORGANIZATION OID_X520 "\x0A"
-#define OID_ORG_UNIT OID_X520 "\x0B"
-
-#define OID_PKCS1 "\x2A\x86\x48\x86\xF7\x0D\x01\x01"
-#define OID_PKCS1_RSA OID_PKCS1 "\x01"
-#define OID_PKCS1_SHA1 OID_PKCS1 "\x05"
-
-#define OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D"
-
-#define OID_PKCS9 "\x2A\x86\x48\x86\xF7\x0D\x01\x09"
-#define OID_PKCS9_EMAIL OID_PKCS9 "\x01"
-
-/** ISO arc for standard certificate and CRL extensions */
-#define OID_ID_CE "\x55\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */
-
-/**
- * Private Internet Extensions
- * { iso(1) identified-organization(3) dod(6) internet(1)
- * security(5) mechanisms(5) pkix(7) }
- */
-#define OID_PKIX "\x2B\x06\x01\x05\x05\x07"
-
-/*
- * OIDs for standard certificate extensions
- */
-#define OID_AUTHORITY_KEY_IDENTIFIER OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */
-#define OID_SUBJECT_KEY_IDENTIFIER OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */
-#define OID_KEY_USAGE OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */
-#define OID_CERTIFICATE_POLICIES OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */
-#define OID_POLICY_MAPPINGS OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */
-#define OID_SUBJECT_ALT_NAME OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */
-#define OID_ISSUER_ALT_NAME OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */
-#define OID_SUBJECT_DIRECTORY_ATTRS OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */
-#define OID_BASIC_CONSTRAINTS OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */
-#define OID_NAME_CONSTRAINTS OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */
-#define OID_POLICY_CONSTRAINTS OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */
-#define OID_EXTENDED_KEY_USAGE OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */
-#define OID_CRL_DISTRIBUTION_POINTS OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */
-#define OID_INIHIBIT_ANYPOLICY OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */
-#define OID_FRESHEST_CRL OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */
-
-/*
- * X.509 v3 Key Usage Extension flags
- */
-#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
-#define KU_NON_REPUDIATION (0x40) /* bit 1 */
-#define KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */
-#define KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */
-#define KU_KEY_AGREEMENT (0x08) /* bit 4 */
-#define KU_KEY_CERT_SIGN (0x04) /* bit 5 */
-#define KU_CRL_SIGN (0x02) /* bit 6 */
-
-/*
- * X.509 v3 Extended key usage OIDs
- */
-#define OID_ANY_EXTENDED_KEY_USAGE OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */
-
-#define OID_KP OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */
-#define OID_SERVER_AUTH OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */
-#define OID_CLIENT_AUTH OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */
-#define OID_CODE_SIGNING OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */
-#define OID_EMAIL_PROTECTION OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */
-#define OID_TIME_STAMPING OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
-#define OID_OCSP_SIGNING OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
-
-#define STRING_SERVER_AUTH "TLS Web Server Authentication"
-#define STRING_CLIENT_AUTH "TLS Web Client Authentication"
-#define STRING_CODE_SIGNING "Code Signing"
-#define STRING_EMAIL_PROTECTION "E-mail Protection"
-#define STRING_TIME_STAMPING "Time Stamping"
-#define STRING_OCSP_SIGNING "OCSP Signing"
-
-/*
- * OIDs for CRL extensions
- */
-#define OID_PRIVATE_KEY_USAGE_PERIOD OID_ID_CE "\x10"
-#define OID_CRL_NUMBER OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */
-
-/*
- * Netscape certificate extensions
- */
-#define OID_NETSCAPE "\x60\x86\x48\x01\x86\xF8\x42" /**< Netscape OID */
-#define OID_NS_CERT OID_NETSCAPE "\x01"
-#define OID_NS_CERT_TYPE OID_NS_CERT "\x01"
-#define OID_NS_BASE_URL OID_NS_CERT "\x02"
-#define OID_NS_REVOCATION_URL OID_NS_CERT "\x03"
-#define OID_NS_CA_REVOCATION_URL OID_NS_CERT "\x04"
-#define OID_NS_RENEWAL_URL OID_NS_CERT "\x07"
-#define OID_NS_CA_POLICY_URL OID_NS_CERT "\x08"
-#define OID_NS_SSL_SERVER_NAME OID_NS_CERT "\x0C"
-#define OID_NS_COMMENT OID_NS_CERT "\x0D"
-#define OID_NS_DATA_TYPE OID_NETSCAPE "\x02"
-#define OID_NS_CERT_SEQUENCE OID_NS_DATA_TYPE "\x05"
-
-/*
- * Netscape certificate types
- * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html)
- */
-
-#define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */
-#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */
-#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */
-#define NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */
-#define NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */
-#define NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */
-#define NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */
-#define NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */
-
-#define EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0)
-#define EXT_SUBJECT_KEY_IDENTIFIER (1 << 1)
-#define EXT_KEY_USAGE (1 << 2)
-#define EXT_CERTIFICATE_POLICIES (1 << 3)
-#define EXT_POLICY_MAPPINGS (1 << 4)
-#define EXT_SUBJECT_ALT_NAME (1 << 5)
-#define EXT_ISSUER_ALT_NAME (1 << 6)
-#define EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7)
-#define EXT_BASIC_CONSTRAINTS (1 << 8)
-#define EXT_NAME_CONSTRAINTS (1 << 9)
-#define EXT_POLICY_CONSTRAINTS (1 << 10)
-#define EXT_EXTENDED_KEY_USAGE (1 << 11)
-#define EXT_CRL_DISTRIBUTION_POINTS (1 << 12)
-#define EXT_INIHIBIT_ANYPOLICY (1 << 13)
-#define EXT_FRESHEST_CRL (1 << 14)
-
-#define EXT_NS_CERT_TYPE (1 << 16)
-
-/*
- * Storage format identifiers
- * Recognized formats: PEM and DER
- */
-#define X509_FORMAT_DER 1
-#define X509_FORMAT_PEM 2
-
-/**
- * \addtogroup x509_module
- * \{ */
-
-/**
- * \name Structures for parsing X.509 certificates and CRLs
- * \{
- */
-
-/**
- * Type-length-value structure that allows for ASN1 using DER.
- */
-typedef asn1_buf x509_buf;
-
-/**
- * Container for ASN1 bit strings.
- */
-typedef asn1_bitstring x509_bitstring;
-
-/**
- * Container for ASN1 named information objects.
- * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.).
- */
-typedef struct _x509_name
-{
- x509_buf oid; /**< The object identifier. */
- x509_buf val; /**< The named value. */
- struct _x509_name *next; /**< The next named information object. */
-}
-x509_name;
-
-/**
- * Container for a sequence of ASN.1 items
- */
-typedef asn1_sequence x509_sequence;
-
-/** Container for date and time (precision in seconds). */
-typedef struct _x509_time
-{
- int year, mon, day; /**< Date. */
- int hour, min, sec; /**< Time. */
-}
-x509_time;
-
-/**
- * Container for an X.509 certificate. The certificate may be chained.
- */
-typedef struct _x509_cert
-{
- x509_buf raw; /**< The raw certificate data (DER). */
- x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */
-
- int version; /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
- x509_buf serial; /**< Unique id for certificate issued by a specific CA. */
- x509_buf sig_oid1; /**< Signature algorithm, e.g. sha1RSA */
-
- x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */
- x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */
-
- x509_name issuer; /**< The parsed issuer data (named information object). */
- x509_name subject; /**< The parsed subject data (named information object). */
-
- x509_time valid_from; /**< Start time of certificate validity. */
- x509_time valid_to; /**< End time of certificate validity. */
-
- x509_buf pk_oid; /**< Subject public key info. Includes the public key algorithm and the key itself. */
- rsa_context rsa; /**< Container for the RSA context. Only RSA is supported for public keys at this time. */
-
- x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */
- x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */
- x509_buf v3_ext; /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */
- x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */
-
- int ext_types; /**< Bit string containing detected and parsed extensions */
- int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
- int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. */
-
- unsigned char key_usage; /**< Optional key usage extension value: See the values below */
-
- x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
-
- unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values below */
-
- x509_buf sig_oid2; /**< Signature algorithm. Must match sig_oid1. */
- x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */
- int sig_alg; /**< Internal representation of the signature algorithm, e.g. SIG_RSA_MD2 */
-
- struct _x509_cert *next; /**< Next certificate in the CA-chain. */
-}
-x509_cert;
-
-/**
- * Certificate revocation list entry.
- * Contains the CA-specific serial numbers and revocation dates.
- */
-typedef struct _x509_crl_entry
-{
- x509_buf raw;
-
- x509_buf serial;
-
- x509_time revocation_date;
-
- x509_buf entry_ext;
-
- struct _x509_crl_entry *next;
-}
-x509_crl_entry;
-
-/**
- * Certificate revocation list structure.
- * Every CRL may have multiple entries.
- */
-typedef struct _x509_crl
-{
- x509_buf raw; /**< The raw certificate data (DER). */
- x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */
-
- int version;
- x509_buf sig_oid1;
-
- x509_buf issuer_raw; /**< The raw issuer data (DER). */
-
- x509_name issuer; /**< The parsed issuer data (named information object). */
-
- x509_time this_update;
- x509_time next_update;
-
- x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */
-
- x509_buf crl_ext;
-
- x509_buf sig_oid2;
- x509_buf sig;
- int sig_alg;
-
- struct _x509_crl *next;
-}
-x509_crl;
-/** \} name Structures for parsing X.509 certificates and CRLs */
-/** \} addtogroup x509_module */
-
-/**
- * \name Structures for writing X.509 certificates.
- * XvP: commented out as they are not used.
- * - <tt>typedef struct _x509_node x509_node;</tt>
- * - <tt>typedef struct _x509_raw x509_raw;</tt>
- */
-/*
-typedef struct _x509_node
-{
- unsigned char *data;
- unsigned char *p;
- unsigned char *end;
-
- size_t len;
-}
-x509_node;
-
-typedef struct _x509_raw
-{
- x509_node raw;
- x509_node tbs;
-
- x509_node version;
- x509_node serial;
- x509_node tbs_signalg;
- x509_node issuer;
- x509_node validity;
- x509_node subject;
- x509_node subpubkey;
-
- x509_node signalg;
- x509_node sign;
-}
-x509_raw;
-*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \name Functions to read in DHM parameters, a certificate, CRL or private RSA key
- * \{
- */
-
-/** \ingroup x509_module */
-/**
- * \brief Parse one or more certificates and add them
- * to the chained list. Parses permissively. If some
- * certificates can be parsed, the result is the number
- * of failed certificates it encountered. If none complete
- * correctly, the first error is returned.
- *
- * \param chain points to the start of the chain
- * \param buf buffer holding the certificate data
- * \param buflen size of the buffer
- *
- * \return 0 if all certificates parsed successfully, a positive number
- * if partly successful or a specific X509 or PEM error code
- */
-int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen );
-
-/** \ingroup x509_module */
-/**
- * \brief Load one or more certificates and add them
- * to the chained list. Parses permissively. If some
- * certificates can be parsed, the result is the number
- * of failed certificates it encountered. If none complete
- * correctly, the first error is returned.
- *
- * \param chain points to the start of the chain
- * \param path filename to read the certificates from
- *
- * \return 0 if all certificates parsed successfully, a positive number
- * if partly successful or a specific X509 or PEM error code
- */
-int x509parse_crtfile( x509_cert *chain, const char *path );
-
-/** \ingroup x509_module */
-/**
- * \brief Parse one or more CRLs and add them
- * to the chained list
- *
- * \param chain points to the start of the chain
- * \param buf buffer holding the CRL data
- * \param buflen size of the buffer
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen );
-
-/** \ingroup x509_module */
-/**
- * \brief Load one or more CRLs and add them
- * to the chained list
- *
- * \param chain points to the start of the chain
- * \param path filename to read the CRLs from
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_crlfile( x509_crl *chain, const char *path );
-
-/** \ingroup x509_module */
-/**
- * \brief Parse a private RSA key
- *
- * \param rsa RSA context to be initialized
- * \param key input buffer
- * \param keylen size of the buffer
- * \param pwd password for decryption (optional)
- * \param pwdlen size of the password
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_key( rsa_context *rsa,
- const unsigned char *key, size_t keylen,
- const unsigned char *pwd, size_t pwdlen );
-
-/** \ingroup x509_module */
-/**
- * \brief Load and parse a private RSA key
- *
- * \param rsa RSA context to be initialized
- * \param path filename to read the private key from
- * \param password password to decrypt the file (can be NULL)
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_keyfile( rsa_context *rsa, const char *path,
- const char *password );
-
-/** \ingroup x509_module */
-/**
- * \brief Parse a public RSA key
- *
- * \param rsa RSA context to be initialized
- * \param key input buffer
- * \param keylen size of the buffer
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_public_key( rsa_context *rsa,
- const unsigned char *key, size_t keylen );
-
-/** \ingroup x509_module */
-/**
- * \brief Load and parse a public RSA key
- *
- * \param rsa RSA context to be initialized
- * \param path filename to read the private key from
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_public_keyfile( rsa_context *rsa, const char *path );
-
-/** \ingroup x509_module */
-/**
- * \brief Parse DHM parameters
- *
- * \param dhm DHM context to be initialized
- * \param dhmin input buffer
- * \param dhminlen size of the buffer
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen );
-
-/** \ingroup x509_module */
-/**
- * \brief Load and parse DHM parameters
- *
- * \param dhm DHM context to be initialized
- * \param path filename to read the DHM Parameters from
- *
- * \return 0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_dhmfile( dhm_context *dhm, const char *path );
-
-/** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */
-
-/**
- * \brief Store the certificate DN in printable form into buf;
- * no more than size characters will be written.
- *
- * \param buf Buffer to write to
- * \param size Maximum size of buffer
- * \param dn The X509 name to represent
- *
- * \return The amount of data written to the buffer, or -1 in
- * case of an error.
- */
-int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn );
-
-/**
- * \brief Store the certificate serial in printable form into buf;
- * no more than size characters will be written.
- *
- * \param buf Buffer to write to
- * \param size Maximum size of buffer
- * \param serial The X509 serial to represent
- *
- * \return The amount of data written to the buffer, or -1 in
- * case of an error.
- */
-int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial );
-
-/**
- * \brief Returns an informational string about the
- * certificate.
- *
- * \param buf Buffer to write to
- * \param size Maximum size of buffer
- * \param prefix A line prefix
- * \param crt The X509 certificate to represent
- *
- * \return The amount of data written to the buffer, or -1 in
- * case of an error.
- */
-int x509parse_cert_info( char *buf, size_t size, const char *prefix,
- const x509_cert *crt );
-
-/**
- * \brief Returns an informational string about the
- * CRL.
- *
- * \param buf Buffer to write to
- * \param size Maximum size of buffer
- * \param prefix A line prefix
- * \param crl The X509 CRL to represent
- *
- * \return The amount of data written to the buffer, or -1 in
- * case of an error.
- */
-int x509parse_crl_info( char *buf, size_t size, const char *prefix,
- const x509_crl *crl );
-
-/**
- * \brief Give an known OID, return its descriptive string.
- *
- * \param oid buffer containing the oid
- *
- * \return Return a string if the OID is known,
- * or NULL otherwise.
- */
-const char *x509_oid_get_description( x509_buf *oid );
-
-/*
- * \brief Give an OID, return a string version of its OID number.
- *
- * \param buf Buffer to write to
- * \param size Maximum size of buffer
- * \param oid Buffer containing the OID
- *
- * \return The amount of data written to the buffer, or -1 in
- * case of an error.
- */
-int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid );
-
-/**
- * \brief Check a given x509_time against the system time and check
- * if it is valid.
- *
- * \param time x509_time to check
- *
- * \return Return 0 if the x509_time is still valid,
- * or 1 otherwise.
- */
-int x509parse_time_expired( const x509_time *time );
-
-/**
- * \name Functions to verify a certificate
- * \{
- */
-/** \ingroup x509_module */
-/**
- * \brief Verify the certificate signature
- *
- * \param crt a certificate to be verified
- * \param trust_ca the trusted CA chain
- * \param ca_crl the CRL chain for trusted CA's
- * \param cn expected Common Name (can be set to
- * NULL if the CN must not be verified)
- * \param flags result of the verification
- * \param f_vrfy verification function
- * \param p_vrfy verification parameter
- *
- * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
- * in which case *flags will have one or more of
- * the following values set:
- * BADCERT_EXPIRED --
- * BADCERT_REVOKED --
- * BADCERT_CN_MISMATCH --
- * BADCERT_NOT_TRUSTED
- *
- * \note TODO: add two arguments, depth and crl
- */
-int x509parse_verify( x509_cert *crt,
- x509_cert *trust_ca,
- x509_crl *ca_crl,
- const char *cn, int *flags,
- int (*f_vrfy)(void *, x509_cert *, int, int),
- void *p_vrfy );
-
-/**
- * \brief Verify the certificate signature
- *
- * \param crt a certificate to be verified
- * \param crl the CRL to verify against
- *
- * \return 1 if the certificate is revoked, 0 otherwise
- *
- */
-int x509parse_revoked( const x509_cert *crt, const x509_crl *crl );
-
-/** \} name Functions to verify a certificate */
-
-
-
-/**
- * \name Functions to clear a certificate, CRL or private RSA key
- * \{
- */
-/** \ingroup x509_module */
-/**
- * \brief Unallocate all certificate data
- *
- * \param crt Certificate chain to free
- */
-void x509_free( x509_cert *crt );
-
-/** \ingroup x509_module */
-/**
- * \brief Unallocate all CRL data
- *
- * \param crl CRL chain to free
- */
-void x509_crl_free( x509_crl *crl );
-
-/** \} name Functions to clear a certificate, CRL or private RSA key */
-
-
-/**
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int x509_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* x509.h */
diff --git a/polarssl/src/include/polarssl/x509write.h b/polarssl/src/include/polarssl/x509write.h
deleted file mode 100644
index 8ce3d86..0000000
--- a/polarssl/src/include/polarssl/x509write.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * \file x509write.h
- *
- * \brief X509 buffer writing functionality
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_X509_WRITE_H
-#define POLARSSL_X509_WRITE_H
-
-#include "rsa.h"
-
-typedef struct _x509_req_name
-{
- char oid[128];
- char name[128];
-
- struct _x509_req_name *next;
-}
-x509_req_name;
-
-int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa );
-int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa );
-int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa,
- x509_req_name *req_name, int hash_id );
-
-#endif /* POLARSSL_X509_WRITE_H */
diff --git a/polarssl/src/include/polarssl/xtea.h b/polarssl/src/include/polarssl/xtea.h
deleted file mode 100644
index e2adb87..0000000
--- a/polarssl/src/include/polarssl/xtea.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * \file xtea.h
- *
- * \brief XTEA block cipher (32-bit)
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_XTEA_H
-#define POLARSSL_XTEA_H
-
-#include <string.h>
-
-#ifdef _MSC_VER
-#include <basetsd.h>
-typedef UINT32 uint32_t;
-#else
-#include <inttypes.h>
-#endif
-
-#define XTEA_ENCRYPT 1
-#define XTEA_DECRYPT 0
-
-#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */
-
-/**
- * \brief XTEA context structure
- */
-typedef struct
-{
- uint32_t k[4]; /*!< key */
-}
-xtea_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief XTEA key schedule
- *
- * \param ctx XTEA context to be initialized
- * \param key the secret key
- */
-void xtea_setup( xtea_context *ctx, unsigned char key[16] );
-
-/**
- * \brief XTEA cipher function
- *
- * \param ctx XTEA context
- * \param mode XTEA_ENCRYPT or XTEA_DECRYPT
- * \param input 8-byte input block
- * \param output 8-byte output block
- *
- * \return 0 if successful
- */
-int xtea_crypt_ecb( xtea_context *ctx,
- int mode,
- unsigned char input[8],
- unsigned char output[8] );
-
-/**
- * \brief XTEA CBC cipher function
- *
- * \param ctx XTEA context
- * \param mode XTEA_ENCRYPT or XTEA_DECRYPT
- * \param length the length of input, multiple of 8
- * \param iv initialization vector for CBC mode
- * \param input input block
- * \param output output block
- *
- * \return 0 if successful,
- * POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0
- */
-int xtea_crypt_cbc( xtea_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[8],
- unsigned char *input,
- unsigned char *output);
-
-/*
- * \brief Checkup routine
- *
- * \return 0 if successful, or 1 if the test failed
- */
-int xtea_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* xtea.h */
diff --git a/polarssl/src/library/aes.c b/polarssl/src/library/aes.c
deleted file mode 100644
index 2f52202..0000000
--- a/polarssl/src/library/aes.c
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * FIPS-197 compliant AES implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
- *
- * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
- * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_AES_C)
-
-#include "polarssl/aes.h"
-#include "polarssl/padlock.h"
-
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_ULONG_LE
-#define GET_ULONG_LE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] ) \
- | ( (unsigned long) (b)[(i) + 1] << 8 ) \
- | ( (unsigned long) (b)[(i) + 2] << 16 ) \
- | ( (unsigned long) (b)[(i) + 3] << 24 ); \
-}
-#endif
-
-#ifndef PUT_ULONG_LE
-#define PUT_ULONG_LE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
-}
-#endif
-
-#if defined(POLARSSL_PADLOCK_C)
-static int aes_padlock_ace = -1;
-#endif
-
-#if defined(POLARSSL_AES_ROM_TABLES)
-/*
- * Forward S-box
- */
-static const unsigned char FSb[256] =
-{
- 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
- 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
- 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
- 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
- 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
- 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
- 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
- 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
- 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
- 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
- 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
- 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
- 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
- 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
- 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
- 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
- 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
- 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
- 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
- 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
- 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
- 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
- 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
- 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
- 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
- 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
- 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
- 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
- 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
- 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
- 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
-};
-
-/*
- * Forward tables
- */
-#define FT \
-\
- V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
- V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
- V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
- V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
- V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
- V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
- V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
- V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
- V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
- V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
- V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
- V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
- V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
- V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
- V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
- V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
- V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
- V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
- V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
- V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
- V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
- V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
- V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
- V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
- V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
- V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
- V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
- V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
- V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
- V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
- V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
- V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
- V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
- V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
- V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
- V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
- V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
- V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
- V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
- V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
- V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
- V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
- V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
- V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
- V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
- V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
- V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
- V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
- V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
- V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
- V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
- V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
- V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
- V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
- V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
- V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
- V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
- V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
- V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
- V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
- V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
- V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
- V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
- V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
-
-#define V(a,b,c,d) 0x##a##b##c##d
-static const unsigned long FT0[256] = { FT };
-#undef V
-
-#define V(a,b,c,d) 0x##b##c##d##a
-static const unsigned long FT1[256] = { FT };
-#undef V
-
-#define V(a,b,c,d) 0x##c##d##a##b
-static const unsigned long FT2[256] = { FT };
-#undef V
-
-#define V(a,b,c,d) 0x##d##a##b##c
-static const unsigned long FT3[256] = { FT };
-#undef V
-
-#undef FT
-
-/*
- * Reverse S-box
- */
-static const unsigned char RSb[256] =
-{
- 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
- 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
- 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
- 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
- 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
- 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
- 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
- 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
- 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
- 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
- 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
- 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
- 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
- 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
- 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
- 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
- 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
- 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
- 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
- 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
- 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
- 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
- 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
- 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
- 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
- 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
- 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
- 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
- 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
- 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
- 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
-};
-
-/*
- * Reverse tables
- */
-#define RT \
-\
- V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
- V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
- V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
- V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
- V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
- V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
- V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
- V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
- V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
- V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
- V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
- V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
- V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
- V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
- V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
- V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
- V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
- V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
- V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
- V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
- V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
- V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
- V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
- V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
- V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
- V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
- V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
- V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
- V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
- V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
- V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
- V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
- V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
- V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
- V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
- V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
- V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
- V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
- V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
- V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
- V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
- V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
- V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
- V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
- V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
- V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
- V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
- V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
- V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
- V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
- V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
- V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
- V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
- V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
- V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
- V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
- V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
- V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
- V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
- V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
- V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
- V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
- V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
- V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
-
-#define V(a,b,c,d) 0x##a##b##c##d
-static const unsigned long RT0[256] = { RT };
-#undef V
-
-#define V(a,b,c,d) 0x##b##c##d##a
-static const unsigned long RT1[256] = { RT };
-#undef V
-
-#define V(a,b,c,d) 0x##c##d##a##b
-static const unsigned long RT2[256] = { RT };
-#undef V
-
-#define V(a,b,c,d) 0x##d##a##b##c
-static const unsigned long RT3[256] = { RT };
-#undef V
-
-#undef RT
-
-/*
- * Round constants
- */
-static const unsigned long RCON[10] =
-{
- 0x00000001, 0x00000002, 0x00000004, 0x00000008,
- 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x0000001B, 0x00000036
-};
-
-#else
-
-/*
- * Forward S-box & tables
- */
-static unsigned char FSb[256];
-static unsigned long FT0[256];
-static unsigned long FT1[256];
-static unsigned long FT2[256];
-static unsigned long FT3[256];
-
-/*
- * Reverse S-box & tables
- */
-static unsigned char RSb[256];
-static unsigned long RT0[256];
-static unsigned long RT1[256];
-static unsigned long RT2[256];
-static unsigned long RT3[256];
-
-/*
- * Round constants
- */
-static unsigned long RCON[10];
-
-/*
- * Tables generation code
- */
-#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
-#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
-#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
-
-static int aes_init_done = 0;
-
-static void aes_gen_tables( void )
-{
- int i, x, y, z;
- int pow[256];
- int log[256];
-
- /*
- * compute pow and log tables over GF(2^8)
- */
- for( i = 0, x = 1; i < 256; i++ )
- {
- pow[i] = x;
- log[x] = i;
- x = ( x ^ XTIME( x ) ) & 0xFF;
- }
-
- /*
- * calculate the round constants
- */
- for( i = 0, x = 1; i < 10; i++ )
- {
- RCON[i] = (unsigned long) x;
- x = XTIME( x ) & 0xFF;
- }
-
- /*
- * generate the forward and reverse S-boxes
- */
- FSb[0x00] = 0x63;
- RSb[0x63] = 0x00;
-
- for( i = 1; i < 256; i++ )
- {
- x = pow[255 - log[i]];
-
- y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y ^ 0x63;
-
- FSb[i] = (unsigned char) x;
- RSb[x] = (unsigned char) i;
- }
-
- /*
- * generate the forward and reverse tables
- */
- for( i = 0; i < 256; i++ )
- {
- x = FSb[i];
- y = XTIME( x ) & 0xFF;
- z = ( y ^ x ) & 0xFF;
-
- FT0[i] = ( (unsigned long) y ) ^
- ( (unsigned long) x << 8 ) ^
- ( (unsigned long) x << 16 ) ^
- ( (unsigned long) z << 24 );
-
- FT1[i] = ROTL8( FT0[i] );
- FT2[i] = ROTL8( FT1[i] );
- FT3[i] = ROTL8( FT2[i] );
-
- x = RSb[i];
-
- RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^
- ( (unsigned long) MUL( 0x09, x ) << 8 ) ^
- ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^
- ( (unsigned long) MUL( 0x0B, x ) << 24 );
-
- RT1[i] = ROTL8( RT0[i] );
- RT2[i] = ROTL8( RT1[i] );
- RT3[i] = ROTL8( RT2[i] );
- }
-}
-
-#endif
-
-/*
- * AES key schedule (encryption)
- */
-int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
-{
- unsigned int i;
- unsigned long *RK;
-
-#if !defined(POLARSSL_AES_ROM_TABLES)
- if( aes_init_done == 0 )
- {
- aes_gen_tables();
- aes_init_done = 1;
-
- }
-#endif
-
- switch( keysize )
- {
- case 128: ctx->nr = 10; break;
- case 192: ctx->nr = 12; break;
- case 256: ctx->nr = 14; break;
- default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
- }
-
-#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
- if( aes_padlock_ace == -1 )
- aes_padlock_ace = padlock_supports( PADLOCK_ACE );
-
- if( aes_padlock_ace )
- ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
- else
-#endif
- ctx->rk = RK = ctx->buf;
-
- for( i = 0; i < (keysize >> 5); i++ )
- {
- GET_ULONG_LE( RK[i], key, i << 2 );
- }
-
- switch( ctx->nr )
- {
- case 10:
-
- for( i = 0; i < 10; i++, RK += 4 )
- {
- RK[4] = RK[0] ^ RCON[i] ^
- ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 );
-
- RK[5] = RK[1] ^ RK[4];
- RK[6] = RK[2] ^ RK[5];
- RK[7] = RK[3] ^ RK[6];
- }
- break;
-
- case 12:
-
- for( i = 0; i < 8; i++, RK += 6 )
- {
- RK[6] = RK[0] ^ RCON[i] ^
- ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 );
-
- RK[7] = RK[1] ^ RK[6];
- RK[8] = RK[2] ^ RK[7];
- RK[9] = RK[3] ^ RK[8];
- RK[10] = RK[4] ^ RK[9];
- RK[11] = RK[5] ^ RK[10];
- }
- break;
-
- case 14:
-
- for( i = 0; i < 7; i++, RK += 8 )
- {
- RK[8] = RK[0] ^ RCON[i] ^
- ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 );
-
- RK[9] = RK[1] ^ RK[8];
- RK[10] = RK[2] ^ RK[9];
- RK[11] = RK[3] ^ RK[10];
-
- RK[12] = RK[4] ^
- ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
-
- RK[13] = RK[5] ^ RK[12];
- RK[14] = RK[6] ^ RK[13];
- RK[15] = RK[7] ^ RK[14];
- }
- break;
-
- default:
-
- break;
- }
-
- return( 0 );
-}
-
-/*
- * AES key schedule (decryption)
- */
-int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize )
-{
- int i, j;
- aes_context cty;
- unsigned long *RK;
- unsigned long *SK;
- int ret;
-
- switch( keysize )
- {
- case 128: ctx->nr = 10; break;
- case 192: ctx->nr = 12; break;
- case 256: ctx->nr = 14; break;
- default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
- }
-
-#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
- if( aes_padlock_ace == -1 )
- aes_padlock_ace = padlock_supports( PADLOCK_ACE );
-
- if( aes_padlock_ace )
- ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
- else
-#endif
- ctx->rk = RK = ctx->buf;
-
- ret = aes_setkey_enc( &cty, key, keysize );
- if( ret != 0 )
- return( ret );
-
- SK = cty.rk + cty.nr * 4;
-
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
-
- for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
- {
- for( j = 0; j < 4; j++, SK++ )
- {
- *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
- RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
- RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
- RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
- }
- }
-
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
-
- memset( &cty, 0, sizeof( aes_context ) );
-
- return( 0 );
-}
-
-#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
-{ \
- X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
- FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y3 >> 24 ) & 0xFF ]; \
- \
- X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
- FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y0 >> 24 ) & 0xFF ]; \
- \
- X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
- FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y1 >> 24 ) & 0xFF ]; \
- \
- X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
- FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y2 >> 24 ) & 0xFF ]; \
-}
-
-#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
-{ \
- X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
- RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y1 >> 24 ) & 0xFF ]; \
- \
- X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
- RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y2 >> 24 ) & 0xFF ]; \
- \
- X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
- RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y3 >> 24 ) & 0xFF ]; \
- \
- X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
- RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y0 >> 24 ) & 0xFF ]; \
-}
-
-/*
- * AES-ECB block encryption/decryption
- */
-int aes_crypt_ecb( aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] )
-{
- int i;
- unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
-
-#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
- if( aes_padlock_ace )
- {
- if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )
- return( 0 );
-
- // If padlock data misaligned, we just fall back to
- // unaccelerated mode
- //
- }
-#endif
-
- RK = ctx->rk;
-
- GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++;
- GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++;
- GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++;
- GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++;
-
- if( mode == AES_DECRYPT )
- {
- for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
- {
- AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
- AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
- }
-
- AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
-
- X0 = *RK++ ^ \
- ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^
- ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
-
- X1 = *RK++ ^ \
- ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^
- ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
-
- X2 = *RK++ ^ \
- ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^
- ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
-
- X3 = *RK++ ^ \
- ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^
- ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
- }
- else /* AES_ENCRYPT */
- {
- for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
- {
- AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
- AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
- }
-
- AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
-
- X0 = *RK++ ^ \
- ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
-
- X1 = *RK++ ^ \
- ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
-
- X2 = *RK++ ^ \
- ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
-
- X3 = *RK++ ^ \
- ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^
- ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
- ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
- ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
- }
-
- PUT_ULONG_LE( X0, output, 0 );
- PUT_ULONG_LE( X1, output, 4 );
- PUT_ULONG_LE( X2, output, 8 );
- PUT_ULONG_LE( X3, output, 12 );
-
- return( 0 );
-}
-
-/*
- * AES-CBC buffer encryption/decryption
- */
-int aes_crypt_cbc( aes_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int i;
- unsigned char temp[16];
-
- if( length % 16 )
- return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
-
-#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
- if( aes_padlock_ace )
- {
- if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
- return( 0 );
-
- // If padlock data misaligned, we just fall back to
- // unaccelerated mode
- //
- }
-#endif
-
- if( mode == AES_DECRYPT )
- {
- while( length > 0 )
- {
- memcpy( temp, input, 16 );
- aes_crypt_ecb( ctx, mode, input, output );
-
- for( i = 0; i < 16; i++ )
- output[i] = (unsigned char)( output[i] ^ iv[i] );
-
- memcpy( iv, temp, 16 );
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
- else
- {
- while( length > 0 )
- {
- for( i = 0; i < 16; i++ )
- output[i] = (unsigned char)( input[i] ^ iv[i] );
-
- aes_crypt_ecb( ctx, mode, output, output );
- memcpy( iv, output, 16 );
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
-
- return( 0 );
-}
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
-/*
- * AES-CFB128 buffer encryption/decryption
- */
-int aes_crypt_cfb128( aes_context *ctx,
- int mode,
- size_t length,
- size_t *iv_off,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int c;
- size_t n = *iv_off;
-
- if( mode == AES_DECRYPT )
- {
- while( length-- )
- {
- if( n == 0 )
- aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
-
- c = *input++;
- *output++ = (unsigned char)( c ^ iv[n] );
- iv[n] = (unsigned char) c;
-
- n = (n + 1) & 0x0F;
- }
- }
- else
- {
- while( length-- )
- {
- if( n == 0 )
- aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
-
- iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
-
- n = (n + 1) & 0x0F;
- }
- }
-
- *iv_off = n;
-
- return( 0 );
-}
-#endif /*POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-/*
- * AES-CTR buffer encryption/decryption
- */
-int aes_crypt_ctr( aes_context *ctx,
- size_t length,
- size_t *nc_off,
- unsigned char nonce_counter[16],
- unsigned char stream_block[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int c, i;
- size_t n = *nc_off;
-
- while( length-- )
- {
- if( n == 0 ) {
- aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
-
- for( i = 16; i > 0; i-- )
- if( ++nonce_counter[i - 1] != 0 )
- break;
- }
- c = *input++;
- *output++ = (unsigned char)( c ^ stream_block[n] );
-
- n = (n + 1) & 0x0F;
- }
-
- *nc_off = n;
-
- return( 0 );
-}
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <stdio.h>
-
-/*
- * AES test vectors from:
- *
- * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
- */
-static const unsigned char aes_test_ecb_dec[3][16] =
-{
- { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
- 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
- { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
- 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
- { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
- 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
-};
-
-static const unsigned char aes_test_ecb_enc[3][16] =
-{
- { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
- 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
- { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
- 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
- { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
- 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
-};
-
-static const unsigned char aes_test_cbc_dec[3][16] =
-{
- { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
- 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
- { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
- 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
- { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
- 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
-};
-
-static const unsigned char aes_test_cbc_enc[3][16] =
-{
- { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
- 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
- { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
- 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
- { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
- 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
-};
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
-/*
- * AES-CFB128 test vectors from:
- *
- * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
- */
-static const unsigned char aes_test_cfb128_key[3][32] =
-{
- { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
- 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
- { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
- 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
- 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
- { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
- 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
- 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
- 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
-};
-
-static const unsigned char aes_test_cfb128_iv[16] =
-{
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
-};
-
-static const unsigned char aes_test_cfb128_pt[64] =
-{
- 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
- 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
- 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
- 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
- 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
- 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
- 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
- 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
-};
-
-static const unsigned char aes_test_cfb128_ct[3][64] =
-{
- { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
- 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
- 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
- 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
- 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
- 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
- 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
- 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
- { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
- 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
- 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
- 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
- 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
- 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
- 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
- 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
- { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
- 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
- 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
- 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
- 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
- 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
- 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
- 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
-};
-#endif /* POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-/*
- * AES-CTR test vectors from:
- *
- * http://www.faqs.org/rfcs/rfc3686.html
- */
-
-static const unsigned char aes_test_ctr_key[3][16] =
-{
- { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
- 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
- { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
- 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
- { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
- 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
-};
-
-static const unsigned char aes_test_ctr_nonce_counter[3][16] =
-{
- { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
- { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
- 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
- { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
- 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
-};
-
-static const unsigned char aes_test_ctr_pt[3][48] =
-{
- { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
- 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
-
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
-
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
- 0x20, 0x21, 0x22, 0x23 }
-};
-
-static const unsigned char aes_test_ctr_ct[3][48] =
-{
- { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
- 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
- { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
- 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
- 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
- 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
- { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
- 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
- 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
- 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
- 0x25, 0xB2, 0x07, 0x2F }
-};
-
-static const int aes_test_ctr_len[3] =
- { 16, 32, 36 };
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-/*
- * Checkup routine
- */
-int aes_self_test( int verbose )
-{
- int i, j, u, v;
- unsigned char key[32];
- unsigned char buf[64];
- unsigned char prv[16];
- unsigned char iv[16];
-#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB)
- size_t offset;
-#endif
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- int len;
- unsigned char nonce_counter[16];
- unsigned char stream_block[16];
-#endif
- aes_context ctx;
-
- memset( key, 0, 32 );
-
- /*
- * ECB mode
- */
- for( i = 0; i < 6; i++ )
- {
- u = i >> 1;
- v = i & 1;
-
- if( verbose != 0 )
- printf( " AES-ECB-%3d (%s): ", 128 + u * 64,
- ( v == AES_DECRYPT ) ? "dec" : "enc" );
-
- memset( buf, 0, 16 );
-
- if( v == AES_DECRYPT )
- {
- aes_setkey_dec( &ctx, key, 128 + u * 64 );
-
- for( j = 0; j < 10000; j++ )
- aes_crypt_ecb( &ctx, v, buf, buf );
-
- if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
- else
- {
- aes_setkey_enc( &ctx, key, 128 + u * 64 );
-
- for( j = 0; j < 10000; j++ )
- aes_crypt_ecb( &ctx, v, buf, buf );
-
- if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- /*
- * CBC mode
- */
- for( i = 0; i < 6; i++ )
- {
- u = i >> 1;
- v = i & 1;
-
- if( verbose != 0 )
- printf( " AES-CBC-%3d (%s): ", 128 + u * 64,
- ( v == AES_DECRYPT ) ? "dec" : "enc" );
-
- memset( iv , 0, 16 );
- memset( prv, 0, 16 );
- memset( buf, 0, 16 );
-
- if( v == AES_DECRYPT )
- {
- aes_setkey_dec( &ctx, key, 128 + u * 64 );
-
- for( j = 0; j < 10000; j++ )
- aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
-
- if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
- else
- {
- aes_setkey_enc( &ctx, key, 128 + u * 64 );
-
- for( j = 0; j < 10000; j++ )
- {
- unsigned char tmp[16];
-
- aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
-
- memcpy( tmp, prv, 16 );
- memcpy( prv, buf, 16 );
- memcpy( buf, tmp, 16 );
- }
-
- if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- /*
- * CFB128 mode
- */
- for( i = 0; i < 6; i++ )
- {
- u = i >> 1;
- v = i & 1;
-
- if( verbose != 0 )
- printf( " AES-CFB128-%3d (%s): ", 128 + u * 64,
- ( v == AES_DECRYPT ) ? "dec" : "enc" );
-
- memcpy( iv, aes_test_cfb128_iv, 16 );
- memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
-
- offset = 0;
- aes_setkey_enc( &ctx, key, 128 + u * 64 );
-
- if( v == AES_DECRYPT )
- {
- memcpy( buf, aes_test_cfb128_ct[u], 64 );
- aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
-
- if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
- else
- {
- memcpy( buf, aes_test_cfb128_pt, 64 );
- aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
-
- if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-#endif /* POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- /*
- * CTR mode
- */
- for( i = 0; i < 6; i++ )
- {
- u = i >> 1;
- v = i & 1;
-
- if( verbose != 0 )
- printf( " AES-CTR-128 (%s): ",
- ( v == AES_DECRYPT ) ? "dec" : "enc" );
-
- memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
- memcpy( key, aes_test_ctr_key[u], 16 );
-
- offset = 0;
- aes_setkey_enc( &ctx, key, 128 );
-
- if( v == AES_DECRYPT )
- {
- len = aes_test_ctr_len[u];
- memcpy( buf, aes_test_ctr_ct[u], len );
-
- aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
-
- if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
- else
- {
- len = aes_test_ctr_len[u];
- memcpy( buf, aes_test_ctr_pt[u], len );
-
- aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
-
- if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/arc4.c b/polarssl/src/library/arc4.c
deleted file mode 100644
index 07665ad..0000000
--- a/polarssl/src/library/arc4.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * An implementation of the ARCFOUR algorithm
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The ARCFOUR algorithm was publicly disclosed on 94/09.
- *
- * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_ARC4_C)
-
-#include "polarssl/arc4.h"
-
-/*
- * ARC4 key schedule
- */
-void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen )
-{
- int i, j, a;
- unsigned int k;
- unsigned char *m;
-
- ctx->x = 0;
- ctx->y = 0;
- m = ctx->m;
-
- for( i = 0; i < 256; i++ )
- m[i] = (unsigned char) i;
-
- j = k = 0;
-
- for( i = 0; i < 256; i++, k++ )
- {
- if( k >= keylen ) k = 0;
-
- a = m[i];
- j = ( j + a + key[k] ) & 0xFF;
- m[i] = m[j];
- m[j] = (unsigned char) a;
- }
-}
-
-/*
- * ARC4 cipher function
- */
-int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
- unsigned char *output )
-{
- int x, y, a, b;
- size_t i;
- unsigned char *m;
-
- x = ctx->x;
- y = ctx->y;
- m = ctx->m;
-
- for( i = 0; i < length; i++ )
- {
- x = ( x + 1 ) & 0xFF; a = m[x];
- y = ( y + a ) & 0xFF; b = m[y];
-
- m[x] = (unsigned char) b;
- m[y] = (unsigned char) a;
-
- output[i] = (unsigned char)
- ( input[i] ^ m[(unsigned char)( a + b )] );
- }
-
- ctx->x = x;
- ctx->y = y;
-
- return( 0 );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <string.h>
-#include <stdio.h>
-
-/*
- * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
- *
- * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
- */
-static const unsigned char arc4_test_key[3][8] =
-{
- { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
- { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
-
-static const unsigned char arc4_test_pt[3][8] =
-{
- { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
-
-static const unsigned char arc4_test_ct[3][8] =
-{
- { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
- { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
- { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
-};
-
-/*
- * Checkup routine
- */
-int arc4_self_test( int verbose )
-{
- int i;
- unsigned char ibuf[8];
- unsigned char obuf[8];
- arc4_context ctx;
-
- for( i = 0; i < 3; i++ )
- {
- if( verbose != 0 )
- printf( " ARC4 test #%d: ", i + 1 );
-
- memcpy( ibuf, arc4_test_pt[i], 8 );
-
- arc4_setup( &ctx, (unsigned char *) arc4_test_key[i], 8 );
- arc4_crypt( &ctx, 8, ibuf, obuf );
-
- if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/asn1parse.c b/polarssl/src/library/asn1parse.c
deleted file mode 100644
index 2584774..0000000
--- a/polarssl/src/library/asn1parse.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Generic ASN.1 parsing
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_ASN1_PARSE_C)
-
-#include "polarssl/asn1.h"
-
-#if defined(POLARSSL_BIGNUM_C)
-#include "polarssl/bignum.h"
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-
-/*
- * ASN.1 DER decoding routines
- */
-int asn1_get_len( unsigned char **p,
- const unsigned char *end,
- size_t *len )
-{
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- if( ( **p & 0x80 ) == 0 )
- *len = *(*p)++;
- else
- {
- switch( **p & 0x7F )
- {
- case 1:
- if( ( end - *p ) < 2 )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- *len = (*p)[1];
- (*p) += 2;
- break;
-
- case 2:
- if( ( end - *p ) < 3 )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- *len = ( (*p)[1] << 8 ) | (*p)[2];
- (*p) += 3;
- break;
-
- case 3:
- if( ( end - *p ) < 4 )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
- (*p) += 4;
- break;
-
- case 4:
- if( ( end - *p ) < 5 )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
- (*p) += 5;
- break;
-
- default:
- return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
- }
- }
-
- if( *len > (size_t) ( end - *p ) )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- return( 0 );
-}
-
-int asn1_get_tag( unsigned char **p,
- const unsigned char *end,
- size_t *len, int tag )
-{
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- if( **p != tag )
- return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
- (*p)++;
-
- return( asn1_get_len( p, end, len ) );
-}
-
-int asn1_get_bool( unsigned char **p,
- const unsigned char *end,
- int *val )
-{
- int ret;
- size_t len;
-
- if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
- return( ret );
-
- if( len != 1 )
- return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
- *val = ( **p != 0 ) ? 1 : 0;
- (*p)++;
-
- return( 0 );
-}
-
-int asn1_get_int( unsigned char **p,
- const unsigned char *end,
- int *val )
-{
- int ret;
- size_t len;
-
- if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
- return( ret );
-
- if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
- return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
- *val = 0;
-
- while( len-- > 0 )
- {
- *val = ( *val << 8 ) | **p;
- (*p)++;
- }
-
- return( 0 );
-}
-
-#if defined(POLARSSL_BIGNUM_C)
-int asn1_get_mpi( unsigned char **p,
- const unsigned char *end,
- mpi *X )
-{
- int ret;
- size_t len;
-
- if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
- return( ret );
-
- ret = mpi_read_binary( X, *p, len );
-
- *p += len;
-
- return( ret );
-}
-#endif /* POLARSSL_BIGNUM_C */
-
-int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
- asn1_bitstring *bs)
-{
- int ret;
-
- /* Certificate type is a single byte bitstring */
- if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
- return( ret );
-
- /* Check length, subtract one for actual bit string length */
- if ( bs->len < 1 )
- return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
- bs->len -= 1;
-
- /* Get number of unused bits, ensure unused bits <= 7 */
- bs->unused_bits = **p;
- if( bs->unused_bits > 7 )
- return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
- (*p)++;
-
- /* Get actual bitstring */
- bs->p = *p;
- *p += bs->len;
-
- if( *p != end )
- return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return 0;
-}
-
-
-/*
- * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
- */
-int asn1_get_sequence_of( unsigned char **p,
- const unsigned char *end,
- asn1_sequence *cur,
- int tag)
-{
- int ret;
- size_t len;
- asn1_buf *buf;
-
- /* Get main sequence tag */
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( ret );
-
- if( *p + len != end )
- return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- while( *p < end )
- {
- buf = &(cur->buf);
- buf->tag = **p;
-
- if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
- return( ret );
-
- buf->p = *p;
- *p += buf->len;
-
- /* Allocate and assign next pointer */
- if (*p < end)
- {
- cur->next = (asn1_sequence *) malloc(
- sizeof( asn1_sequence ) );
-
- if( cur->next == NULL )
- return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
-
- cur = cur->next;
- }
- }
-
- /* Set final sequence entry's next pointer to NULL */
- cur->next = NULL;
-
- if( *p != end )
- return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-#endif
diff --git a/polarssl/src/library/asn1write.c b/polarssl/src/library/asn1write.c
deleted file mode 100644
index e50c17c..0000000
--- a/polarssl/src/library/asn1write.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * ASN.1 buffer writing functionality
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_ASN1_WRITE_C)
-
-#include "polarssl/asn1write.h"
-
-int asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
-{
- if( len < 0x80 )
- {
- if( *p - start < 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- *--(*p) = len;
- return( 1 );
- }
-
- if( len <= 0xFF )
- {
- if( *p - start < 2 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- *--(*p) = len;
- *--(*p) = 0x81;
- return( 2 );
- }
-
- if( *p - start < 3 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- // We assume we never have lengths larger than 65535 bytes
- //
- *--(*p) = len % 256;
- *--(*p) = ( len / 256 ) % 256;
- *--(*p) = 0x82;
-
- return( 3 );
-}
-
-int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
-{
- if( *p - start < 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- *--(*p) = tag;
-
- return( 1 );
-}
-
-int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X )
-{
- int ret;
- size_t len = 0;
-
- // Write the MPI
- //
- len = mpi_size( X );
-
- if( *p - start < (int) len )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- (*p) -= len;
- mpi_write_binary( X, *p, len );
-
- // DER format assumes 2s complement for numbers, so the leftmost bit
- // should be 0 for positive numbers and 1 for negative numbers.
- //
- if ( X->s ==1 && **p & 0x80 )
- {
- if( *p - start < 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- *--(*p) = 0x00;
- len += 1;
- }
-
- ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
-
- return( len );
-}
-
-int asn1_write_null( unsigned char **p, unsigned char *start )
-{
- int ret;
- size_t len = 0;
-
- // Write NULL
- //
- ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) );
-
- return( len );
-}
-
-int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid )
-{
- int ret;
- size_t len = 0;
-
- // Write OID
- //
- len = strlen( oid );
-
- if( *p - start < (int) len )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- (*p) -= len;
- memcpy( *p, oid, len );
-
- ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) );
- ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) );
-
- return( len );
-}
-
-int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
- char *algorithm_oid )
-{
- int ret;
- size_t null_len = 0;
- size_t oid_len = 0;
- size_t len = 0;
-
- // Write NULL
- //
- ASN1_CHK_ADD( null_len, asn1_write_null( p, start ) );
-
- // Write OID
- //
- ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, algorithm_oid ) );
-
- len = oid_len + null_len;
- ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + null_len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- return( len );
-}
-
-int asn1_write_int( unsigned char **p, unsigned char *start, int val )
-{
- int ret;
- size_t len = 0;
-
- // TODO negative values and values larger than 128
- // DER format assumes 2s complement for numbers, so the leftmost bit
- // should be 0 for positive numbers and 1 for negative numbers.
- //
- if( *p - start < 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- len += 1;
- *--(*p) = val;
-
- if ( val > 0 && **p & 0x80 )
- {
- if( *p - start < 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- *--(*p) = 0x00;
- len += 1;
- }
-
- ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
-
- return( len );
-}
-
-int asn1_write_printable_string( unsigned char **p, unsigned char *start,
- char *text )
-{
- int ret;
- size_t len = 0;
-
- // Write string
- //
- len = strlen( text );
-
- if( *p - start < (int) len )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- (*p) -= len;
- memcpy( *p, text, len );
-
- ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) );
-
- return( len );
-}
-
-int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
- char *text )
-{
- int ret;
- size_t len = 0;
-
- // Write string
- //
- len = strlen( text );
-
- if( *p - start < (int) len )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- (*p) -= len;
- memcpy( *p, text, len );
-
- ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) );
-
- return( len );
-}
-
-
-#endif
diff --git a/polarssl/src/library/base64.c b/polarssl/src/library/base64.c
deleted file mode 100644
index 8601c94..0000000
--- a/polarssl/src/library/base64.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * RFC 1521 base64 encoding/decoding
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_BASE64_C)
-
-#include "polarssl/base64.h"
-
-static const unsigned char base64_enc_map[64] =
-{
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
- 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', '+', '/'
-};
-
-static const unsigned char base64_dec_map[128] =
-{
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
- 127, 64, 127, 127, 127, 0, 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, 127, 127, 127, 127, 127, 127, 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, 127, 127, 127, 127, 127
-};
-
-/*
- * Encode a buffer into base64 format
- */
-int base64_encode( unsigned char *dst, size_t *dlen,
- const unsigned char *src, size_t slen )
-{
- size_t i, n;
- int C1, C2, C3;
- unsigned char *p;
-
- if( slen == 0 )
- return( 0 );
-
- n = (slen << 3) / 6;
-
- switch( (slen << 3) - (n * 6) )
- {
- case 2: n += 3; break;
- case 4: n += 2; break;
- default: break;
- }
-
- if( *dlen < n + 1 )
- {
- *dlen = n + 1;
- return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
- }
-
- n = (slen / 3) * 3;
-
- for( i = 0, p = dst; i < n; i += 3 )
- {
- C1 = *src++;
- C2 = *src++;
- C3 = *src++;
-
- *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
- *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
- *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
- *p++ = base64_enc_map[C3 & 0x3F];
- }
-
- if( i < slen )
- {
- C1 = *src++;
- C2 = ((i + 1) < slen) ? *src++ : 0;
-
- *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
- *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
-
- if( (i + 1) < slen )
- *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
- else *p++ = '=';
-
- *p++ = '=';
- }
-
- *dlen = p - dst;
- *p = 0;
-
- return( 0 );
-}
-
-/*
- * Decode a base64-formatted buffer
- */
-int base64_decode( unsigned char *dst, size_t *dlen,
- const unsigned char *src, size_t slen )
-{
- size_t i, j, n;
- unsigned long x;
- unsigned char *p;
-
- for( i = j = n = 0; i < slen; i++ )
- {
- if( ( slen - i ) >= 2 &&
- src[i] == '\r' && src[i + 1] == '\n' )
- continue;
-
- if( src[i] == '\n' )
- continue;
-
- if( src[i] == '=' && ++j > 2 )
- return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
-
- if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
- return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
-
- if( base64_dec_map[src[i]] < 64 && j != 0 )
- return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
-
- n++;
- }
-
- if( n == 0 )
- return( 0 );
-
- n = ((n * 6) + 7) >> 3;
-
- if( *dlen < n )
- {
- *dlen = n;
- return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
- }
-
- for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
- {
- if( *src == '\r' || *src == '\n' )
- continue;
-
- j -= ( base64_dec_map[*src] == 64 );
- x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
-
- if( ++n == 4 )
- {
- n = 0;
- if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
- if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
- if( j > 2 ) *p++ = (unsigned char)( x );
- }
- }
-
- *dlen = p - dst;
-
- return( 0 );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <string.h>
-#include <stdio.h>
-
-static const unsigned char base64_test_dec[64] =
-{
- 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
- 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
- 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
- 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
- 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
- 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
- 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
- 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
-};
-
-static const unsigned char base64_test_enc[] =
- "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
- "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
-
-/*
- * Checkup routine
- */
-int base64_self_test( int verbose )
-{
- size_t len;
- unsigned char *src, buffer[128];
-
- if( verbose != 0 )
- printf( " Base64 encoding test: " );
-
- len = sizeof( buffer );
- src = (unsigned char *) base64_test_dec;
-
- if( base64_encode( buffer, &len, src, 64 ) != 0 ||
- memcmp( base64_test_enc, buffer, 88 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n Base64 decoding test: " );
-
- len = sizeof( buffer );
- src = (unsigned char *) base64_test_enc;
-
- if( base64_decode( buffer, &len, src, 88 ) != 0 ||
- memcmp( base64_test_dec, buffer, 64 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/bignum.c b/polarssl/src/library/bignum.c
deleted file mode 100644
index 0cb9505..0000000
--- a/polarssl/src/library/bignum.c
+++ /dev/null
@@ -1,2111 +0,0 @@
-/*
- * Multi-precision integer library
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * This MPI implementation is based on:
- *
- * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
- * http://www.stillhq.com/extracted/gnupg-api/mpi/
- * http://math.libtomcrypt.com/files/tommath.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_BIGNUM_C)
-
-#include "polarssl/bignum.h"
-#include "polarssl/bn_mul.h"
-
-#include <stdlib.h>
-
-#define ciL (sizeof(t_uint)) /* chars in limb */
-#define biL (ciL << 3) /* bits in limb */
-#define biH (ciL << 2) /* half limb size */
-
-/*
- * Convert between bits/chars and number of limbs
- */
-#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
-#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
-
-/*
- * Initialize one MPI
- */
-void mpi_init( mpi *X )
-{
- if( X == NULL )
- return;
-
- X->s = 1;
- X->n = 0;
- X->p = NULL;
-}
-
-/*
- * Unallocate one MPI
- */
-void mpi_free( mpi *X )
-{
- if( X == NULL )
- return;
-
- if( X->p != NULL )
- {
- memset( X->p, 0, X->n * ciL );
- free( X->p );
- }
-
- X->s = 1;
- X->n = 0;
- X->p = NULL;
-}
-
-/*
- * Enlarge to the specified number of limbs
- */
-int mpi_grow( mpi *X, size_t nblimbs )
-{
- t_uint *p;
-
- if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
- return( POLARSSL_ERR_MPI_MALLOC_FAILED );
-
- if( X->n < nblimbs )
- {
- if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
- return( POLARSSL_ERR_MPI_MALLOC_FAILED );
-
- memset( p, 0, nblimbs * ciL );
-
- if( X->p != NULL )
- {
- memcpy( p, X->p, X->n * ciL );
- memset( X->p, 0, X->n * ciL );
- free( X->p );
- }
-
- X->n = nblimbs;
- X->p = p;
- }
-
- return( 0 );
-}
-
-/*
- * Copy the contents of Y into X
- */
-int mpi_copy( mpi *X, const mpi *Y )
-{
- int ret;
- size_t i;
-
- if( X == Y )
- return( 0 );
-
- for( i = Y->n - 1; i > 0; i-- )
- if( Y->p[i] != 0 )
- break;
- i++;
-
- X->s = Y->s;
-
- MPI_CHK( mpi_grow( X, i ) );
-
- memset( X->p, 0, X->n * ciL );
- memcpy( X->p, Y->p, i * ciL );
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Swap the contents of X and Y
- */
-void mpi_swap( mpi *X, mpi *Y )
-{
- mpi T;
-
- memcpy( &T, X, sizeof( mpi ) );
- memcpy( X, Y, sizeof( mpi ) );
- memcpy( Y, &T, sizeof( mpi ) );
-}
-
-/*
- * Set value from integer
- */
-int mpi_lset( mpi *X, t_sint z )
-{
- int ret;
-
- MPI_CHK( mpi_grow( X, 1 ) );
- memset( X->p, 0, X->n * ciL );
-
- X->p[0] = ( z < 0 ) ? -z : z;
- X->s = ( z < 0 ) ? -1 : 1;
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Get a specific bit
- */
-int mpi_get_bit( mpi *X, size_t pos )
-{
- if( X->n * biL <= pos )
- return( 0 );
-
- return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
-}
-
-/*
- * Set a bit to a specific value of 0 or 1
- */
-int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
-{
- int ret = 0;
- size_t off = pos / biL;
- size_t idx = pos % biL;
-
- if( val != 0 && val != 1 )
- return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
-
- if( X->n * biL <= pos )
- {
- if( val == 0 )
- return ( 0 );
-
- MPI_CHK( mpi_grow( X, off + 1 ) );
- }
-
- X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Return the number of least significant bits
- */
-size_t mpi_lsb( const mpi *X )
-{
- size_t i, j, count = 0;
-
- for( i = 0; i < X->n; i++ )
- for( j = 0; j < biL; j++, count++ )
- if( ( ( X->p[i] >> j ) & 1 ) != 0 )
- return( count );
-
- return( 0 );
-}
-
-/*
- * Return the number of most significant bits
- */
-size_t mpi_msb( const mpi *X )
-{
- size_t i, j;
-
- for( i = X->n - 1; i > 0; i-- )
- if( X->p[i] != 0 )
- break;
-
- for( j = biL; j > 0; j-- )
- if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
- break;
-
- return( ( i * biL ) + j );
-}
-
-/*
- * Return the total size in bytes
- */
-size_t mpi_size( const mpi *X )
-{
- return( ( mpi_msb( X ) + 7 ) >> 3 );
-}
-
-/*
- * Convert an ASCII character to digit value
- */
-static int mpi_get_digit( t_uint *d, int radix, char c )
-{
- *d = 255;
-
- if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
- if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
- if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
-
- if( *d >= (t_uint) radix )
- return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
-
- return( 0 );
-}
-
-/*
- * Import from an ASCII string
- */
-int mpi_read_string( mpi *X, int radix, const char *s )
-{
- int ret;
- size_t i, j, slen, n;
- t_uint d;
- mpi T;
-
- if( radix < 2 || radix > 16 )
- return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
- mpi_init( &T );
-
- slen = strlen( s );
-
- if( radix == 16 )
- {
- n = BITS_TO_LIMBS( slen << 2 );
-
- MPI_CHK( mpi_grow( X, n ) );
- MPI_CHK( mpi_lset( X, 0 ) );
-
- for( i = slen, j = 0; i > 0; i--, j++ )
- {
- if( i == 1 && s[i - 1] == '-' )
- {
- X->s = -1;
- break;
- }
-
- MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
- X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
- }
- }
- else
- {
- MPI_CHK( mpi_lset( X, 0 ) );
-
- for( i = 0; i < slen; i++ )
- {
- if( i == 0 && s[i] == '-' )
- {
- X->s = -1;
- continue;
- }
-
- MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
- MPI_CHK( mpi_mul_int( &T, X, radix ) );
-
- if( X->s == 1 )
- {
- MPI_CHK( mpi_add_int( X, &T, d ) );
- }
- else
- {
- MPI_CHK( mpi_sub_int( X, &T, d ) );
- }
- }
- }
-
-cleanup:
-
- mpi_free( &T );
-
- return( ret );
-}
-
-/*
- * Helper to write the digits high-order first
- */
-static int mpi_write_hlp( mpi *X, int radix, char **p )
-{
- int ret;
- t_uint r;
-
- if( radix < 2 || radix > 16 )
- return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
- MPI_CHK( mpi_mod_int( &r, X, radix ) );
- MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
-
- if( mpi_cmp_int( X, 0 ) != 0 )
- MPI_CHK( mpi_write_hlp( X, radix, p ) );
-
- if( r < 10 )
- *(*p)++ = (char)( r + 0x30 );
- else
- *(*p)++ = (char)( r + 0x37 );
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Export into an ASCII string
- */
-int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
-{
- int ret = 0;
- size_t n;
- char *p;
- mpi T;
-
- if( radix < 2 || radix > 16 )
- return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
- n = mpi_msb( X );
- if( radix >= 4 ) n >>= 1;
- if( radix >= 16 ) n >>= 1;
- n += 3;
-
- if( *slen < n )
- {
- *slen = n;
- return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
- }
-
- p = s;
- mpi_init( &T );
-
- if( X->s == -1 )
- *p++ = '-';
-
- if( radix == 16 )
- {
- int c;
- size_t i, j, k;
-
- for( i = X->n, k = 0; i > 0; i-- )
- {
- for( j = ciL; j > 0; j-- )
- {
- c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
-
- if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
- continue;
-
- p += sprintf( p, "%02X", c );
- k = 1;
- }
- }
- }
- else
- {
- MPI_CHK( mpi_copy( &T, X ) );
-
- if( T.s == -1 )
- T.s = 1;
-
- MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
- }
-
- *p++ = '\0';
- *slen = p - s;
-
-cleanup:
-
- mpi_free( &T );
-
- return( ret );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * Read X from an opened file
- */
-int mpi_read_file( mpi *X, int radix, FILE *fin )
-{
- t_uint d;
- size_t slen;
- char *p;
- /*
- * Buffer should have space for (short) label and decimal formatted MPI,
- * newline characters and '\0'
- */
- char s[ POLARSSL_MPI_READ_BUFFER_SIZE ];
-
- memset( s, 0, sizeof( s ) );
- if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
- return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
-
- slen = strlen( s );
- if( slen == sizeof( s ) - 2 )
- return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
-
- if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
- if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
-
- p = s + slen;
- while( --p >= s )
- if( mpi_get_digit( &d, radix, *p ) != 0 )
- break;
-
- return( mpi_read_string( X, radix, p + 1 ) );
-}
-
-/*
- * Write X into an opened file (or stdout if fout == NULL)
- */
-int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
-{
- int ret;
- size_t n, slen, plen;
- /*
- * Buffer should have space for minus sign, hexified MPI and '\0'
- */
- char s[ 2 * POLARSSL_MPI_MAX_SIZE + 2 ];
-
- n = sizeof( s );
- memset( s, 0, n );
- n -= 2;
-
- MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
-
- if( p == NULL ) p = "";
-
- plen = strlen( p );
- slen = strlen( s );
- s[slen++] = '\r';
- s[slen++] = '\n';
-
- if( fout != NULL )
- {
- if( fwrite( p, 1, plen, fout ) != plen ||
- fwrite( s, 1, slen, fout ) != slen )
- return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
- }
- else
- printf( "%s%s", p, s );
-
-cleanup:
-
- return( ret );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * Import X from unsigned binary data, big endian
- */
-int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
-{
- int ret;
- size_t i, j, n;
-
- for( n = 0; n < buflen; n++ )
- if( buf[n] != 0 )
- break;
-
- MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
- MPI_CHK( mpi_lset( X, 0 ) );
-
- for( i = buflen, j = 0; i > n; i--, j++ )
- X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Export X into unsigned binary data, big endian
- */
-int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
-{
- size_t i, j, n;
-
- n = mpi_size( X );
-
- if( buflen < n )
- return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
-
- memset( buf, 0, buflen );
-
- for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
- buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
-
- return( 0 );
-}
-
-/*
- * Left-shift: X <<= count
- */
-int mpi_shift_l( mpi *X, size_t count )
-{
- int ret;
- size_t i, v0, t1;
- t_uint r0 = 0, r1;
-
- v0 = count / (biL );
- t1 = count & (biL - 1);
-
- i = mpi_msb( X ) + count;
-
- if( X->n * biL < i )
- MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
-
- ret = 0;
-
- /*
- * shift by count / limb_size
- */
- if( v0 > 0 )
- {
- for( i = X->n; i > v0; i-- )
- X->p[i - 1] = X->p[i - v0 - 1];
-
- for( ; i > 0; i-- )
- X->p[i - 1] = 0;
- }
-
- /*
- * shift by count % limb_size
- */
- if( t1 > 0 )
- {
- for( i = v0; i < X->n; i++ )
- {
- r1 = X->p[i] >> (biL - t1);
- X->p[i] <<= t1;
- X->p[i] |= r0;
- r0 = r1;
- }
- }
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Right-shift: X >>= count
- */
-int mpi_shift_r( mpi *X, size_t count )
-{
- size_t i, v0, v1;
- t_uint r0 = 0, r1;
-
- v0 = count / biL;
- v1 = count & (biL - 1);
-
- /*
- * shift by count / limb_size
- */
- if( v0 > 0 )
- {
- for( i = 0; i < X->n - v0; i++ )
- X->p[i] = X->p[i + v0];
-
- for( ; i < X->n; i++ )
- X->p[i] = 0;
- }
-
- /*
- * shift by count % limb_size
- */
- if( v1 > 0 )
- {
- for( i = X->n; i > 0; i-- )
- {
- r1 = X->p[i - 1] << (biL - v1);
- X->p[i - 1] >>= v1;
- X->p[i - 1] |= r0;
- r0 = r1;
- }
- }
-
- return( 0 );
-}
-
-/*
- * Compare unsigned values
- */
-int mpi_cmp_abs( const mpi *X, const mpi *Y )
-{
- size_t i, j;
-
- for( i = X->n; i > 0; i-- )
- if( X->p[i - 1] != 0 )
- break;
-
- for( j = Y->n; j > 0; j-- )
- if( Y->p[j - 1] != 0 )
- break;
-
- if( i == 0 && j == 0 )
- return( 0 );
-
- if( i > j ) return( 1 );
- if( j > i ) return( -1 );
-
- for( ; i > 0; i-- )
- {
- if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
- if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
- }
-
- return( 0 );
-}
-
-/*
- * Compare signed values
- */
-int mpi_cmp_mpi( const mpi *X, const mpi *Y )
-{
- size_t i, j;
-
- for( i = X->n; i > 0; i-- )
- if( X->p[i - 1] != 0 )
- break;
-
- for( j = Y->n; j > 0; j-- )
- if( Y->p[j - 1] != 0 )
- break;
-
- if( i == 0 && j == 0 )
- return( 0 );
-
- if( i > j ) return( X->s );
- if( j > i ) return( -Y->s );
-
- if( X->s > 0 && Y->s < 0 ) return( 1 );
- if( Y->s > 0 && X->s < 0 ) return( -1 );
-
- for( ; i > 0; i-- )
- {
- if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
- if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
- }
-
- return( 0 );
-}
-
-/*
- * Compare signed values
- */
-int mpi_cmp_int( const mpi *X, t_sint z )
-{
- mpi Y;
- t_uint p[1];
-
- *p = ( z < 0 ) ? -z : z;
- Y.s = ( z < 0 ) ? -1 : 1;
- Y.n = 1;
- Y.p = p;
-
- return( mpi_cmp_mpi( X, &Y ) );
-}
-
-/*
- * Unsigned addition: X = |A| + |B| (HAC 14.7)
- */
-int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
-{
- int ret;
- size_t i, j;
- t_uint *o, *p, c;
-
- if( X == B )
- {
- const mpi *T = A; A = X; B = T;
- }
-
- if( X != A )
- MPI_CHK( mpi_copy( X, A ) );
-
- /*
- * X should always be positive as a result of unsigned additions.
- */
- X->s = 1;
-
- for( j = B->n; j > 0; j-- )
- if( B->p[j - 1] != 0 )
- break;
-
- MPI_CHK( mpi_grow( X, j ) );
-
- o = B->p; p = X->p; c = 0;
-
- for( i = 0; i < j; i++, o++, p++ )
- {
- *p += c; c = ( *p < c );
- *p += *o; c += ( *p < *o );
- }
-
- while( c != 0 )
- {
- if( i >= X->n )
- {
- MPI_CHK( mpi_grow( X, i + 1 ) );
- p = X->p + i;
- }
-
- *p += c; c = ( *p < c ); i++;
- }
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Helper for mpi substraction
- */
-static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
-{
- size_t i;
- t_uint c, z;
-
- for( i = c = 0; i < n; i++, s++, d++ )
- {
- z = ( *d < c ); *d -= c;
- c = ( *d < *s ) + z; *d -= *s;
- }
-
- while( c != 0 )
- {
- z = ( *d < c ); *d -= c;
- c = z; i++; d++;
- }
-}
-
-/*
- * Unsigned substraction: X = |A| - |B| (HAC 14.9)
- */
-int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
-{
- mpi TB;
- int ret;
- size_t n;
-
- if( mpi_cmp_abs( A, B ) < 0 )
- return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
-
- mpi_init( &TB );
-
- if( X == B )
- {
- MPI_CHK( mpi_copy( &TB, B ) );
- B = &TB;
- }
-
- if( X != A )
- MPI_CHK( mpi_copy( X, A ) );
-
- /*
- * X should always be positive as a result of unsigned substractions.
- */
- X->s = 1;
-
- ret = 0;
-
- for( n = B->n; n > 0; n-- )
- if( B->p[n - 1] != 0 )
- break;
-
- mpi_sub_hlp( n, B->p, X->p );
-
-cleanup:
-
- mpi_free( &TB );
-
- return( ret );
-}
-
-/*
- * Signed addition: X = A + B
- */
-int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
-{
- int ret, s = A->s;
-
- if( A->s * B->s < 0 )
- {
- if( mpi_cmp_abs( A, B ) >= 0 )
- {
- MPI_CHK( mpi_sub_abs( X, A, B ) );
- X->s = s;
- }
- else
- {
- MPI_CHK( mpi_sub_abs( X, B, A ) );
- X->s = -s;
- }
- }
- else
- {
- MPI_CHK( mpi_add_abs( X, A, B ) );
- X->s = s;
- }
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Signed substraction: X = A - B
- */
-int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
-{
- int ret, s = A->s;
-
- if( A->s * B->s > 0 )
- {
- if( mpi_cmp_abs( A, B ) >= 0 )
- {
- MPI_CHK( mpi_sub_abs( X, A, B ) );
- X->s = s;
- }
- else
- {
- MPI_CHK( mpi_sub_abs( X, B, A ) );
- X->s = -s;
- }
- }
- else
- {
- MPI_CHK( mpi_add_abs( X, A, B ) );
- X->s = s;
- }
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Signed addition: X = A + b
- */
-int mpi_add_int( mpi *X, const mpi *A, t_sint b )
-{
- mpi _B;
- t_uint p[1];
-
- p[0] = ( b < 0 ) ? -b : b;
- _B.s = ( b < 0 ) ? -1 : 1;
- _B.n = 1;
- _B.p = p;
-
- return( mpi_add_mpi( X, A, &_B ) );
-}
-
-/*
- * Signed substraction: X = A - b
- */
-int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
-{
- mpi _B;
- t_uint p[1];
-
- p[0] = ( b < 0 ) ? -b : b;
- _B.s = ( b < 0 ) ? -1 : 1;
- _B.n = 1;
- _B.p = p;
-
- return( mpi_sub_mpi( X, A, &_B ) );
-}
-
-/*
- * Helper for mpi multiplication
- */
-static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
-{
- t_uint c = 0, t = 0;
-
-#if defined(MULADDC_HUIT)
- for( ; i >= 8; i -= 8 )
- {
- MULADDC_INIT
- MULADDC_HUIT
- MULADDC_STOP
- }
-
- for( ; i > 0; i-- )
- {
- MULADDC_INIT
- MULADDC_CORE
- MULADDC_STOP
- }
-#else
- for( ; i >= 16; i -= 16 )
- {
- MULADDC_INIT
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
-
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
- MULADDC_STOP
- }
-
- for( ; i >= 8; i -= 8 )
- {
- MULADDC_INIT
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
-
- MULADDC_CORE MULADDC_CORE
- MULADDC_CORE MULADDC_CORE
- MULADDC_STOP
- }
-
- for( ; i > 0; i-- )
- {
- MULADDC_INIT
- MULADDC_CORE
- MULADDC_STOP
- }
-#endif
-
- t++;
-
- do {
- *d += c; c = ( *d < c ); d++;
- }
- while( c != 0 );
-}
-
-/*
- * Baseline multiplication: X = A * B (HAC 14.12)
- */
-int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
-{
- int ret;
- size_t i, j;
- mpi TA, TB;
-
- mpi_init( &TA ); mpi_init( &TB );
-
- if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
- if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
-
- for( i = A->n; i > 0; i-- )
- if( A->p[i - 1] != 0 )
- break;
-
- for( j = B->n; j > 0; j-- )
- if( B->p[j - 1] != 0 )
- break;
-
- MPI_CHK( mpi_grow( X, i + j ) );
- MPI_CHK( mpi_lset( X, 0 ) );
-
- for( i++; j > 0; j-- )
- mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
-
- X->s = A->s * B->s;
-
-cleanup:
-
- mpi_free( &TB ); mpi_free( &TA );
-
- return( ret );
-}
-
-/*
- * Baseline multiplication: X = A * b
- */
-int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
-{
- mpi _B;
- t_uint p[1];
-
- _B.s = 1;
- _B.n = 1;
- _B.p = p;
- p[0] = b;
-
- return( mpi_mul_mpi( X, A, &_B ) );
-}
-
-/*
- * Division by mpi: A = Q * B + R (HAC 14.20)
- */
-int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
-{
- int ret;
- size_t i, n, t, k;
- mpi X, Y, Z, T1, T2;
-
- if( mpi_cmp_int( B, 0 ) == 0 )
- return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
-
- mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
- mpi_init( &T1 ); mpi_init( &T2 );
-
- if( mpi_cmp_abs( A, B ) < 0 )
- {
- if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
- if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
- return( 0 );
- }
-
- MPI_CHK( mpi_copy( &X, A ) );
- MPI_CHK( mpi_copy( &Y, B ) );
- X.s = Y.s = 1;
-
- MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
- MPI_CHK( mpi_lset( &Z, 0 ) );
- MPI_CHK( mpi_grow( &T1, 2 ) );
- MPI_CHK( mpi_grow( &T2, 3 ) );
-
- k = mpi_msb( &Y ) % biL;
- if( k < biL - 1 )
- {
- k = biL - 1 - k;
- MPI_CHK( mpi_shift_l( &X, k ) );
- MPI_CHK( mpi_shift_l( &Y, k ) );
- }
- else k = 0;
-
- n = X.n - 1;
- t = Y.n - 1;
- mpi_shift_l( &Y, biL * (n - t) );
-
- while( mpi_cmp_mpi( &X, &Y ) >= 0 )
- {
- Z.p[n - t]++;
- mpi_sub_mpi( &X, &X, &Y );
- }
- mpi_shift_r( &Y, biL * (n - t) );
-
- for( i = n; i > t ; i-- )
- {
- if( X.p[i] >= Y.p[t] )
- Z.p[i - t - 1] = ~0;
- else
- {
-#if defined(POLARSSL_HAVE_LONGLONG)
- t_udbl r;
-
- r = (t_udbl) X.p[i] << biL;
- r |= (t_udbl) X.p[i - 1];
- r /= Y.p[t];
- if( r > ((t_udbl) 1 << biL) - 1)
- r = ((t_udbl) 1 << biL) - 1;
-
- Z.p[i - t - 1] = (t_uint) r;
-#else
- /*
- * __udiv_qrnnd_c, from gmp/longlong.h
- */
- t_uint q0, q1, r0, r1;
- t_uint d0, d1, d, m;
-
- d = Y.p[t];
- d0 = ( d << biH ) >> biH;
- d1 = ( d >> biH );
-
- q1 = X.p[i] / d1;
- r1 = X.p[i] - d1 * q1;
- r1 <<= biH;
- r1 |= ( X.p[i - 1] >> biH );
-
- m = q1 * d0;
- if( r1 < m )
- {
- q1--, r1 += d;
- while( r1 >= d && r1 < m )
- q1--, r1 += d;
- }
- r1 -= m;
-
- q0 = r1 / d1;
- r0 = r1 - d1 * q0;
- r0 <<= biH;
- r0 |= ( X.p[i - 1] << biH ) >> biH;
-
- m = q0 * d0;
- if( r0 < m )
- {
- q0--, r0 += d;
- while( r0 >= d && r0 < m )
- q0--, r0 += d;
- }
- r0 -= m;
-
- Z.p[i - t - 1] = ( q1 << biH ) | q0;
-#endif
- }
-
- Z.p[i - t - 1]++;
- do
- {
- Z.p[i - t - 1]--;
-
- MPI_CHK( mpi_lset( &T1, 0 ) );
- T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
- T1.p[1] = Y.p[t];
- MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
-
- MPI_CHK( mpi_lset( &T2, 0 ) );
- T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
- T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
- T2.p[2] = X.p[i];
- }
- while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
-
- MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
- MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
- MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
-
- if( mpi_cmp_int( &X, 0 ) < 0 )
- {
- MPI_CHK( mpi_copy( &T1, &Y ) );
- MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
- MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
- Z.p[i - t - 1]--;
- }
- }
-
- if( Q != NULL )
- {
- mpi_copy( Q, &Z );
- Q->s = A->s * B->s;
- }
-
- if( R != NULL )
- {
- mpi_shift_r( &X, k );
- mpi_copy( R, &X );
-
- R->s = A->s;
- if( mpi_cmp_int( R, 0 ) == 0 )
- R->s = 1;
- }
-
-cleanup:
-
- mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
- mpi_free( &T1 ); mpi_free( &T2 );
-
- return( ret );
-}
-
-/*
- * Division by int: A = Q * b + R
- *
- * Returns 0 if successful
- * 1 if memory allocation failed
- * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
- */
-int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
-{
- mpi _B;
- t_uint p[1];
-
- p[0] = ( b < 0 ) ? -b : b;
- _B.s = ( b < 0 ) ? -1 : 1;
- _B.n = 1;
- _B.p = p;
-
- return( mpi_div_mpi( Q, R, A, &_B ) );
-}
-
-/*
- * Modulo: R = A mod B
- */
-int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
-{
- int ret;
-
- if( mpi_cmp_int( B, 0 ) < 0 )
- return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
-
- MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
-
- while( mpi_cmp_int( R, 0 ) < 0 )
- MPI_CHK( mpi_add_mpi( R, R, B ) );
-
- while( mpi_cmp_mpi( R, B ) >= 0 )
- MPI_CHK( mpi_sub_mpi( R, R, B ) );
-
-cleanup:
-
- return( ret );
-}
-
-/*
- * Modulo: r = A mod b
- */
-int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
-{
- size_t i;
- t_uint x, y, z;
-
- if( b == 0 )
- return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
-
- if( b < 0 )
- return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
-
- /*
- * handle trivial cases
- */
- if( b == 1 )
- {
- *r = 0;
- return( 0 );
- }
-
- if( b == 2 )
- {
- *r = A->p[0] & 1;
- return( 0 );
- }
-
- /*
- * general case
- */
- for( i = A->n, y = 0; i > 0; i-- )
- {
- x = A->p[i - 1];
- y = ( y << biH ) | ( x >> biH );
- z = y / b;
- y -= z * b;
-
- x <<= biH;
- y = ( y << biH ) | ( x >> biH );
- z = y / b;
- y -= z * b;
- }
-
- /*
- * If A is negative, then the current y represents a negative value.
- * Flipping it to the positive side.
- */
- if( A->s < 0 && y != 0 )
- y = b - y;
-
- *r = y;
-
- return( 0 );
-}
-
-/*
- * Fast Montgomery initialization (thanks to Tom St Denis)
- */
-static void mpi_montg_init( t_uint *mm, const mpi *N )
-{
- t_uint x, m0 = N->p[0];
-
- x = m0;
- x += ( ( m0 + 2 ) & 4 ) << 1;
- x *= ( 2 - ( m0 * x ) );
-
- if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
- if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
- if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
-
- *mm = ~x + 1;
-}
-
-/*
- * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
- */
-static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
-{
- size_t i, n, m;
- t_uint u0, u1, *d;
-
- memset( T->p, 0, T->n * ciL );
-
- d = T->p;
- n = N->n;
- m = ( B->n < n ) ? B->n : n;
-
- for( i = 0; i < n; i++ )
- {
- /*
- * T = (T + u0*B + u1*N) / 2^biL
- */
- u0 = A->p[i];
- u1 = ( d[0] + u0 * B->p[0] ) * mm;
-
- mpi_mul_hlp( m, B->p, d, u0 );
- mpi_mul_hlp( n, N->p, d, u1 );
-
- *d++ = u0; d[n + 1] = 0;
- }
-
- memcpy( A->p, d, (n + 1) * ciL );
-
- if( mpi_cmp_abs( A, N ) >= 0 )
- mpi_sub_hlp( n, N->p, A->p );
- else
- /* prevent timing attacks */
- mpi_sub_hlp( n, A->p, T->p );
-}
-
-/*
- * Montgomery reduction: A = A * R^-1 mod N
- */
-static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
-{
- t_uint z = 1;
- mpi U;
-
- U.n = U.s = z;
- U.p = &z;
-
- mpi_montmul( A, &U, N, mm, T );
-}
-
-/*
- * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
- */
-int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
-{
- int ret;
- size_t wbits, wsize, one = 1;
- size_t i, j, nblimbs;
- size_t bufsize, nbits;
- t_uint ei, mm, state;
- mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ];
-
- if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
- return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
- /*
- * Init temps and window size
- */
- mpi_montg_init( &mm, N );
- mpi_init( &RR ); mpi_init( &T );
- memset( W, 0, sizeof( W ) );
-
- i = mpi_msb( E );
-
- wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
- ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
-
- if( wsize > POLARSSL_MPI_WINDOW_SIZE )
- wsize = POLARSSL_MPI_WINDOW_SIZE;
-
- j = N->n + 1;
- MPI_CHK( mpi_grow( X, j ) );
- MPI_CHK( mpi_grow( &W[1], j ) );
- MPI_CHK( mpi_grow( &T, j * 2 ) );
-
- /*
- * If 1st call, pre-compute R^2 mod N
- */
- if( _RR == NULL || _RR->p == NULL )
- {
- MPI_CHK( mpi_lset( &RR, 1 ) );
- MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
- MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
-
- if( _RR != NULL )
- memcpy( _RR, &RR, sizeof( mpi ) );
- }
- else
- memcpy( &RR, _RR, sizeof( mpi ) );
-
- /*
- * W[1] = A * R^2 * R^-1 mod N = A * R mod N
- */
- if( mpi_cmp_mpi( A, N ) >= 0 )
- mpi_mod_mpi( &W[1], A, N );
- else mpi_copy( &W[1], A );
-
- mpi_montmul( &W[1], &RR, N, mm, &T );
-
- /*
- * X = R^2 * R^-1 mod N = R mod N
- */
- MPI_CHK( mpi_copy( X, &RR ) );
- mpi_montred( X, N, mm, &T );
-
- if( wsize > 1 )
- {
- /*
- * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
- */
- j = one << (wsize - 1);
-
- MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
- MPI_CHK( mpi_copy( &W[j], &W[1] ) );
-
- for( i = 0; i < wsize - 1; i++ )
- mpi_montmul( &W[j], &W[j], N, mm, &T );
-
- /*
- * W[i] = W[i - 1] * W[1]
- */
- for( i = j + 1; i < (one << wsize); i++ )
- {
- MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
- MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
-
- mpi_montmul( &W[i], &W[1], N, mm, &T );
- }
- }
-
- nblimbs = E->n;
- bufsize = 0;
- nbits = 0;
- wbits = 0;
- state = 0;
-
- while( 1 )
- {
- if( bufsize == 0 )
- {
- if( nblimbs-- == 0 )
- break;
-
- bufsize = sizeof( t_uint ) << 3;
- }
-
- bufsize--;
-
- ei = (E->p[nblimbs] >> bufsize) & 1;
-
- /*
- * skip leading 0s
- */
- if( ei == 0 && state == 0 )
- continue;
-
- if( ei == 0 && state == 1 )
- {
- /*
- * out of window, square X
- */
- mpi_montmul( X, X, N, mm, &T );
- continue;
- }
-
- /*
- * add ei to current window
- */
- state = 2;
-
- nbits++;
- wbits |= (ei << (wsize - nbits));
-
- if( nbits == wsize )
- {
- /*
- * X = X^wsize R^-1 mod N
- */
- for( i = 0; i < wsize; i++ )
- mpi_montmul( X, X, N, mm, &T );
-
- /*
- * X = X * W[wbits] R^-1 mod N
- */
- mpi_montmul( X, &W[wbits], N, mm, &T );
-
- state--;
- nbits = 0;
- wbits = 0;
- }
- }
-
- /*
- * process the remaining bits
- */
- for( i = 0; i < nbits; i++ )
- {
- mpi_montmul( X, X, N, mm, &T );
-
- wbits <<= 1;
-
- if( (wbits & (one << wsize)) != 0 )
- mpi_montmul( X, &W[1], N, mm, &T );
- }
-
- /*
- * X = A^E * R * R^-1 mod N = A^E mod N
- */
- mpi_montred( X, N, mm, &T );
-
-cleanup:
-
- for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
- mpi_free( &W[i] );
-
- mpi_free( &W[1] ); mpi_free( &T );
-
- if( _RR == NULL )
- mpi_free( &RR );
-
- return( ret );
-}
-
-/*
- * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
- */
-int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
-{
- int ret;
- size_t lz, lzt;
- mpi TG, TA, TB;
-
- mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
-
- MPI_CHK( mpi_copy( &TA, A ) );
- MPI_CHK( mpi_copy( &TB, B ) );
-
- lz = mpi_lsb( &TA );
- lzt = mpi_lsb( &TB );
-
- if ( lzt < lz )
- lz = lzt;
-
- MPI_CHK( mpi_shift_r( &TA, lz ) );
- MPI_CHK( mpi_shift_r( &TB, lz ) );
-
- TA.s = TB.s = 1;
-
- while( mpi_cmp_int( &TA, 0 ) != 0 )
- {
- MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
- MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
-
- if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
- {
- MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
- MPI_CHK( mpi_shift_r( &TA, 1 ) );
- }
- else
- {
- MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
- MPI_CHK( mpi_shift_r( &TB, 1 ) );
- }
- }
-
- MPI_CHK( mpi_shift_l( &TB, lz ) );
- MPI_CHK( mpi_copy( G, &TB ) );
-
-cleanup:
-
- mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
-
- return( ret );
-}
-
-int mpi_fill_random( mpi *X, size_t size,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
-{
- int ret;
-
- MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
- MPI_CHK( mpi_lset( X, 0 ) );
-
- MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
-
-cleanup:
- return( ret );
-}
-
-#if defined(POLARSSL_GENPRIME)
-
-/*
- * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
- */
-int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
-{
- int ret;
- mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
-
- if( mpi_cmp_int( N, 0 ) <= 0 )
- return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
- mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
- mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
- mpi_init( &V1 ); mpi_init( &V2 );
-
- MPI_CHK( mpi_gcd( &G, A, N ) );
-
- if( mpi_cmp_int( &G, 1 ) != 0 )
- {
- ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
- goto cleanup;
- }
-
- MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
- MPI_CHK( mpi_copy( &TU, &TA ) );
- MPI_CHK( mpi_copy( &TB, N ) );
- MPI_CHK( mpi_copy( &TV, N ) );
-
- MPI_CHK( mpi_lset( &U1, 1 ) );
- MPI_CHK( mpi_lset( &U2, 0 ) );
- MPI_CHK( mpi_lset( &V1, 0 ) );
- MPI_CHK( mpi_lset( &V2, 1 ) );
-
- do
- {
- while( ( TU.p[0] & 1 ) == 0 )
- {
- MPI_CHK( mpi_shift_r( &TU, 1 ) );
-
- if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
- {
- MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
- MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
- }
-
- MPI_CHK( mpi_shift_r( &U1, 1 ) );
- MPI_CHK( mpi_shift_r( &U2, 1 ) );
- }
-
- while( ( TV.p[0] & 1 ) == 0 )
- {
- MPI_CHK( mpi_shift_r( &TV, 1 ) );
-
- if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
- {
- MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
- MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
- }
-
- MPI_CHK( mpi_shift_r( &V1, 1 ) );
- MPI_CHK( mpi_shift_r( &V2, 1 ) );
- }
-
- if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
- {
- MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
- MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
- MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
- }
- else
- {
- MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
- MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
- MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
- }
- }
- while( mpi_cmp_int( &TU, 0 ) != 0 );
-
- while( mpi_cmp_int( &V1, 0 ) < 0 )
- MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
-
- while( mpi_cmp_mpi( &V1, N ) >= 0 )
- MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
-
- MPI_CHK( mpi_copy( X, &V1 ) );
-
-cleanup:
-
- mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
- mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
- mpi_free( &V1 ); mpi_free( &V2 );
-
- return( ret );
-}
-
-static const int small_prime[] =
-{
- 3, 5, 7, 11, 13, 17, 19, 23,
- 29, 31, 37, 41, 43, 47, 53, 59,
- 61, 67, 71, 73, 79, 83, 89, 97,
- 101, 103, 107, 109, 113, 127, 131, 137,
- 139, 149, 151, 157, 163, 167, 173, 179,
- 181, 191, 193, 197, 199, 211, 223, 227,
- 229, 233, 239, 241, 251, 257, 263, 269,
- 271, 277, 281, 283, 293, 307, 311, 313,
- 317, 331, 337, 347, 349, 353, 359, 367,
- 373, 379, 383, 389, 397, 401, 409, 419,
- 421, 431, 433, 439, 443, 449, 457, 461,
- 463, 467, 479, 487, 491, 499, 503, 509,
- 521, 523, 541, 547, 557, 563, 569, 571,
- 577, 587, 593, 599, 601, 607, 613, 617,
- 619, 631, 641, 643, 647, 653, 659, 661,
- 673, 677, 683, 691, 701, 709, 719, 727,
- 733, 739, 743, 751, 757, 761, 769, 773,
- 787, 797, 809, 811, 821, 823, 827, 829,
- 839, 853, 857, 859, 863, 877, 881, 883,
- 887, 907, 911, 919, 929, 937, 941, 947,
- 953, 967, 971, 977, 983, 991, 997, -103
-};
-
-/*
- * Miller-Rabin primality test (HAC 4.24)
- */
-int mpi_is_prime( mpi *X,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
-{
- int ret, xs;
- size_t i, j, n, s;
- mpi W, R, T, A, RR;
-
- if( mpi_cmp_int( X, 0 ) == 0 ||
- mpi_cmp_int( X, 1 ) == 0 )
- return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
-
- if( mpi_cmp_int( X, 2 ) == 0 )
- return( 0 );
-
- mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
- mpi_init( &RR );
-
- xs = X->s; X->s = 1;
-
- /*
- * test trivial factors first
- */
- if( ( X->p[0] & 1 ) == 0 )
- return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
-
- for( i = 0; small_prime[i] > 0; i++ )
- {
- t_uint r;
-
- if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
- return( 0 );
-
- MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
-
- if( r == 0 )
- return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
- }
-
- /*
- * W = |X| - 1
- * R = W >> lsb( W )
- */
- MPI_CHK( mpi_sub_int( &W, X, 1 ) );
- s = mpi_lsb( &W );
- MPI_CHK( mpi_copy( &R, &W ) );
- MPI_CHK( mpi_shift_r( &R, s ) );
-
- i = mpi_msb( X );
- /*
- * HAC, table 4.4
- */
- n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
- ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
- ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
-
- for( i = 0; i < n; i++ )
- {
- /*
- * pick a random A, 1 < A < |X| - 1
- */
- MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
-
- if( mpi_cmp_mpi( &A, &W ) >= 0 )
- {
- j = mpi_msb( &A ) - mpi_msb( &W );
- MPI_CHK( mpi_shift_r( &A, j + 1 ) );
- }
- A.p[0] |= 3;
-
- /*
- * A = A^R mod |X|
- */
- MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
-
- if( mpi_cmp_mpi( &A, &W ) == 0 ||
- mpi_cmp_int( &A, 1 ) == 0 )
- continue;
-
- j = 1;
- while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
- {
- /*
- * A = A * A mod |X|
- */
- MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
- MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
-
- if( mpi_cmp_int( &A, 1 ) == 0 )
- break;
-
- j++;
- }
-
- /*
- * not prime if A != |X| - 1 or A == 1
- */
- if( mpi_cmp_mpi( &A, &W ) != 0 ||
- mpi_cmp_int( &A, 1 ) == 0 )
- {
- ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
- break;
- }
- }
-
-cleanup:
-
- X->s = xs;
-
- mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
- mpi_free( &RR );
-
- return( ret );
-}
-
-/*
- * Prime number generation
- */
-int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
-{
- int ret;
- size_t k, n;
- mpi Y;
-
- if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
- return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
- mpi_init( &Y );
-
- n = BITS_TO_LIMBS( nbits );
-
- MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
-
- k = mpi_msb( X );
- if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
- if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
-
- X->p[0] |= 3;
-
- if( dh_flag == 0 )
- {
- while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
- {
- if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
- goto cleanup;
-
- MPI_CHK( mpi_add_int( X, X, 2 ) );
- }
- }
- else
- {
- MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
- MPI_CHK( mpi_shift_r( &Y, 1 ) );
-
- while( 1 )
- {
- if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
- {
- if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
- break;
-
- if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
- goto cleanup;
- }
-
- if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
- goto cleanup;
-
- MPI_CHK( mpi_add_int( &Y, X, 1 ) );
- MPI_CHK( mpi_add_int( X, X, 2 ) );
- MPI_CHK( mpi_shift_r( &Y, 1 ) );
- }
- }
-
-cleanup:
-
- mpi_free( &Y );
-
- return( ret );
-}
-
-#endif
-
-#if defined(POLARSSL_SELF_TEST)
-
-#define GCD_PAIR_COUNT 3
-
-static const int gcd_pairs[GCD_PAIR_COUNT][3] =
-{
- { 693, 609, 21 },
- { 1764, 868, 28 },
- { 768454923, 542167814, 1 }
-};
-
-/*
- * Checkup routine
- */
-int mpi_self_test( int verbose )
-{
- int ret, i;
- mpi A, E, N, X, Y, U, V;
-
- mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
- mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
-
- MPI_CHK( mpi_read_string( &A, 16,
- "EFE021C2645FD1DC586E69184AF4A31E" \
- "D5F53E93B5F123FA41680867BA110131" \
- "944FE7952E2517337780CB0DB80E61AA" \
- "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
-
- MPI_CHK( mpi_read_string( &E, 16,
- "B2E7EFD37075B9F03FF989C7C5051C20" \
- "34D2A323810251127E7BF8625A4F49A5" \
- "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
- "5B5C25763222FEFCCFC38B832366C29E" ) );
-
- MPI_CHK( mpi_read_string( &N, 16,
- "0066A198186C18C10B2F5ED9B522752A" \
- "9830B69916E535C8F047518A889A43A5" \
- "94B6BED27A168D31D4A52F88925AA8F5" ) );
-
- MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
-
- MPI_CHK( mpi_read_string( &U, 16,
- "602AB7ECA597A3D6B56FF9829A5E8B85" \
- "9E857EA95A03512E2BAE7391688D264A" \
- "A5663B0341DB9CCFD2C4C5F421FEC814" \
- "8001B72E848A38CAE1C65F78E56ABDEF" \
- "E12D3C039B8A02D6BE593F0BBBDA56F1" \
- "ECF677152EF804370C1A305CAF3B5BF1" \
- "30879B56C61DE584A0F53A2447A51E" ) );
-
- if( verbose != 0 )
- printf( " MPI test #1 (mul_mpi): " );
-
- if( mpi_cmp_mpi( &X, &U ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-
- MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
-
- MPI_CHK( mpi_read_string( &U, 16,
- "256567336059E52CAE22925474705F39A94" ) );
-
- MPI_CHK( mpi_read_string( &V, 16,
- "6613F26162223DF488E9CD48CC132C7A" \
- "0AC93C701B001B092E4E5B9F73BCD27B" \
- "9EE50D0657C77F374E903CDFA4C642" ) );
-
- if( verbose != 0 )
- printf( " MPI test #2 (div_mpi): " );
-
- if( mpi_cmp_mpi( &X, &U ) != 0 ||
- mpi_cmp_mpi( &Y, &V ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-
- MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
-
- MPI_CHK( mpi_read_string( &U, 16,
- "36E139AEA55215609D2816998ED020BB" \
- "BD96C37890F65171D948E9BC7CBAA4D9" \
- "325D24D6A3C12710F10A09FA08AB87" ) );
-
- if( verbose != 0 )
- printf( " MPI test #3 (exp_mod): " );
-
- if( mpi_cmp_mpi( &X, &U ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-
-#if defined(POLARSSL_GENPRIME)
- MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
-
- MPI_CHK( mpi_read_string( &U, 16,
- "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
- "C3DBA76456363A10869622EAC2DD84EC" \
- "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
-
- if( verbose != 0 )
- printf( " MPI test #4 (inv_mod): " );
-
- if( mpi_cmp_mpi( &X, &U ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-#endif
-
- if( verbose != 0 )
- printf( " MPI test #5 (simple gcd): " );
-
- for ( i = 0; i < GCD_PAIR_COUNT; i++)
- {
- MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
- MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
-
- MPI_CHK( mpi_gcd( &A, &X, &Y ) );
-
- if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed at %d\n", i );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-
-cleanup:
-
- if( ret != 0 && verbose != 0 )
- printf( "Unexpected error, return code = %08X\n", ret );
-
- mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
- mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( ret );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/camellia.c b/polarssl/src/library/camellia.c
deleted file mode 100644
index 34b8f29..0000000
--- a/polarssl/src/library/camellia.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * Camellia implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The Camellia block cipher was designed by NTT and Mitsubishi Electric
- * Corporation.
- *
- * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_CAMELLIA_C)
-
-#include "polarssl/camellia.h"
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) ); \
-}
-#endif
-
-static const unsigned char SIGMA_CHARS[6][8] =
-{
- { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
- { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },
- { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },
- { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },
- { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },
- { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }
-};
-
-#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY)
-
-static const unsigned char FSb[256] =
-{
- 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
- 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
- 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
- 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77,
- 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
- 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215,
- 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
- 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80,
- 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
- 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148,
- 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226,
- 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
- 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
- 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
- 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
- 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
-};
-
-#define SBOX1(n) FSb[(n)]
-#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
-#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
-#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
-
-#else
-
-static const unsigned char FSb[256] =
-{
- 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65,
- 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189,
- 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26,
- 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77,
- 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153,
- 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215,
- 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
- 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80,
- 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210,
- 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148,
- 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226,
- 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46,
- 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89,
- 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
- 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164,
- 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158
-};
-
-static const unsigned char FSb2[256] =
-{
- 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130,
- 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123,
- 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52,
- 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154,
- 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51,
- 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175,
- 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68,
- 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160,
- 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165,
- 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41,
- 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197,
- 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92,
- 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178,
- 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245,
- 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73,
- 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61
-};
-
-static const unsigned char FSb3[256] =
-{
- 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160,
- 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222,
- 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13,
- 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166,
- 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204,
- 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235,
- 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17,
- 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40,
- 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105,
- 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74,
- 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
- 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23,
- 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172,
- 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125,
- 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82,
- 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79
-};
-
-static const unsigned char FSb4[256] =
-{
- 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146,
- 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108,
- 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4,
- 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105,
- 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221,
- 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99,
- 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141,
- 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128,
- 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189,
- 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77,
- 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215,
- 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80,
- 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148,
- 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46,
- 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250,
- 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158
-};
-
-#define SBOX1(n) FSb[(n)]
-#define SBOX2(n) FSb2[(n)]
-#define SBOX3(n) FSb3[(n)]
-#define SBOX4(n) FSb4[(n)]
-
-#endif
-
-static const unsigned char shifts[2][4][4] =
-{
- {
- { 1, 1, 1, 1 }, /* KL */
- { 0, 0, 0, 0 }, /* KR */
- { 1, 1, 1, 1 }, /* KA */
- { 0, 0, 0, 0 } /* KB */
- },
- {
- { 1, 0, 1, 1 }, /* KL */
- { 1, 1, 0, 1 }, /* KR */
- { 1, 1, 1, 0 }, /* KA */
- { 1, 1, 0, 1 } /* KB */
- }
-};
-
-static const signed char indexes[2][4][20] =
-{
- {
- { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39,
- 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
- { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
- { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17,
- 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
- { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */
- },
- {
- { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1,
- -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
- { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17,
- 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
- { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
- 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
- { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21,
- 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */
- }
-};
-
-static const signed char transposes[2][20] =
-{
- {
- 21, 22, 23, 20,
- -1, -1, -1, -1,
- 18, 19, 16, 17,
- 11, 8, 9, 10,
- 15, 12, 13, 14
- },
- {
- 25, 26, 27, 24,
- 29, 30, 31, 28,
- 18, 19, 16, 17,
- -1, -1, -1, -1,
- -1, -1, -1, -1
- }
-};
-
-/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
-#define ROTL(DEST, SRC, SHIFT) \
-{ \
- (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \
- (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \
- (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \
- (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \
-}
-
-#define FL(XL, XR, KL, KR) \
-{ \
- (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \
- (XL) = ((XR) | (KR)) ^ (XL); \
-}
-
-#define FLInv(YL, YR, KL, KR) \
-{ \
- (YL) = ((YR) | (KR)) ^ (YL); \
- (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \
-}
-
-#define SHIFT_AND_PLACE(INDEX, OFFSET) \
-{ \
- TK[0] = KC[(OFFSET) * 4 + 0]; \
- TK[1] = KC[(OFFSET) * 4 + 1]; \
- TK[2] = KC[(OFFSET) * 4 + 2]; \
- TK[3] = KC[(OFFSET) * 4 + 3]; \
- \
- for ( i = 1; i <= 4; i++ ) \
- if (shifts[(INDEX)][(OFFSET)][i -1]) \
- ROTL(TK + i * 4, TK, (15 * i) % 32); \
- \
- for ( i = 0; i < 20; i++ ) \
- if (indexes[(INDEX)][(OFFSET)][i] != -1) { \
- RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \
- } \
-}
-
-static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2])
-{
- uint32_t I0, I1;
- I0 = x[0] ^ k[0];
- I1 = x[1] ^ k[1];
-
- I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) |
- (SBOX2((I0 >> 16) & 0xFF) << 16) |
- (SBOX3((I0 >> 8) & 0xFF) << 8) |
- (SBOX4((I0 ) & 0xFF) );
- I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) |
- (SBOX3((I1 >> 16) & 0xFF) << 16) |
- (SBOX4((I1 >> 8) & 0xFF) << 8) |
- (SBOX1((I1 ) & 0xFF) );
-
- I0 ^= (I1 << 8) | (I1 >> 24);
- I1 ^= (I0 << 16) | (I0 >> 16);
- I0 ^= (I1 >> 8) | (I1 << 24);
- I1 ^= (I0 >> 8) | (I0 << 24);
-
- z[0] ^= I1;
- z[1] ^= I0;
-}
-
-/*
- * Camellia key schedule (encryption)
- */
-int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
-{
- int idx;
- size_t i;
- uint32_t *RK;
- unsigned char t[64];
- uint32_t SIGMA[6][2];
- uint32_t KC[16];
- uint32_t TK[20];
-
- RK = ctx->rk;
-
- memset(t, 0, 64);
- memset(RK, 0, sizeof(ctx->rk));
-
- switch( keysize )
- {
- case 128: ctx->nr = 3; idx = 0; break;
- case 192:
- case 256: ctx->nr = 4; idx = 1; break;
- default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
- }
-
- for( i = 0; i < keysize / 8; ++i)
- t[i] = key[i];
-
- if (keysize == 192) {
- for (i = 0; i < 8; i++)
- t[24 + i] = ~t[16 + i];
- }
-
- /*
- * Prepare SIGMA values
- */
- for (i = 0; i < 6; i++) {
- GET_ULONG_BE(SIGMA[i][0], SIGMA_CHARS[i], 0);
- GET_ULONG_BE(SIGMA[i][1], SIGMA_CHARS[i], 4);
- }
-
- /*
- * Key storage in KC
- * Order: KL, KR, KA, KB
- */
- memset(KC, 0, sizeof(KC));
-
- /* Store KL, KR */
- for (i = 0; i < 8; i++)
- GET_ULONG_BE(KC[i], t, i * 4);
-
- /* Generate KA */
- for( i = 0; i < 4; ++i)
- KC[8 + i] = KC[i] ^ KC[4 + i];
-
- camellia_feistel(KC + 8, SIGMA[0], KC + 10);
- camellia_feistel(KC + 10, SIGMA[1], KC + 8);
-
- for( i = 0; i < 4; ++i)
- KC[8 + i] ^= KC[i];
-
- camellia_feistel(KC + 8, SIGMA[2], KC + 10);
- camellia_feistel(KC + 10, SIGMA[3], KC + 8);
-
- if (keysize > 128) {
- /* Generate KB */
- for( i = 0; i < 4; ++i)
- KC[12 + i] = KC[4 + i] ^ KC[8 + i];
-
- camellia_feistel(KC + 12, SIGMA[4], KC + 14);
- camellia_feistel(KC + 14, SIGMA[5], KC + 12);
- }
-
- /*
- * Generating subkeys
- */
-
- /* Manipulating KL */
- SHIFT_AND_PLACE(idx, 0);
-
- /* Manipulating KR */
- if (keysize > 128) {
- SHIFT_AND_PLACE(idx, 1);
- }
-
- /* Manipulating KA */
- SHIFT_AND_PLACE(idx, 2);
-
- /* Manipulating KB */
- if (keysize > 128) {
- SHIFT_AND_PLACE(idx, 3);
- }
-
- /* Do transpositions */
- for ( i = 0; i < 20; i++ ) {
- if (transposes[idx][i] != -1) {
- RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
- }
- }
-
- return( 0 );
-}
-
-/*
- * Camellia key schedule (decryption)
- */
-int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
-{
- int idx;
- size_t i;
- camellia_context cty;
- uint32_t *RK;
- uint32_t *SK;
- int ret;
-
- switch( keysize )
- {
- case 128: ctx->nr = 3; idx = 0; break;
- case 192:
- case 256: ctx->nr = 4; idx = 1; break;
- default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
- }
-
- RK = ctx->rk;
-
- ret = camellia_setkey_enc(&cty, key, keysize);
- if( ret != 0 )
- return( ret );
-
- SK = cty.rk + 24 * 2 + 8 * idx * 2;
-
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
-
- for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4)
- {
- *RK++ = *SK++;
- *RK++ = *SK++;
- }
-
- SK -= 2;
-
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
-
- memset( &cty, 0, sizeof( camellia_context ) );
-
- return( 0 );
-}
-
-/*
- * Camellia-ECB block encryption/decryption
- */
-int camellia_crypt_ecb( camellia_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] )
-{
- int NR;
- uint32_t *RK, X[4];
-
- ( (void) mode );
-
- NR = ctx->nr;
- RK = ctx->rk;
-
- GET_ULONG_BE( X[0], input, 0 );
- GET_ULONG_BE( X[1], input, 4 );
- GET_ULONG_BE( X[2], input, 8 );
- GET_ULONG_BE( X[3], input, 12 );
-
- X[0] ^= *RK++;
- X[1] ^= *RK++;
- X[2] ^= *RK++;
- X[3] ^= *RK++;
-
- while (NR) {
- --NR;
- camellia_feistel(X, RK, X + 2);
- RK += 2;
- camellia_feistel(X + 2, RK, X);
- RK += 2;
- camellia_feistel(X, RK, X + 2);
- RK += 2;
- camellia_feistel(X + 2, RK, X);
- RK += 2;
- camellia_feistel(X, RK, X + 2);
- RK += 2;
- camellia_feistel(X + 2, RK, X);
- RK += 2;
-
- if (NR) {
- FL(X[0], X[1], RK[0], RK[1]);
- RK += 2;
- FLInv(X[2], X[3], RK[0], RK[1]);
- RK += 2;
- }
- }
-
- X[2] ^= *RK++;
- X[3] ^= *RK++;
- X[0] ^= *RK++;
- X[1] ^= *RK++;
-
- PUT_ULONG_BE( X[2], output, 0 );
- PUT_ULONG_BE( X[3], output, 4 );
- PUT_ULONG_BE( X[0], output, 8 );
- PUT_ULONG_BE( X[1], output, 12 );
-
- return( 0 );
-}
-
-/*
- * Camellia-CBC buffer encryption/decryption
- */
-int camellia_crypt_cbc( camellia_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int i;
- unsigned char temp[16];
-
- if( length % 16 )
- return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
-
- if( mode == CAMELLIA_DECRYPT )
- {
- while( length > 0 )
- {
- memcpy( temp, input, 16 );
- camellia_crypt_ecb( ctx, mode, input, output );
-
- for( i = 0; i < 16; i++ )
- output[i] = (unsigned char)( output[i] ^ iv[i] );
-
- memcpy( iv, temp, 16 );
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
- else
- {
- while( length > 0 )
- {
- for( i = 0; i < 16; i++ )
- output[i] = (unsigned char)( input[i] ^ iv[i] );
-
- camellia_crypt_ecb( ctx, mode, output, output );
- memcpy( iv, output, 16 );
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
-
- return( 0 );
-}
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
-/*
- * Camellia-CFB128 buffer encryption/decryption
- */
-int camellia_crypt_cfb128( camellia_context *ctx,
- int mode,
- size_t length,
- size_t *iv_off,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int c;
- size_t n = *iv_off;
-
- if( mode == CAMELLIA_DECRYPT )
- {
- while( length-- )
- {
- if( n == 0 )
- camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
-
- c = *input++;
- *output++ = (unsigned char)( c ^ iv[n] );
- iv[n] = (unsigned char) c;
-
- n = (n + 1) & 0x0F;
- }
- }
- else
- {
- while( length-- )
- {
- if( n == 0 )
- camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
-
- iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
-
- n = (n + 1) & 0x0F;
- }
- }
-
- *iv_off = n;
-
- return( 0 );
-}
-#endif /* POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-/*
- * Camellia-CTR buffer encryption/decryption
- */
-int camellia_crypt_ctr( camellia_context *ctx,
- size_t length,
- size_t *nc_off,
- unsigned char nonce_counter[16],
- unsigned char stream_block[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int c, i;
- size_t n = *nc_off;
-
- while( length-- )
- {
- if( n == 0 ) {
- camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, stream_block );
-
- for( i = 16; i > 0; i-- )
- if( ++nonce_counter[i - 1] != 0 )
- break;
- }
- c = *input++;
- *output++ = (unsigned char)( c ^ stream_block[n] );
-
- n = (n + 1) & 0x0F;
- }
-
- *nc_off = n;
-
- return( 0 );
-}
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <stdio.h>
-
-/*
- * Camellia test vectors from:
- *
- * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
- * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
- * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
- * (For each bitlength: Key 0, Nr 39)
- */
-#define CAMELLIA_TESTS_ECB 2
-
-static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
-{
- {
- { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
- },
- {
- { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
- },
- {
- { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
- },
-};
-
-static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
-{
- { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
- { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
-
-static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
-{
- {
- { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
- 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
- { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
- 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
- },
- {
- { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
- 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
- { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
- 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
- },
- {
- { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
- 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
- { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
- 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
- }
-};
-
-#define CAMELLIA_TESTS_CBC 3
-
-static const unsigned char camellia_test_cbc_key[3][32] =
-{
- { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
- 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
- ,
- { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
- 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
- 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
- ,
- { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
- 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
- 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
- 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
-};
-
-static const unsigned char camellia_test_cbc_iv[16] =
-
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
-;
-
-static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
-{
- { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
- 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
- { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
- 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
- { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
- 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
-
-};
-
-static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
-{
- {
- { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
- 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
- { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
- 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
- { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
- 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
- },
- {
- { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
- 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
- { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
- 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
- { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
- 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
- },
- {
- { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
- 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
- { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
- 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
- { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
- 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
- }
-};
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-/*
- * Camellia-CTR test vectors from:
- *
- * http://www.faqs.org/rfcs/rfc5528.html
- */
-
-static const unsigned char camellia_test_ctr_key[3][16] =
-{
- { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
- 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
- { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
- 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
- { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
- 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
-};
-
-static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
-{
- { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
- { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
- 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
- { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
- 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
-};
-
-static const unsigned char camellia_test_ctr_pt[3][48] =
-{
- { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
- 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
-
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
-
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
- 0x20, 0x21, 0x22, 0x23 }
-};
-
-static const unsigned char camellia_test_ctr_ct[3][48] =
-{
- { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
- 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
- { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
- 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
- 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
- 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
- { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
- 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
- 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
- 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
- 0xDF, 0x50, 0x86, 0x96 }
-};
-
-static const int camellia_test_ctr_len[3] =
- { 16, 32, 36 };
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-/*
- * Checkup routine
- */
-int camellia_self_test( int verbose )
-{
- int i, j, u, v;
- unsigned char key[32];
- unsigned char buf[64];
- unsigned char src[16];
- unsigned char dst[16];
- unsigned char iv[16];
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- size_t offset, len;
- unsigned char nonce_counter[16];
- unsigned char stream_block[16];
-#endif
-
- camellia_context ctx;
-
- memset( key, 0, 32 );
-
- for (j = 0; j < 6; j++) {
- u = j >> 1;
- v = j & 1;
-
- if( verbose != 0 )
- printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
- (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
-
- for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
- memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
-
- if (v == CAMELLIA_DECRYPT) {
- camellia_setkey_dec(&ctx, key, 128 + u * 64);
- memcpy(src, camellia_test_ecb_cipher[u][i], 16);
- memcpy(dst, camellia_test_ecb_plain[i], 16);
- } else { /* CAMELLIA_ENCRYPT */
- camellia_setkey_enc(&ctx, key, 128 + u * 64);
- memcpy(src, camellia_test_ecb_plain[i], 16);
- memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
- }
-
- camellia_crypt_ecb(&ctx, v, src, buf);
-
- if( memcmp( buf, dst, 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- /*
- * CBC mode
- */
- for( j = 0; j < 6; j++ )
- {
- u = j >> 1;
- v = j & 1;
-
- if( verbose != 0 )
- printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
- ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
-
- memcpy( src, camellia_test_cbc_iv, 16);
- memcpy( dst, camellia_test_cbc_iv, 16);
- memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
-
- if (v == CAMELLIA_DECRYPT) {
- camellia_setkey_dec(&ctx, key, 128 + u * 64);
- } else {
- camellia_setkey_enc(&ctx, key, 128 + u * 64);
- }
-
- for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
-
- if (v == CAMELLIA_DECRYPT) {
- memcpy( iv , src, 16 );
- memcpy(src, camellia_test_cbc_cipher[u][i], 16);
- memcpy(dst, camellia_test_cbc_plain[i], 16);
- } else { /* CAMELLIA_ENCRYPT */
- memcpy( iv , dst, 16 );
- memcpy(src, camellia_test_cbc_plain[i], 16);
- memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
- }
-
- camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
-
- if( memcmp( buf, dst, 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- /*
- * CTR mode
- */
- for( i = 0; i < 6; i++ )
- {
- u = i >> 1;
- v = i & 1;
-
- if( verbose != 0 )
- printf( " CAMELLIA-CTR-128 (%s): ",
- ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
-
- memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
- memcpy( key, camellia_test_ctr_key[u], 16 );
-
- offset = 0;
- camellia_setkey_enc( &ctx, key, 128 );
-
- if( v == CAMELLIA_DECRYPT )
- {
- len = camellia_test_ctr_len[u];
- memcpy( buf, camellia_test_ctr_ct[u], len );
-
- camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
-
- if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
- else
- {
- len = camellia_test_ctr_len[u];
- memcpy( buf, camellia_test_ctr_pt[u], len );
-
- camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
-
- if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
- return ( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/certs.c b/polarssl/src/library/certs.c
deleted file mode 100644
index e2d07f7..0000000
--- a/polarssl/src/library/certs.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * X.509 test certificates
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_CERTS_C)
-
-const char test_ca_crt[] =
-"-----BEGIN CERTIFICATE-----\r\n"
-"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
-"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
-"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n"
-"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n"
-"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n"
-"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n"
-"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n"
-"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n"
-"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n"
-"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n"
-"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n"
-"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n"
-"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n"
-"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n"
-"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n"
-"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n"
-"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n"
-"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n"
-"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n"
-"-----END CERTIFICATE-----\r\n";
-
-const char test_ca_key[] =
-"-----BEGIN RSA PRIVATE KEY-----\r\n"
-"Proc-Type: 4,ENCRYPTED\r\n"
-"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n"
-"\r\n"
-"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n"
-"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n"
-"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n"
-"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n"
-"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n"
-"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n"
-"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n"
-"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n"
-"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n"
-"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n"
-"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n"
-"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n"
-"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n"
-"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n"
-"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n"
-"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n"
-"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n"
-"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n"
-"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n"
-"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n"
-"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n"
-"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n"
-"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n"
-"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n"
-"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n"
-"-----END RSA PRIVATE KEY-----\r\n";
-
-const char test_ca_pwd[] = "PolarSSLTest";
-
-const char test_srv_crt[] =
-"-----BEGIN CERTIFICATE-----\r\n"
-"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
-"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
-"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
-"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n"
-"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n"
-"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n"
-"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n"
-"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n"
-"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n"
-"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n"
-"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n"
-"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
-"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n"
-"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n"
-"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n"
-"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n"
-"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n"
-"/WzRyYRBRjAI49mzHX6raleqnw==\r\n"
-"-----END CERTIFICATE-----\r\n";
-
-const char test_srv_key[] =
-"-----BEGIN RSA PRIVATE KEY-----\r\n"
-"MIIEogIBAAKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS0/FDUEeW\r\n"
-"Ellkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4KwVzlw7aPs\r\n"
-"FRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms+Vruf5Ke\r\n"
-"pgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6babFtpzAK6\r\n"
-"FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZnm5akmXi\r\n"
-"iD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABAoIBABaJ9eiRQq4Ypv+w\r\n"
-"UTcVpLC0oTueWzcpor1i1zjG4Vzqe/Ok2FqyGToGKMlFK7Hwwa+LEyeJ3xyV5yd4\r\n"
-"v1Mw9bDZFdJC1eCBjoUAHtX6k9HOE0Vd6woVQ4Vi6OPI1g7B5Mnr/58rNrnN6TMs\r\n"
-"x58NF6euecwTU811QJrZtLbX7j2Cr28yB2Vs8qyYlHwVw5jbDOv43D7vU5gmlIDN\r\n"
-"0JQRuWAnOuPzZNoJr4SfJKqHNGxYYY6pHZ1s0dOTLIDb/B8KQWapA2kRmZyid2EH\r\n"
-"nwzgLbAsHJCf+bQnhXjXuxtUsrcIL8noZLazlOMxwNEammglVWW23Ud/QRnFgJg5\r\n"
-"UgcAcRECgYEA19uYetht5qmwdJ+12oC6zeO+vXLcyD9gon23T5J6w2YThld7/OW0\r\n"
-"oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n"
-"GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n"
-"//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n"
-"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n"
-"LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n"
-"Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n"
-"ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n"
-"8EFrye7wmzpthrjOgZnUMQKBgE9Lhsz/5J0Nis6Y+2Pqn3CLKEukg9Ewtqdct2y0\r\n"
-"5Dcta0F3TyCRIxlCDKTL/BslqMtfAdY4H268UO0+8IAQMn9boqzBrHIgs/pvc5kx\r\n"
-"TbKHmw2wtWR6vYersBKVgVpbCGSRssDYHGFu1n74qM4HJ/RGcR1zI9QUe1gopSFD\r\n"
-"xDtLAoGAVAdWvrqDwgoL2hHW3scGpxdE/ygJDOwHnf+1B9goKAOP5lf2FJaiAxf3\r\n"
-"ectoPOgZbCmm/iiDmigu703ld3O+VoCLDD4qx3R+KyALL78gtVJYzSRiKhzgCZ3g\r\n"
-"mKsIVRBq4IfwiwyMNG2BYZQAwbSDjjPtn/kPBduPzPj7eriByhI=\r\n"
-"-----END RSA PRIVATE KEY-----\r\n";
-
-const char test_cli_crt[] =
-"-----BEGIN CERTIFICATE-----\r\n"
-"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
-"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
-"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
-"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"
-"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"
-"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"
-"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n"
-"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"
-"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"
-"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"
-"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"
-"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
-"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n"
-"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n"
-"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n"
-"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n"
-"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n"
-"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n"
-"-----END CERTIFICATE-----\r\n";
-
-const char test_cli_key[] =
-"-----BEGIN RSA PRIVATE KEY-----\r\n"
-"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"
-"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n"
-"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n"
-"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n"
-"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n"
-"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n"
-"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n"
-"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n"
-"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n"
-"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n"
-"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n"
-"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n"
-"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n"
-"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n"
-"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n"
-"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n"
-"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n"
-"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n"
-"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n"
-"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n"
-"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n"
-"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n"
-"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n"
-"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n"
-"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"
-"-----END RSA PRIVATE KEY-----\r\n";
-
-const char test_dhm_params[] =
-"-----BEGIN DH PARAMETERS-----\r\n"
-"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
-"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
-"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
-"-----END DH PARAMETERS-----\r\n";
-
-#endif
diff --git a/polarssl/src/library/cipher.c b/polarssl/src/library/cipher.c
deleted file mode 100644
index 0d1258b..0000000
--- a/polarssl/src/library/cipher.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/**
- * \file cipher.c
- *
- * \brief Generic cipher wrapper for PolarSSL
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_CIPHER_C)
-
-#include "polarssl/cipher.h"
-#include "polarssl/cipher_wrap.h"
-
-#include <stdlib.h>
-
-#if defined _MSC_VER && !defined strcasecmp
-#define strcasecmp _stricmp
-#endif
-
-static const int supported_ciphers[] = {
-
-#if defined(POLARSSL_AES_C)
- POLARSSL_CIPHER_AES_128_CBC,
- POLARSSL_CIPHER_AES_192_CBC,
- POLARSSL_CIPHER_AES_256_CBC,
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- POLARSSL_CIPHER_AES_128_CFB128,
- POLARSSL_CIPHER_AES_192_CFB128,
- POLARSSL_CIPHER_AES_256_CFB128,
-#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- POLARSSL_CIPHER_AES_128_CTR,
- POLARSSL_CIPHER_AES_192_CTR,
- POLARSSL_CIPHER_AES_256_CTR,
-#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
-
-#endif /* defined(POLARSSL_AES_C) */
-
-#if defined(POLARSSL_CAMELLIA_C)
- POLARSSL_CIPHER_CAMELLIA_128_CBC,
- POLARSSL_CIPHER_CAMELLIA_192_CBC,
- POLARSSL_CIPHER_CAMELLIA_256_CBC,
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- POLARSSL_CIPHER_CAMELLIA_128_CFB128,
- POLARSSL_CIPHER_CAMELLIA_192_CFB128,
- POLARSSL_CIPHER_CAMELLIA_256_CFB128,
-#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- POLARSSL_CIPHER_CAMELLIA_128_CTR,
- POLARSSL_CIPHER_CAMELLIA_192_CTR,
- POLARSSL_CIPHER_CAMELLIA_256_CTR,
-#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
-
-#endif /* defined(POLARSSL_CAMELLIA_C) */
-
-#if defined(POLARSSL_DES_C)
- POLARSSL_CIPHER_DES_CBC,
- POLARSSL_CIPHER_DES_EDE_CBC,
- POLARSSL_CIPHER_DES_EDE3_CBC,
-#endif /* defined(POLARSSL_DES_C) */
-
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- POLARSSL_CIPHER_NULL,
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
- 0
-};
-
-const int *cipher_list( void )
-{
- return supported_ciphers;
-}
-
-const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
-{
- /* Find static cipher information */
- switch ( cipher_type )
- {
-#if defined(POLARSSL_AES_C)
- case POLARSSL_CIPHER_AES_128_CBC:
- return &aes_128_cbc_info;
- case POLARSSL_CIPHER_AES_192_CBC:
- return &aes_192_cbc_info;
- case POLARSSL_CIPHER_AES_256_CBC:
- return &aes_256_cbc_info;
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- case POLARSSL_CIPHER_AES_128_CFB128:
- return &aes_128_cfb128_info;
- case POLARSSL_CIPHER_AES_192_CFB128:
- return &aes_192_cfb128_info;
- case POLARSSL_CIPHER_AES_256_CFB128:
- return &aes_256_cfb128_info;
-#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- case POLARSSL_CIPHER_AES_128_CTR:
- return &aes_128_ctr_info;
- case POLARSSL_CIPHER_AES_192_CTR:
- return &aes_192_ctr_info;
- case POLARSSL_CIPHER_AES_256_CTR:
- return &aes_256_ctr_info;
-#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
-
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
- case POLARSSL_CIPHER_CAMELLIA_128_CBC:
- return &camellia_128_cbc_info;
- case POLARSSL_CIPHER_CAMELLIA_192_CBC:
- return &camellia_192_cbc_info;
- case POLARSSL_CIPHER_CAMELLIA_256_CBC:
- return &camellia_256_cbc_info;
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- case POLARSSL_CIPHER_CAMELLIA_128_CFB128:
- return &camellia_128_cfb128_info;
- case POLARSSL_CIPHER_CAMELLIA_192_CFB128:
- return &camellia_192_cfb128_info;
- case POLARSSL_CIPHER_CAMELLIA_256_CFB128:
- return &camellia_256_cfb128_info;
-#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- case POLARSSL_CIPHER_CAMELLIA_128_CTR:
- return &camellia_128_ctr_info;
- case POLARSSL_CIPHER_CAMELLIA_192_CTR:
- return &camellia_192_ctr_info;
- case POLARSSL_CIPHER_CAMELLIA_256_CTR:
- return &camellia_256_ctr_info;
-#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
-
-#endif
-
-#if defined(POLARSSL_DES_C)
- case POLARSSL_CIPHER_DES_CBC:
- return &des_cbc_info;
- case POLARSSL_CIPHER_DES_EDE_CBC:
- return &des_ede_cbc_info;
- case POLARSSL_CIPHER_DES_EDE3_CBC:
- return &des_ede3_cbc_info;
-#endif
-
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- case POLARSSL_CIPHER_NULL:
- return &null_cipher_info;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
- default:
- return NULL;
- }
-}
-
-const cipher_info_t *cipher_info_from_string( const char *cipher_name )
-{
- if( NULL == cipher_name )
- return NULL;
-
- /* Get the appropriate cipher information */
-#if defined(POLARSSL_CAMELLIA_C)
- if( !strcasecmp( "CAMELLIA-128-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CBC );
- if( !strcasecmp( "CAMELLIA-192-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CBC );
- if( !strcasecmp( "CAMELLIA-256-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CBC );
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- if( !strcasecmp( "CAMELLIA-128-CFB128", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CFB128 );
- if( !strcasecmp( "CAMELLIA-192-CFB128", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CFB128 );
- if( !strcasecmp( "CAMELLIA-256-CFB128", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CFB128 );
-#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- if( !strcasecmp( "CAMELLIA-128-CTR", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CTR );
- if( !strcasecmp( "CAMELLIA-192-CTR", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CTR );
- if( !strcasecmp( "CAMELLIA-256-CTR", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CTR );
-#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
-#endif
-
-#if defined(POLARSSL_AES_C)
- if( !strcasecmp( "AES-128-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC );
- if( !strcasecmp( "AES-192-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CBC );
- if( !strcasecmp( "AES-256-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CBC );
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- if( !strcasecmp( "AES-128-CFB128", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CFB128 );
- if( !strcasecmp( "AES-192-CFB128", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CFB128 );
- if( !strcasecmp( "AES-256-CFB128", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CFB128 );
-#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- if( !strcasecmp( "AES-128-CTR", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CTR );
- if( !strcasecmp( "AES-192-CTR", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CTR );
- if( !strcasecmp( "AES-256-CTR", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR );
-#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
-#endif
-
-#if defined(POLARSSL_DES_C)
- if( !strcasecmp( "DES-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_DES_CBC );
- if( !strcasecmp( "DES-EDE-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE_CBC );
- if( !strcasecmp( "DES-EDE3-CBC", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC );
-#endif
-
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- if( !strcasecmp( "NULL", cipher_name ) )
- return cipher_info_from_type( POLARSSL_CIPHER_NULL );
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
- return NULL;
-}
-
-int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
-{
- if( NULL == cipher_info || NULL == ctx )
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
-
- memset( ctx, 0, sizeof( cipher_context_t ) );
-
- if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
- return POLARSSL_ERR_CIPHER_ALLOC_FAILED;
-
- ctx->cipher_info = cipher_info;
-
- return 0;
-}
-
-int cipher_free_ctx( cipher_context_t *ctx )
-{
- if( ctx == NULL || ctx->cipher_info == NULL )
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
-
- ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
-
- return 0;
-}
-
-int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
- int key_length, const operation_t operation )
-{
- if( NULL == ctx || NULL == ctx->cipher_info )
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
-
- ctx->key_length = key_length;
- ctx->operation = operation;
-
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
- return 0;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
- /*
- * For CFB128 and CTR mode always use the encryption key schedule
- */
- if( POLARSSL_ENCRYPT == operation ||
- POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||
- POLARSSL_MODE_CTR == ctx->cipher_info->mode )
- {
- return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
- ctx->key_length );
- }
-
- if( POLARSSL_DECRYPT == operation )
- return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
- ctx->key_length );
-
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
-}
-
-int cipher_reset( cipher_context_t *ctx, const unsigned char *iv )
-{
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
-
- ctx->unprocessed_len = 0;
-
- memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
-
- return 0;
-}
-
-int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
- unsigned char *output, size_t *olen )
-{
- int ret;
- size_t copy_len = 0;
-
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ||
- input == output )
- {
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
- }
-
- *olen = 0;
-
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
- {
- memcpy( output, input, ilen );
- *olen = ilen;
- return 0;
- }
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
- if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
- {
- /*
- * If there is not enough data for a full block, cache it.
- */
- if( ( ctx->operation == POLARSSL_DECRYPT &&
- ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) ||
- ( ctx->operation == POLARSSL_ENCRYPT &&
- ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) )
- {
- memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
- ilen );
-
- ctx->unprocessed_len += ilen;
- return 0;
- }
-
- /*
- * Process cached data first
- */
- if( ctx->unprocessed_len != 0 )
- {
- copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len;
-
- memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
- copy_len );
-
- if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
- ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
- ctx->unprocessed_data, output ) ) )
- {
- return ret;
- }
-
- *olen += cipher_get_block_size( ctx );
- output += cipher_get_block_size( ctx );
- ctx->unprocessed_len = 0;
-
- input += copy_len;
- ilen -= copy_len;
- }
-
- /*
- * Cache final, incomplete block
- */
- if( 0 != ilen )
- {
- copy_len = ilen % cipher_get_block_size( ctx );
- if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )
- copy_len = cipher_get_block_size(ctx);
-
- memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
- copy_len );
-
- ctx->unprocessed_len += copy_len;
- ilen -= copy_len;
- }
-
- /*
- * Process remaining full blocks
- */
- if( ilen )
- {
- if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
- ctx->operation, ilen, ctx->iv, input, output ) ) )
- {
- return ret;
- }
- *olen += ilen;
- }
-
- return 0;
- }
-
- if( ctx->cipher_info->mode == POLARSSL_MODE_CFB128 )
- {
- if( 0 != ( ret = ctx->cipher_info->base->cfb128_func( ctx->cipher_ctx,
- ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
- input, output ) ) )
- {
- return ret;
- }
-
- *olen = ilen;
-
- return 0;
- }
-
- if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
- {
- if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
- ilen, &ctx->unprocessed_len, ctx->iv,
- ctx->unprocessed_data, input, output ) ) )
- {
- return ret;
- }
-
- *olen = ilen;
-
- return 0;
- }
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-}
-
-static void add_pkcs_padding( unsigned char *output, size_t output_len,
- size_t data_len )
-{
- size_t padding_len = output_len - data_len;
- unsigned char i = 0;
-
- for( i = 0; i < padding_len; i++ )
- output[data_len + i] = (unsigned char) padding_len;
-}
-
-static int get_pkcs_padding( unsigned char *input, unsigned int input_len,
- size_t *data_len)
-{
- unsigned int i, padding_len = 0;
-
- if( NULL == input || NULL == data_len )
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
-
- padding_len = input[input_len - 1];
-
- if( padding_len > input_len )
- return POLARSSL_ERR_CIPHER_INVALID_PADDING;
-
- for( i = input_len - padding_len; i < input_len; i++ )
- if( input[i] != padding_len )
- return POLARSSL_ERR_CIPHER_INVALID_PADDING;
-
- *data_len = input_len - padding_len;
-
- return 0;
-}
-
-int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen)
-{
- int ret = 0;
-
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
- return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
-
- *olen = 0;
-
- if( POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||
- POLARSSL_MODE_CTR == ctx->cipher_info->mode ||
- POLARSSL_MODE_NULL == ctx->cipher_info->mode )
- {
- return 0;
- }
-
- if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
- {
- if( POLARSSL_ENCRYPT == ctx->operation )
- {
- add_pkcs_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),
- ctx->unprocessed_len );
- }
- else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
- {
- /* For decrypt operations, expect a full block */
- return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
- }
-
- /* cipher block */
- if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
- ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
- ctx->unprocessed_data, output ) ) )
- {
- return ret;
- }
-
- /* Set output size for decryption */
- if( POLARSSL_DECRYPT == ctx->operation )
- return get_pkcs_padding( output, cipher_get_block_size( ctx ), olen );
-
- /* Set output size for encryption */
- *olen = cipher_get_block_size( ctx );
- return 0;
- }
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <stdio.h>
-
-#define ASSERT(x) if (!(x)) { \
- printf( "failed with %i at %s\n", value, (#x) ); \
- return( 1 ); \
-}
-/*
- * Checkup routine
- */
-
-int cipher_self_test( int verbose )
-{
- ((void) verbose);
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/cipher_wrap.c b/polarssl/src/library/cipher_wrap.c
deleted file mode 100644
index 99e5092..0000000
--- a/polarssl/src/library/cipher_wrap.c
+++ /dev/null
@@ -1,595 +0,0 @@
-/**
- * \file md_wrap.c
- *
- * \brief Generic cipher wrapper for PolarSSL
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_CIPHER_C)
-
-#include "polarssl/cipher_wrap.h"
-
-#if defined(POLARSSL_AES_C)
-#include "polarssl/aes.h"
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-#include "polarssl/camellia.h"
-#endif
-
-#if defined(POLARSSL_DES_C)
-#include "polarssl/des.h"
-#endif
-
-#include <stdlib.h>
-
-#if defined(POLARSSL_AES_C)
-
-int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
- unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
- return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, output );
-}
-
-int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
- size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, input, output );
-#else
- ((void) ctx);
- ((void) operation);
- ((void) length);
- ((void) iv_off);
- ((void) iv);
- ((void) input);
- ((void) output);
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
-}
-
-int aes_crypt_ctr_wrap( void *ctx, size_t length,
- size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
- const unsigned char *input, unsigned char *output )
-{
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter,
- stream_block, input, output );
-#else
- ((void) ctx);
- ((void) length);
- ((void) nc_off);
- ((void) nonce_counter);
- ((void) stream_block);
- ((void) input);
- ((void) output);
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
-}
-
-int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- return aes_setkey_dec( (aes_context *) ctx, key, key_length );
-}
-
-int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- return aes_setkey_enc( (aes_context *) ctx, key, key_length );
-}
-
-static void * aes_ctx_alloc( void )
-{
- return malloc( sizeof( aes_context ) );
-}
-
-static void aes_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const cipher_base_t aes_info = {
- POLARSSL_CIPHER_ID_AES,
- aes_crypt_cbc_wrap,
- aes_crypt_cfb128_wrap,
- aes_crypt_ctr_wrap,
- aes_setkey_enc_wrap,
- aes_setkey_dec_wrap,
- aes_ctx_alloc,
- aes_ctx_free
-};
-
-const cipher_info_t aes_128_cbc_info = {
- POLARSSL_CIPHER_AES_128_CBC,
- POLARSSL_MODE_CBC,
- 128,
- "AES-128-CBC",
- 16,
- 16,
- &aes_info
-};
-
-const cipher_info_t aes_192_cbc_info = {
- POLARSSL_CIPHER_AES_192_CBC,
- POLARSSL_MODE_CBC,
- 192,
- "AES-192-CBC",
- 16,
- 16,
- &aes_info
-};
-
-const cipher_info_t aes_256_cbc_info = {
- POLARSSL_CIPHER_AES_256_CBC,
- POLARSSL_MODE_CBC,
- 256,
- "AES-256-CBC",
- 16,
- 16,
- &aes_info
-};
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
-const cipher_info_t aes_128_cfb128_info = {
- POLARSSL_CIPHER_AES_128_CFB128,
- POLARSSL_MODE_CFB128,
- 128,
- "AES-128-CFB128",
- 16,
- 16,
- &aes_info
-};
-
-const cipher_info_t aes_192_cfb128_info = {
- POLARSSL_CIPHER_AES_192_CFB128,
- POLARSSL_MODE_CFB128,
- 192,
- "AES-192-CFB128",
- 16,
- 16,
- &aes_info
-};
-
-const cipher_info_t aes_256_cfb128_info = {
- POLARSSL_CIPHER_AES_256_CFB128,
- POLARSSL_MODE_CFB128,
- 256,
- "AES-256-CFB128",
- 16,
- 16,
- &aes_info
-};
-#endif /* POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-const cipher_info_t aes_128_ctr_info = {
- POLARSSL_CIPHER_AES_128_CTR,
- POLARSSL_MODE_CTR,
- 128,
- "AES-128-CTR",
- 16,
- 16,
- &aes_info
-};
-
-const cipher_info_t aes_192_ctr_info = {
- POLARSSL_CIPHER_AES_192_CTR,
- POLARSSL_MODE_CTR,
- 192,
- "AES-192-CTR",
- 16,
- 16,
- &aes_info
-};
-
-const cipher_info_t aes_256_ctr_info = {
- POLARSSL_CIPHER_AES_256_CTR,
- POLARSSL_MODE_CTR,
- 256,
- "AES-256-CTR",
- 16,
- 16,
- &aes_info
-};
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-
-int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
- unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
- return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, input, output );
-}
-
-int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
- size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
-#if defined(POLARSSL_CIPHER_MODE_CFB)
- return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, iv_off, iv, input, output );
-#else
- ((void) ctx);
- ((void) operation);
- ((void) length);
- ((void) iv_off);
- ((void) iv);
- ((void) input);
- ((void) output);
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
-}
-
-int camellia_crypt_ctr_wrap( void *ctx, size_t length,
- size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
- const unsigned char *input, unsigned char *output )
-{
-#if defined(POLARSSL_CIPHER_MODE_CTR)
- return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, nonce_counter,
- stream_block, input, output );
-#else
- ((void) ctx);
- ((void) length);
- ((void) nc_off);
- ((void) nonce_counter);
- ((void) stream_block);
- ((void) input);
- ((void) output);
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
-}
-
-int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- return camellia_setkey_dec( (camellia_context *) ctx, key, key_length );
-}
-
-int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- return camellia_setkey_enc( (camellia_context *) ctx, key, key_length );
-}
-
-static void * camellia_ctx_alloc( void )
-{
- return malloc( sizeof( camellia_context ) );
-}
-
-static void camellia_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const cipher_base_t camellia_info = {
- POLARSSL_CIPHER_ID_CAMELLIA,
- camellia_crypt_cbc_wrap,
- camellia_crypt_cfb128_wrap,
- camellia_crypt_ctr_wrap,
- camellia_setkey_enc_wrap,
- camellia_setkey_dec_wrap,
- camellia_ctx_alloc,
- camellia_ctx_free
-};
-
-const cipher_info_t camellia_128_cbc_info = {
- POLARSSL_CIPHER_CAMELLIA_128_CBC,
- POLARSSL_MODE_CBC,
- 128,
- "CAMELLIA-128-CBC",
- 16,
- 16,
- &camellia_info
-};
-
-const cipher_info_t camellia_192_cbc_info = {
- POLARSSL_CIPHER_CAMELLIA_192_CBC,
- POLARSSL_MODE_CBC,
- 192,
- "CAMELLIA-192-CBC",
- 16,
- 16,
- &camellia_info
-};
-
-const cipher_info_t camellia_256_cbc_info = {
- POLARSSL_CIPHER_CAMELLIA_256_CBC,
- POLARSSL_MODE_CBC,
- 256,
- "CAMELLIA-256-CBC",
- 16,
- 16,
- &camellia_info
-};
-
-#if defined(POLARSSL_CIPHER_MODE_CFB)
-const cipher_info_t camellia_128_cfb128_info = {
- POLARSSL_CIPHER_CAMELLIA_128_CFB128,
- POLARSSL_MODE_CFB128,
- 128,
- "CAMELLIA-128-CFB128",
- 16,
- 16,
- &camellia_info
-};
-
-const cipher_info_t camellia_192_cfb128_info = {
- POLARSSL_CIPHER_CAMELLIA_192_CFB128,
- POLARSSL_MODE_CFB128,
- 192,
- "CAMELLIA-192-CFB128",
- 16,
- 16,
- &camellia_info
-};
-
-const cipher_info_t camellia_256_cfb128_info = {
- POLARSSL_CIPHER_CAMELLIA_256_CFB128,
- POLARSSL_MODE_CFB128,
- 256,
- "CAMELLIA-256-CFB128",
- 16,
- 16,
- &camellia_info
-};
-#endif /* POLARSSL_CIPHER_MODE_CFB */
-
-#if defined(POLARSSL_CIPHER_MODE_CTR)
-const cipher_info_t camellia_128_ctr_info = {
- POLARSSL_CIPHER_CAMELLIA_128_CTR,
- POLARSSL_MODE_CTR,
- 128,
- "CAMELLIA-128-CTR",
- 16,
- 16,
- &camellia_info
-};
-
-const cipher_info_t camellia_192_ctr_info = {
- POLARSSL_CIPHER_CAMELLIA_192_CTR,
- POLARSSL_MODE_CTR,
- 192,
- "CAMELLIA-192-CTR",
- 16,
- 16,
- &camellia_info
-};
-
-const cipher_info_t camellia_256_ctr_info = {
- POLARSSL_CIPHER_CAMELLIA_256_CTR,
- POLARSSL_MODE_CTR,
- 256,
- "CAMELLIA-256-CTR",
- 16,
- 16,
- &camellia_info
-};
-#endif /* POLARSSL_CIPHER_MODE_CTR */
-
-#endif
-
-#if defined(POLARSSL_DES_C)
-
-int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
- unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
- return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, output );
-}
-
-int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
- unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
- return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, output );
-}
-
-int des_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
- size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
- ((void) ctx);
- ((void) operation);
- ((void) length);
- ((void) iv_off);
- ((void) iv);
- ((void) input);
- ((void) output);
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-}
-
-int des_crypt_ctr_wrap( void *ctx, size_t length,
- size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
- const unsigned char *input, unsigned char *output )
-{
- ((void) ctx);
- ((void) length);
- ((void) nc_off);
- ((void) nonce_counter);
- ((void) stream_block);
- ((void) input);
- ((void) output);
-
- return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-}
-
-
-int des_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- ((void) key_length);
-
- return des_setkey_dec( (des_context *) ctx, key );
-}
-
-int des_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- ((void) key_length);
-
- return des_setkey_enc( (des_context *) ctx, key );
-}
-
-int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- ((void) key_length);
-
- return des3_set2key_dec( (des3_context *) ctx, key );
-}
-
-int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- ((void) key_length);
-
- return des3_set2key_enc( (des3_context *) ctx, key );
-}
-
-int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- ((void) key_length);
-
- return des3_set3key_dec( (des3_context *) ctx, key );
-}
-
-int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
- ((void) key_length);
-
- return des3_set3key_enc( (des3_context *) ctx, key );
-}
-
-static void * des_ctx_alloc( void )
-{
- return malloc( sizeof( des_context ) );
-}
-
-static void * des3_ctx_alloc( void )
-{
- return malloc( sizeof( des3_context ) );
-}
-
-static void des_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const cipher_base_t des_info = {
- POLARSSL_CIPHER_ID_DES,
- des_crypt_cbc_wrap,
- des_crypt_cfb128_wrap,
- des_crypt_ctr_wrap,
- des_setkey_enc_wrap,
- des_setkey_dec_wrap,
- des_ctx_alloc,
- des_ctx_free
-};
-
-const cipher_info_t des_cbc_info = {
- POLARSSL_CIPHER_DES_CBC,
- POLARSSL_MODE_CBC,
- POLARSSL_KEY_LENGTH_DES,
- "DES-CBC",
- 8,
- 8,
- &des_info
-};
-
-const cipher_base_t des_ede_info = {
- POLARSSL_CIPHER_ID_DES,
- des3_crypt_cbc_wrap,
- des_crypt_cfb128_wrap,
- des_crypt_ctr_wrap,
- des3_set2key_enc_wrap,
- des3_set2key_dec_wrap,
- des3_ctx_alloc,
- des_ctx_free
-};
-
-const cipher_info_t des_ede_cbc_info = {
- POLARSSL_CIPHER_DES_EDE_CBC,
- POLARSSL_MODE_CBC,
- POLARSSL_KEY_LENGTH_DES_EDE,
- "DES-EDE-CBC",
- 16,
- 16,
- &des_ede_info
-};
-
-const cipher_base_t des_ede3_info = {
- POLARSSL_CIPHER_ID_DES,
- des3_crypt_cbc_wrap,
- des_crypt_cfb128_wrap,
- des_crypt_ctr_wrap,
- des3_set3key_enc_wrap,
- des3_set3key_dec_wrap,
- des3_ctx_alloc,
- des_ctx_free
-};
-
-const cipher_info_t des_ede3_cbc_info = {
- POLARSSL_CIPHER_DES_EDE3_CBC,
- POLARSSL_MODE_CBC,
- POLARSSL_KEY_LENGTH_DES_EDE3,
- "DES-EDE3-CBC",
- 8,
- 8,
- &des_ede3_info
-};
-#endif
-
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-static void * null_ctx_alloc( void )
-{
- return (void *) 1;
-}
-
-
-static void null_ctx_free( void *ctx )
-{
- ((void) ctx);
-}
-
-const cipher_base_t null_base_info = {
- POLARSSL_CIPHER_ID_NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- null_ctx_alloc,
- null_ctx_free
-};
-
-const cipher_info_t null_cipher_info = {
- POLARSSL_CIPHER_NULL,
- POLARSSL_MODE_NULL,
- 0,
- "NULL",
- 1,
- 1,
- &null_base_info
-};
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#endif
diff --git a/polarssl/src/library/ctr_drbg.c b/polarssl/src/library/ctr_drbg.c
deleted file mode 100644
index 1de7f05..0000000
--- a/polarssl/src/library/ctr_drbg.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The NIST SP 800-90 DRBGs are described in the following publucation.
- *
- * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_CTR_DRBG_C)
-
-#include "polarssl/ctr_drbg.h"
-
-#if defined(POLARSSL_FS_IO)
-#include <stdio.h>
-#endif
-
-/*
- * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
- * tests to succeed (which require known length fixed entropy)
- */
-int ctr_drbg_init_entropy_len(
- ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t),
- void *p_entropy,
- const unsigned char *custom,
- size_t len,
- size_t entropy_len )
-{
- int ret;
- unsigned char key[CTR_DRBG_KEYSIZE];
-
- memset( ctx, 0, sizeof(ctr_drbg_context) );
- memset( key, 0, CTR_DRBG_KEYSIZE );
-
- ctx->f_entropy = f_entropy;
- ctx->p_entropy = p_entropy;
-
- ctx->entropy_len = entropy_len;
- ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
-
- /*
- * Initialize with an empty key
- */
- aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
-
- if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
- return( ret );
-
- return( 0 );
-}
-
-int ctr_drbg_init( ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t),
- void *p_entropy,
- const unsigned char *custom,
- size_t len )
-{
- return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
- CTR_DRBG_ENTROPY_LEN ) );
-}
-
-void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
-{
- ctx->prediction_resistance = resistance;
-}
-
-void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
-{
- ctx->entropy_len = len;
-}
-
-void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
-{
- ctx->reseed_interval = interval;
-}
-
-int block_cipher_df( unsigned char *output,
- const unsigned char *data, size_t data_len )
-{
- unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
- unsigned char tmp[CTR_DRBG_SEEDLEN];
- unsigned char key[CTR_DRBG_KEYSIZE];
- unsigned char chain[CTR_DRBG_BLOCKSIZE];
- unsigned char *p = buf, *iv;
- aes_context aes_ctx;
-
- int i, j, buf_len, use_len;
-
- memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
-
- /*
- * Construct IV (16 bytes) and S in buffer
- * IV = Counter (in 32-bits) padded to 16 with zeroes
- * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
- * data || 0x80
- * (Total is padded to a multiple of 16-bytes with zeroes)
- */
- p = buf + CTR_DRBG_BLOCKSIZE;
- *p++ = ( data_len >> 24 ) & 0xff;
- *p++ = ( data_len >> 16 ) & 0xff;
- *p++ = ( data_len >> 8 ) & 0xff;
- *p++ = ( data_len ) & 0xff;
- p += 3;
- *p++ = CTR_DRBG_SEEDLEN;
- memcpy( p, data, data_len );
- p[data_len] = 0x80;
-
- buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
-
- for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
- key[i] = i;
-
- aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
-
- /*
- * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
- */
- for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
- {
- p = buf;
- memset( chain, 0, CTR_DRBG_BLOCKSIZE );
- use_len = buf_len;
-
- while( use_len > 0 )
- {
- for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
- chain[i] ^= p[i];
- p += CTR_DRBG_BLOCKSIZE;
- use_len -= CTR_DRBG_BLOCKSIZE;
-
- aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
- }
-
- memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
-
- /*
- * Update IV
- */
- buf[3]++;
- }
-
- /*
- * Do final encryption with reduced data
- */
- aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
- iv = tmp + CTR_DRBG_KEYSIZE;
- p = output;
-
- for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
- {
- aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
- memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
- p += CTR_DRBG_BLOCKSIZE;
- }
-
- return( 0 );
-}
-
-int ctr_drbg_update_internal( ctr_drbg_context *ctx,
- const unsigned char data[CTR_DRBG_SEEDLEN] )
-{
- unsigned char tmp[CTR_DRBG_SEEDLEN];
- unsigned char *p = tmp;
- int i, j;
-
- memset( tmp, 0, CTR_DRBG_SEEDLEN );
-
- for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
- {
- /*
- * Increase counter
- */
- for( i = CTR_DRBG_BLOCKSIZE; i >= 0; i-- )
- if( ++ctx->counter[i - 1] != 0 )
- break;
-
- /*
- * Crypt counter block
- */
- aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
-
- p += CTR_DRBG_BLOCKSIZE;
- }
-
- for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
- tmp[i] ^= data[i];
-
- /*
- * Update key and counter
- */
- aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
- memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
-
- return( 0 );
-}
-
-void ctr_drbg_update( ctr_drbg_context *ctx,
- const unsigned char *additional, size_t add_len )
-{
- unsigned char add_input[CTR_DRBG_SEEDLEN];
-
- if( add_len > 0 )
- {
- block_cipher_df( add_input, additional, add_len );
- ctr_drbg_update_internal( ctx, add_input );
- }
-}
-
-int ctr_drbg_reseed( ctr_drbg_context *ctx,
- const unsigned char *additional, size_t len )
-{
- unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
- size_t seedlen = 0;
-
- if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
- return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
-
- memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
-
- /*
- * Gather enropy_len bytes of entropy to seed state
- */
- if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
- ctx->entropy_len ) )
- {
- return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
- }
-
- seedlen += ctx->entropy_len;
-
- /*
- * Add additional data
- */
- if( additional && len )
- {
- memcpy( seed + seedlen, additional, len );
- seedlen += len;
- }
-
- /*
- * Reduce to 384 bits
- */
- block_cipher_df( seed, seed, seedlen );
-
- /*
- * Update state
- */
- ctr_drbg_update_internal( ctx, seed );
- ctx->reseed_counter = 1;
-
- return( 0 );
-}
-
-int ctr_drbg_random_with_add( void *p_rng,
- unsigned char *output, size_t output_len,
- const unsigned char *additional, size_t add_len )
-{
- int ret = 0;
- ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
- unsigned char add_input[CTR_DRBG_SEEDLEN];
- unsigned char *p = output;
- unsigned char tmp[CTR_DRBG_BLOCKSIZE];
- int i;
- size_t use_len;
-
- if( output_len > CTR_DRBG_MAX_REQUEST )
- return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
-
- if( add_len > CTR_DRBG_MAX_INPUT )
- return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
-
- memset( add_input, 0, CTR_DRBG_SEEDLEN );
-
- if( ctx->reseed_counter > ctx->reseed_interval ||
- ctx->prediction_resistance )
- {
- if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
- return( ret );
-
- add_len = 0;
- }
-
- if( add_len > 0 )
- {
- block_cipher_df( add_input, additional, add_len );
- ctr_drbg_update_internal( ctx, add_input );
- }
-
- while( output_len > 0 )
- {
- /*
- * Increase counter
- */
- for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
- if( ++ctx->counter[i - 1] != 0 )
- break;
-
- /*
- * Crypt counter block
- */
- aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
-
- use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
- /*
- * Copy random block to destination
- */
- memcpy( p, tmp, use_len );
- p += use_len;
- output_len -= use_len;
- }
-
- ctr_drbg_update_internal( ctx, add_input );
-
- ctx->reseed_counter++;
-
- return( 0 );
-}
-
-int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
-{
- return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
-}
-
-#if defined(POLARSSL_FS_IO)
-int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
-{
- int ret;
- FILE *f;
- unsigned char buf[ CTR_DRBG_MAX_INPUT ];
-
- if( ( f = fopen( path, "wb" ) ) == NULL )
- return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
-
- if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
- return( ret );
-
- if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
- {
- fclose( f );
- return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
- }
-
- fclose( f );
- return( 0 );
-}
-
-int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
-{
- FILE *f;
- size_t n;
- unsigned char buf[ CTR_DRBG_MAX_INPUT ];
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
-
- fseek( f, 0, SEEK_END );
- n = (size_t) ftell( f );
- fseek( f, 0, SEEK_SET );
-
- if( n > CTR_DRBG_MAX_INPUT )
- return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
-
- if( fread( buf, 1, n, f ) != n )
- {
- fclose( f );
- return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
- }
-
- ctr_drbg_update( ctx, buf, n );
-
- fclose( f );
-
- return( ctr_drbg_write_seed_file( ctx, path ) );
-}
-#endif /* POLARSSL_FS_IO */
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <stdio.h>
-
-unsigned char entropy_source_pr[96] =
- { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
- 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
- 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
- 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
- 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
- 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
- 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
- 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
- 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
- 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
- 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
- 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
-
-unsigned char entropy_source_nopr[64] =
- { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
- 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
- 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
- 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
- 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
- 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
- 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
- 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
-
-unsigned char nonce_pers_pr[16] =
- { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
- 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
-
-unsigned char nonce_pers_nopr[16] =
- { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
- 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
-
-unsigned char result_pr[16] =
- { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
- 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
-
-unsigned char result_nopr[16] =
- { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
- 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
-
-int test_offset;
-int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
-{
- unsigned char *p = data;
- memcpy( buf, p + test_offset, len );
- test_offset += 32;
- return( 0 );
-}
-
-/*
- * Checkup routine
- */
-int ctr_drbg_self_test( int verbose )
-{
- ctr_drbg_context ctx;
- unsigned char buf[16];
-
- /*
- * Based on a NIST CTR_DRBG test vector (PR = True)
- */
- if( verbose != 0 )
- printf( " CTR_DRBG (PR = TRUE) : " );
-
- test_offset = 0;
- if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
- ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
-
- if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-
- /*
- * Based on a NIST CTR_DRBG test vector (PR = FALSE)
- */
- if( verbose != 0 )
- printf( " CTR_DRBG (PR = FALSE): " );
-
- test_offset = 0;
- if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( memcmp( buf, result_nopr, 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-#endif
-
-#endif
diff --git a/polarssl/src/library/debug.c b/polarssl/src/library/debug.c
deleted file mode 100644
index 687e194..0000000
--- a/polarssl/src/library/debug.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Debugging routines
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_DEBUG_C)
-
-#include "polarssl/debug.h"
-
-#include <stdarg.h>
-#include <stdlib.h>
-
-#if defined _MSC_VER && !defined snprintf
-#define snprintf _snprintf
-#endif
-
-#if defined _MSC_VER && !defined vsnprintf
-#define vsnprintf _vsnprintf
-#endif
-
-char *debug_fmt( const char *format, ... )
-{
- va_list argp;
- static char str[512];
- int maxlen = sizeof( str ) - 1;
-
- va_start( argp, format );
- vsnprintf( str, maxlen, format, argp );
- va_end( argp );
-
- str[maxlen] = '\0';
- return( str );
-}
-
-void debug_print_msg( const ssl_context *ssl, int level,
- const char *file, int line, const char *text )
-{
- char str[512];
- int maxlen = sizeof( str ) - 1;
-
- if( ssl->f_dbg == NULL )
- return;
-
- snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text );
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
-}
-
-void debug_print_ret( const ssl_context *ssl, int level,
- const char *file, int line,
- const char *text, int ret )
-{
- char str[512];
- int maxlen = sizeof( str ) - 1;
-
- if( ssl->f_dbg == NULL )
- return;
-
- snprintf( str, maxlen, "%s(%04d): %s() returned %d (0x%x)\n",
- file, line, text, ret, ret );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
-}
-
-void debug_print_buf( const ssl_context *ssl, int level,
- const char *file, int line, const char *text,
- unsigned char *buf, size_t len )
-{
- char str[512];
- size_t i, maxlen = sizeof( str ) - 1;
-
- if( ssl->f_dbg == NULL )
- return;
-
- snprintf( str, maxlen, "%s(%04d): dumping '%s' (%d bytes)\n",
- file, line, text, (unsigned int) len );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
-
- for( i = 0; i < len; i++ )
- {
- if( i >= 4096 )
- break;
-
- if( i % 16 == 0 )
- {
- if( i > 0 )
- ssl->f_dbg( ssl->p_dbg, level, "\n" );
-
- snprintf( str, maxlen, "%s(%04d): %04x: ", file, line,
- (unsigned int) i );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
- }
-
- snprintf( str, maxlen, " %02x", (unsigned int) buf[i] );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
- }
-
- if( len > 0 )
- ssl->f_dbg( ssl->p_dbg, level, "\n" );
-}
-
-void debug_print_mpi( const ssl_context *ssl, int level,
- const char *file, int line,
- const char *text, const mpi *X )
-{
- char str[512];
- int j, k, maxlen = sizeof( str ) - 1, zeros = 1;
- size_t i, n;
-
- if( ssl->f_dbg == NULL || X == NULL )
- return;
-
- for( n = X->n - 1; n > 0; n-- )
- if( X->p[n] != 0 )
- break;
-
- for( j = ( sizeof(t_uint) << 3 ) - 1; j >= 0; j-- )
- if( ( ( X->p[n] >> j ) & 1 ) != 0 )
- break;
-
- snprintf( str, maxlen, "%s(%04d): value of '%s' (%lu bits) is:\n",
- file, line, text,
- (unsigned long) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
-
- for( i = n + 1, j = 0; i > 0; i-- )
- {
- if( zeros && X->p[i - 1] == 0 )
- continue;
-
- for( k = sizeof( t_uint ) - 1; k >= 0; k-- )
- {
- if( zeros && ( ( X->p[i - 1] >> (k << 3) ) & 0xFF ) == 0 )
- continue;
- else
- zeros = 0;
-
- if( j % 16 == 0 )
- {
- if( j > 0 )
- ssl->f_dbg( ssl->p_dbg, level, "\n" );
-
- snprintf( str, maxlen, "%s(%04d): ", file, line );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
- }
-
- snprintf( str, maxlen, " %02x", (unsigned int)
- ( X->p[i - 1] >> (k << 3) ) & 0xFF );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
-
- j++;
- }
-
- }
-
- if( zeros == 1 )
- {
- snprintf( str, maxlen, "%s(%04d): ", file, line );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
- ssl->f_dbg( ssl->p_dbg, level, " 00" );
- }
-
- ssl->f_dbg( ssl->p_dbg, level, "\n" );
-}
-
-void debug_print_crt( const ssl_context *ssl, int level,
- const char *file, int line,
- const char *text, const x509_cert *crt )
-{
- char str[1024], prefix[64];
- int i = 0, maxlen = sizeof( prefix ) - 1;
-
- if( ssl->f_dbg == NULL || crt == NULL )
- return;
-
- snprintf( prefix, maxlen, "%s(%04d): ", file, line );
- prefix[maxlen] = '\0';
- maxlen = sizeof( str ) - 1;
-
- while( crt != NULL )
- {
- char buf[1024];
- x509parse_cert_info( buf, sizeof( buf ) - 1, prefix, crt );
-
- snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s",
- file, line, text, ++i, buf );
-
- str[maxlen] = '\0';
- ssl->f_dbg( ssl->p_dbg, level, str );
-
- debug_print_mpi( ssl, level, file, line,
- "crt->rsa.N", &crt->rsa.N );
-
- debug_print_mpi( ssl, level, file, line,
- "crt->rsa.E", &crt->rsa.E );
-
- crt = crt->next;
- }
-}
-
-#endif
diff --git a/polarssl/src/library/des.c b/polarssl/src/library/des.c
deleted file mode 100644
index b40baf8..0000000
--- a/polarssl/src/library/des.c
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
- * FIPS-46-3 compliant Triple-DES implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * DES, on which TDES is based, was originally designed by Horst Feistel
- * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
- *
- * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_DES_C)
-
-#include "polarssl/des.h"
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) ); \
-}
-#endif
-
-/*
- * Expanded DES S-boxes
- */
-static const unsigned long SB1[64] =
-{
- 0x01010400, 0x00000000, 0x00010000, 0x01010404,
- 0x01010004, 0x00010404, 0x00000004, 0x00010000,
- 0x00000400, 0x01010400, 0x01010404, 0x00000400,
- 0x01000404, 0x01010004, 0x01000000, 0x00000004,
- 0x00000404, 0x01000400, 0x01000400, 0x00010400,
- 0x00010400, 0x01010000, 0x01010000, 0x01000404,
- 0x00010004, 0x01000004, 0x01000004, 0x00010004,
- 0x00000000, 0x00000404, 0x00010404, 0x01000000,
- 0x00010000, 0x01010404, 0x00000004, 0x01010000,
- 0x01010400, 0x01000000, 0x01000000, 0x00000400,
- 0x01010004, 0x00010000, 0x00010400, 0x01000004,
- 0x00000400, 0x00000004, 0x01000404, 0x00010404,
- 0x01010404, 0x00010004, 0x01010000, 0x01000404,
- 0x01000004, 0x00000404, 0x00010404, 0x01010400,
- 0x00000404, 0x01000400, 0x01000400, 0x00000000,
- 0x00010004, 0x00010400, 0x00000000, 0x01010004
-};
-
-static const unsigned long SB2[64] =
-{
- 0x80108020, 0x80008000, 0x00008000, 0x00108020,
- 0x00100000, 0x00000020, 0x80100020, 0x80008020,
- 0x80000020, 0x80108020, 0x80108000, 0x80000000,
- 0x80008000, 0x00100000, 0x00000020, 0x80100020,
- 0x00108000, 0x00100020, 0x80008020, 0x00000000,
- 0x80000000, 0x00008000, 0x00108020, 0x80100000,
- 0x00100020, 0x80000020, 0x00000000, 0x00108000,
- 0x00008020, 0x80108000, 0x80100000, 0x00008020,
- 0x00000000, 0x00108020, 0x80100020, 0x00100000,
- 0x80008020, 0x80100000, 0x80108000, 0x00008000,
- 0x80100000, 0x80008000, 0x00000020, 0x80108020,
- 0x00108020, 0x00000020, 0x00008000, 0x80000000,
- 0x00008020, 0x80108000, 0x00100000, 0x80000020,
- 0x00100020, 0x80008020, 0x80000020, 0x00100020,
- 0x00108000, 0x00000000, 0x80008000, 0x00008020,
- 0x80000000, 0x80100020, 0x80108020, 0x00108000
-};
-
-static const unsigned long SB3[64] =
-{
- 0x00000208, 0x08020200, 0x00000000, 0x08020008,
- 0x08000200, 0x00000000, 0x00020208, 0x08000200,
- 0x00020008, 0x08000008, 0x08000008, 0x00020000,
- 0x08020208, 0x00020008, 0x08020000, 0x00000208,
- 0x08000000, 0x00000008, 0x08020200, 0x00000200,
- 0x00020200, 0x08020000, 0x08020008, 0x00020208,
- 0x08000208, 0x00020200, 0x00020000, 0x08000208,
- 0x00000008, 0x08020208, 0x00000200, 0x08000000,
- 0x08020200, 0x08000000, 0x00020008, 0x00000208,
- 0x00020000, 0x08020200, 0x08000200, 0x00000000,
- 0x00000200, 0x00020008, 0x08020208, 0x08000200,
- 0x08000008, 0x00000200, 0x00000000, 0x08020008,
- 0x08000208, 0x00020000, 0x08000000, 0x08020208,
- 0x00000008, 0x00020208, 0x00020200, 0x08000008,
- 0x08020000, 0x08000208, 0x00000208, 0x08020000,
- 0x00020208, 0x00000008, 0x08020008, 0x00020200
-};
-
-static const unsigned long SB4[64] =
-{
- 0x00802001, 0x00002081, 0x00002081, 0x00000080,
- 0x00802080, 0x00800081, 0x00800001, 0x00002001,
- 0x00000000, 0x00802000, 0x00802000, 0x00802081,
- 0x00000081, 0x00000000, 0x00800080, 0x00800001,
- 0x00000001, 0x00002000, 0x00800000, 0x00802001,
- 0x00000080, 0x00800000, 0x00002001, 0x00002080,
- 0x00800081, 0x00000001, 0x00002080, 0x00800080,
- 0x00002000, 0x00802080, 0x00802081, 0x00000081,
- 0x00800080, 0x00800001, 0x00802000, 0x00802081,
- 0x00000081, 0x00000000, 0x00000000, 0x00802000,
- 0x00002080, 0x00800080, 0x00800081, 0x00000001,
- 0x00802001, 0x00002081, 0x00002081, 0x00000080,
- 0x00802081, 0x00000081, 0x00000001, 0x00002000,
- 0x00800001, 0x00002001, 0x00802080, 0x00800081,
- 0x00002001, 0x00002080, 0x00800000, 0x00802001,
- 0x00000080, 0x00800000, 0x00002000, 0x00802080
-};
-
-static const unsigned long SB5[64] =
-{
- 0x00000100, 0x02080100, 0x02080000, 0x42000100,
- 0x00080000, 0x00000100, 0x40000000, 0x02080000,
- 0x40080100, 0x00080000, 0x02000100, 0x40080100,
- 0x42000100, 0x42080000, 0x00080100, 0x40000000,
- 0x02000000, 0x40080000, 0x40080000, 0x00000000,
- 0x40000100, 0x42080100, 0x42080100, 0x02000100,
- 0x42080000, 0x40000100, 0x00000000, 0x42000000,
- 0x02080100, 0x02000000, 0x42000000, 0x00080100,
- 0x00080000, 0x42000100, 0x00000100, 0x02000000,
- 0x40000000, 0x02080000, 0x42000100, 0x40080100,
- 0x02000100, 0x40000000, 0x42080000, 0x02080100,
- 0x40080100, 0x00000100, 0x02000000, 0x42080000,
- 0x42080100, 0x00080100, 0x42000000, 0x42080100,
- 0x02080000, 0x00000000, 0x40080000, 0x42000000,
- 0x00080100, 0x02000100, 0x40000100, 0x00080000,
- 0x00000000, 0x40080000, 0x02080100, 0x40000100
-};
-
-static const unsigned long SB6[64] =
-{
- 0x20000010, 0x20400000, 0x00004000, 0x20404010,
- 0x20400000, 0x00000010, 0x20404010, 0x00400000,
- 0x20004000, 0x00404010, 0x00400000, 0x20000010,
- 0x00400010, 0x20004000, 0x20000000, 0x00004010,
- 0x00000000, 0x00400010, 0x20004010, 0x00004000,
- 0x00404000, 0x20004010, 0x00000010, 0x20400010,
- 0x20400010, 0x00000000, 0x00404010, 0x20404000,
- 0x00004010, 0x00404000, 0x20404000, 0x20000000,
- 0x20004000, 0x00000010, 0x20400010, 0x00404000,
- 0x20404010, 0x00400000, 0x00004010, 0x20000010,
- 0x00400000, 0x20004000, 0x20000000, 0x00004010,
- 0x20000010, 0x20404010, 0x00404000, 0x20400000,
- 0x00404010, 0x20404000, 0x00000000, 0x20400010,
- 0x00000010, 0x00004000, 0x20400000, 0x00404010,
- 0x00004000, 0x00400010, 0x20004010, 0x00000000,
- 0x20404000, 0x20000000, 0x00400010, 0x20004010
-};
-
-static const unsigned long SB7[64] =
-{
- 0x00200000, 0x04200002, 0x04000802, 0x00000000,
- 0x00000800, 0x04000802, 0x00200802, 0x04200800,
- 0x04200802, 0x00200000, 0x00000000, 0x04000002,
- 0x00000002, 0x04000000, 0x04200002, 0x00000802,
- 0x04000800, 0x00200802, 0x00200002, 0x04000800,
- 0x04000002, 0x04200000, 0x04200800, 0x00200002,
- 0x04200000, 0x00000800, 0x00000802, 0x04200802,
- 0x00200800, 0x00000002, 0x04000000, 0x00200800,
- 0x04000000, 0x00200800, 0x00200000, 0x04000802,
- 0x04000802, 0x04200002, 0x04200002, 0x00000002,
- 0x00200002, 0x04000000, 0x04000800, 0x00200000,
- 0x04200800, 0x00000802, 0x00200802, 0x04200800,
- 0x00000802, 0x04000002, 0x04200802, 0x04200000,
- 0x00200800, 0x00000000, 0x00000002, 0x04200802,
- 0x00000000, 0x00200802, 0x04200000, 0x00000800,
- 0x04000002, 0x04000800, 0x00000800, 0x00200002
-};
-
-static const unsigned long SB8[64] =
-{
- 0x10001040, 0x00001000, 0x00040000, 0x10041040,
- 0x10000000, 0x10001040, 0x00000040, 0x10000000,
- 0x00040040, 0x10040000, 0x10041040, 0x00041000,
- 0x10041000, 0x00041040, 0x00001000, 0x00000040,
- 0x10040000, 0x10000040, 0x10001000, 0x00001040,
- 0x00041000, 0x00040040, 0x10040040, 0x10041000,
- 0x00001040, 0x00000000, 0x00000000, 0x10040040,
- 0x10000040, 0x10001000, 0x00041040, 0x00040000,
- 0x00041040, 0x00040000, 0x10041000, 0x00001000,
- 0x00000040, 0x10040040, 0x00001000, 0x00041040,
- 0x10001000, 0x00000040, 0x10000040, 0x10040000,
- 0x10040040, 0x10000000, 0x00040000, 0x10001040,
- 0x00000000, 0x10041040, 0x00040040, 0x10000040,
- 0x10040000, 0x10001000, 0x10001040, 0x00000000,
- 0x10041040, 0x00041000, 0x00041000, 0x00001040,
- 0x00001040, 0x00040040, 0x10000000, 0x10041000
-};
-
-/*
- * PC1: left and right halves bit-swap
- */
-static const unsigned long LHs[16] =
-{
- 0x00000000, 0x00000001, 0x00000100, 0x00000101,
- 0x00010000, 0x00010001, 0x00010100, 0x00010101,
- 0x01000000, 0x01000001, 0x01000100, 0x01000101,
- 0x01010000, 0x01010001, 0x01010100, 0x01010101
-};
-
-static const unsigned long RHs[16] =
-{
- 0x00000000, 0x01000000, 0x00010000, 0x01010000,
- 0x00000100, 0x01000100, 0x00010100, 0x01010100,
- 0x00000001, 0x01000001, 0x00010001, 0x01010001,
- 0x00000101, 0x01000101, 0x00010101, 0x01010101,
-};
-
-/*
- * Initial Permutation macro
- */
-#define DES_IP(X,Y) \
-{ \
- T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
- T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
- T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
- T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
- Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
- T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
- X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
-}
-
-/*
- * Final Permutation macro
- */
-#define DES_FP(X,Y) \
-{ \
- X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
- T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
- Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
- T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
- T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
- T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
- T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
-}
-
-/*
- * DES round macro
- */
-#define DES_ROUND(X,Y) \
-{ \
- T = *SK++ ^ X; \
- Y ^= SB8[ (T ) & 0x3F ] ^ \
- SB6[ (T >> 8) & 0x3F ] ^ \
- SB4[ (T >> 16) & 0x3F ] ^ \
- SB2[ (T >> 24) & 0x3F ]; \
- \
- T = *SK++ ^ ((X << 28) | (X >> 4)); \
- Y ^= SB7[ (T ) & 0x3F ] ^ \
- SB5[ (T >> 8) & 0x3F ] ^ \
- SB3[ (T >> 16) & 0x3F ] ^ \
- SB1[ (T >> 24) & 0x3F ]; \
-}
-
-#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
-
-static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
- 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
- 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
- 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
- 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
- 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
- 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
- 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
- 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
- 254 };
-
-void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
-{
- int i;
-
- for( i = 0; i < DES_KEY_SIZE; i++ )
- key[i] = odd_parity_table[key[i] / 2];
-}
-
-/*
- * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
- */
-int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
-{
- int i;
-
- for( i = 0; i < DES_KEY_SIZE; i++ )
- if ( key[i] != odd_parity_table[key[i] / 2] )
- return( 1 );
-
- return( 0 );
-}
-
-/*
- * Table of weak and semi-weak keys
- *
- * Source: http://en.wikipedia.org/wiki/Weak_key
- *
- * Weak:
- * Alternating ones + zeros (0x0101010101010101)
- * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
- * '0xE0E0E0E0F1F1F1F1'
- * '0x1F1F1F1F0E0E0E0E'
- *
- * Semi-weak:
- * 0x011F011F010E010E and 0x1F011F010E010E01
- * 0x01E001E001F101F1 and 0xE001E001F101F101
- * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
- * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
- * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
- * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
- *
- */
-
-#define WEAK_KEY_COUNT 16
-
-static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
-{
- { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
- { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
- { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
- { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
-
- { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
- { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
- { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
- { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
- { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
- { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
- { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
- { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
- { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
- { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
- { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
- { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
-};
-
-int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
-{
- int i;
-
- for( i = 0; i < WEAK_KEY_COUNT; i++ )
- if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0)
- return( 1 );
-
- return( 0 );
-}
-
-static void des_setkey( unsigned long SK[32], const unsigned char key[DES_KEY_SIZE] )
-{
- int i;
- unsigned long X, Y, T;
-
- GET_ULONG_BE( X, key, 0 );
- GET_ULONG_BE( Y, key, 4 );
-
- /*
- * Permuted Choice 1
- */
- T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
- T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
-
- X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
- | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
- | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
- | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
-
- Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
- | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
- | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
- | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
-
- X &= 0x0FFFFFFF;
- Y &= 0x0FFFFFFF;
-
- /*
- * calculate subkeys
- */
- for( i = 0; i < 16; i++ )
- {
- if( i < 2 || i == 8 || i == 15 )
- {
- X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
- Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
- }
- else
- {
- X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
- Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
- }
-
- *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
- | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
- | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
- | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
- | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
- | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
- | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
- | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
- | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
- | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
- | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
-
- *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
- | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
- | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
- | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
- | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
- | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
- | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
- | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
- | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
- | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
- | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
- }
-}
-
-/*
- * DES key schedule (56-bit, encryption)
- */
-int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
-{
- des_setkey( ctx->sk, key );
-
- return( 0 );
-}
-
-/*
- * DES key schedule (56-bit, decryption)
- */
-int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
-{
- int i;
-
- des_setkey( ctx->sk, key );
-
- for( i = 0; i < 16; i += 2 )
- {
- SWAP( ctx->sk[i ], ctx->sk[30 - i] );
- SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
- }
-
- return( 0 );
-}
-
-static void des3_set2key( unsigned long esk[96],
- unsigned long dsk[96],
- const unsigned char key[DES_KEY_SIZE*2] )
-{
- int i;
-
- des_setkey( esk, key );
- des_setkey( dsk + 32, key + 8 );
-
- for( i = 0; i < 32; i += 2 )
- {
- dsk[i ] = esk[30 - i];
- dsk[i + 1] = esk[31 - i];
-
- esk[i + 32] = dsk[62 - i];
- esk[i + 33] = dsk[63 - i];
-
- esk[i + 64] = esk[i ];
- esk[i + 65] = esk[i + 1];
-
- dsk[i + 64] = dsk[i ];
- dsk[i + 65] = dsk[i + 1];
- }
-}
-
-/*
- * Triple-DES key schedule (112-bit, encryption)
- */
-int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
-{
- unsigned long sk[96];
-
- des3_set2key( ctx->sk, sk, key );
- memset( sk, 0, sizeof( sk ) );
-
- return( 0 );
-}
-
-/*
- * Triple-DES key schedule (112-bit, decryption)
- */
-int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
-{
- unsigned long sk[96];
-
- des3_set2key( sk, ctx->sk, key );
- memset( sk, 0, sizeof( sk ) );
-
- return( 0 );
-}
-
-static void des3_set3key( unsigned long esk[96],
- unsigned long dsk[96],
- const unsigned char key[24] )
-{
- int i;
-
- des_setkey( esk, key );
- des_setkey( dsk + 32, key + 8 );
- des_setkey( esk + 64, key + 16 );
-
- for( i = 0; i < 32; i += 2 )
- {
- dsk[i ] = esk[94 - i];
- dsk[i + 1] = esk[95 - i];
-
- esk[i + 32] = dsk[62 - i];
- esk[i + 33] = dsk[63 - i];
-
- dsk[i + 64] = esk[30 - i];
- dsk[i + 65] = esk[31 - i];
- }
-}
-
-/*
- * Triple-DES key schedule (168-bit, encryption)
- */
-int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
-{
- unsigned long sk[96];
-
- des3_set3key( ctx->sk, sk, key );
- memset( sk, 0, sizeof( sk ) );
-
- return( 0 );
-}
-
-/*
- * Triple-DES key schedule (168-bit, decryption)
- */
-int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
-{
- unsigned long sk[96];
-
- des3_set3key( sk, ctx->sk, key );
- memset( sk, 0, sizeof( sk ) );
-
- return( 0 );
-}
-
-/*
- * DES-ECB block encryption/decryption
- */
-int des_crypt_ecb( des_context *ctx,
- const unsigned char input[8],
- unsigned char output[8] )
-{
- int i;
- unsigned long X, Y, T, *SK;
-
- SK = ctx->sk;
-
- GET_ULONG_BE( X, input, 0 );
- GET_ULONG_BE( Y, input, 4 );
-
- DES_IP( X, Y );
-
- for( i = 0; i < 8; i++ )
- {
- DES_ROUND( Y, X );
- DES_ROUND( X, Y );
- }
-
- DES_FP( Y, X );
-
- PUT_ULONG_BE( Y, output, 0 );
- PUT_ULONG_BE( X, output, 4 );
-
- return( 0 );
-}
-
-/*
- * DES-CBC buffer encryption/decryption
- */
-int des_crypt_cbc( des_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[8],
- const unsigned char *input,
- unsigned char *output )
-{
- int i;
- unsigned char temp[8];
-
- if( length % 8 )
- return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
-
- if( mode == DES_ENCRYPT )
- {
- while( length > 0 )
- {
- for( i = 0; i < 8; i++ )
- output[i] = (unsigned char)( input[i] ^ iv[i] );
-
- des_crypt_ecb( ctx, output, output );
- memcpy( iv, output, 8 );
-
- input += 8;
- output += 8;
- length -= 8;
- }
- }
- else /* DES_DECRYPT */
- {
- while( length > 0 )
- {
- memcpy( temp, input, 8 );
- des_crypt_ecb( ctx, input, output );
-
- for( i = 0; i < 8; i++ )
- output[i] = (unsigned char)( output[i] ^ iv[i] );
-
- memcpy( iv, temp, 8 );
-
- input += 8;
- output += 8;
- length -= 8;
- }
- }
-
- return( 0 );
-}
-
-/*
- * 3DES-ECB block encryption/decryption
- */
-int des3_crypt_ecb( des3_context *ctx,
- const unsigned char input[8],
- unsigned char output[8] )
-{
- int i;
- unsigned long X, Y, T, *SK;
-
- SK = ctx->sk;
-
- GET_ULONG_BE( X, input, 0 );
- GET_ULONG_BE( Y, input, 4 );
-
- DES_IP( X, Y );
-
- for( i = 0; i < 8; i++ )
- {
- DES_ROUND( Y, X );
- DES_ROUND( X, Y );
- }
-
- for( i = 0; i < 8; i++ )
- {
- DES_ROUND( X, Y );
- DES_ROUND( Y, X );
- }
-
- for( i = 0; i < 8; i++ )
- {
- DES_ROUND( Y, X );
- DES_ROUND( X, Y );
- }
-
- DES_FP( Y, X );
-
- PUT_ULONG_BE( Y, output, 0 );
- PUT_ULONG_BE( X, output, 4 );
-
- return( 0 );
-}
-
-/*
- * 3DES-CBC buffer encryption/decryption
- */
-int des3_crypt_cbc( des3_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[8],
- const unsigned char *input,
- unsigned char *output )
-{
- int i;
- unsigned char temp[8];
-
- if( length % 8 )
- return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
-
- if( mode == DES_ENCRYPT )
- {
- while( length > 0 )
- {
- for( i = 0; i < 8; i++ )
- output[i] = (unsigned char)( input[i] ^ iv[i] );
-
- des3_crypt_ecb( ctx, output, output );
- memcpy( iv, output, 8 );
-
- input += 8;
- output += 8;
- length -= 8;
- }
- }
- else /* DES_DECRYPT */
- {
- while( length > 0 )
- {
- memcpy( temp, input, 8 );
- des3_crypt_ecb( ctx, input, output );
-
- for( i = 0; i < 8; i++ )
- output[i] = (unsigned char)( output[i] ^ iv[i] );
-
- memcpy( iv, temp, 8 );
-
- input += 8;
- output += 8;
- length -= 8;
- }
- }
-
- return( 0 );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <stdio.h>
-
-/*
- * DES and 3DES test vectors from:
- *
- * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
- */
-static const unsigned char des3_test_keys[24] =
-{
- 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
- 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
- 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
-};
-
-static const unsigned char des3_test_iv[8] =
-{
- 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
-};
-
-static const unsigned char des3_test_buf[8] =
-{
- 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
-};
-
-static const unsigned char des3_test_ecb_dec[3][8] =
-{
- { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
- { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
- { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
-};
-
-static const unsigned char des3_test_ecb_enc[3][8] =
-{
- { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
- { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
- { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
-};
-
-static const unsigned char des3_test_cbc_dec[3][8] =
-{
- { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
- { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
- { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
-};
-
-static const unsigned char des3_test_cbc_enc[3][8] =
-{
- { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
- { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
- { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
-};
-
-/*
- * Checkup routine
- */
-int des_self_test( int verbose )
-{
- int i, j, u, v;
- des_context ctx;
- des3_context ctx3;
- unsigned char key[24];
- unsigned char buf[8];
- unsigned char prv[8];
- unsigned char iv[8];
-
- memset( key, 0, 24 );
-
- /*
- * ECB mode
- */
- for( i = 0; i < 6; i++ )
- {
- u = i >> 1;
- v = i & 1;
-
- if( verbose != 0 )
- printf( " DES%c-ECB-%3d (%s): ",
- ( u == 0 ) ? ' ' : '3', 56 + u * 56,
- ( v == DES_DECRYPT ) ? "dec" : "enc" );
-
- memcpy( buf, des3_test_buf, 8 );
-
- switch( i )
- {
- case 0:
- des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
- break;
-
- case 1:
- des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
- break;
-
- case 2:
- des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- case 3:
- des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- case 4:
- des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- case 5:
- des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- default:
- return( 1 );
- }
-
- for( j = 0; j < 10000; j++ )
- {
- if( u == 0 )
- des_crypt_ecb( &ctx, buf, buf );
- else
- des3_crypt_ecb( &ctx3, buf, buf );
- }
-
- if( ( v == DES_DECRYPT &&
- memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
- ( v != DES_DECRYPT &&
- memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- /*
- * CBC mode
- */
- for( i = 0; i < 6; i++ )
- {
- u = i >> 1;
- v = i & 1;
-
- if( verbose != 0 )
- printf( " DES%c-CBC-%3d (%s): ",
- ( u == 0 ) ? ' ' : '3', 56 + u * 56,
- ( v == DES_DECRYPT ) ? "dec" : "enc" );
-
- memcpy( iv, des3_test_iv, 8 );
- memcpy( prv, des3_test_iv, 8 );
- memcpy( buf, des3_test_buf, 8 );
-
- switch( i )
- {
- case 0:
- des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
- break;
-
- case 1:
- des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
- break;
-
- case 2:
- des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- case 3:
- des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- case 4:
- des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- case 5:
- des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
- break;
-
- default:
- return( 1 );
- }
-
- if( v == DES_DECRYPT )
- {
- for( j = 0; j < 10000; j++ )
- {
- if( u == 0 )
- des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
- else
- des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
- }
- }
- else
- {
- for( j = 0; j < 10000; j++ )
- {
- unsigned char tmp[8];
-
- if( u == 0 )
- des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
- else
- des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
-
- memcpy( tmp, prv, 8 );
- memcpy( prv, buf, 8 );
- memcpy( buf, tmp, 8 );
- }
-
- memcpy( buf, prv, 8 );
- }
-
- if( ( v == DES_DECRYPT &&
- memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
- ( v != DES_DECRYPT &&
- memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/dhm.c b/polarssl/src/library/dhm.c
deleted file mode 100644
index 4a59571..0000000
--- a/polarssl/src/library/dhm.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Diffie-Hellman-Merkle key exchange
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * Reference:
- *
- * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_DHM_C)
-
-#include "polarssl/dhm.h"
-
-/*
- * helper to validate the mpi size and import it
- */
-static int dhm_read_bignum( mpi *X,
- unsigned char **p,
- const unsigned char *end )
-{
- int ret, n;
-
- if( end - *p < 2 )
- return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
-
- n = ( (*p)[0] << 8 ) | (*p)[1];
- (*p) += 2;
-
- if( (int)( end - *p ) < n )
- return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
-
- if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
- return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret );
-
- (*p) += n;
-
- return( 0 );
-}
-
-/*
- * Verify sanity of parameter with regards to P
- *
- * Parameter should be: 2 <= public_param <= P - 2
- *
- * For more information on the attack, see:
- * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
- * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
- */
-static int dhm_check_range( const mpi *param, const mpi *P )
-{
- mpi L, U;
- int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA;
-
- mpi_init( &L ); mpi_init( &U );
- mpi_lset( &L, 2 );
- mpi_sub_int( &U, P, 2 );
-
- if( mpi_cmp_mpi( param, &L ) >= 0 &&
- mpi_cmp_mpi( param, &U ) <= 0 )
- {
- ret = 0;
- }
-
- mpi_free( &L ); mpi_free( &U );
-
- return( ret );
-}
-
-/*
- * Parse the ServerKeyExchange parameters
- */
-int dhm_read_params( dhm_context *ctx,
- unsigned char **p,
- const unsigned char *end )
-{
- int ret;
-
- memset( ctx, 0, sizeof( dhm_context ) );
-
- if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
- ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
- ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
- return( ret );
-
- if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
- return( ret );
-
- ctx->len = mpi_size( &ctx->P );
-
- if( end - *p < 2 )
- return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
-
- return( 0 );
-}
-
-/*
- * Setup and write the ServerKeyExchange parameters
- */
-int dhm_make_params( dhm_context *ctx, int x_size,
- unsigned char *output, size_t *olen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
-{
- int ret, count = 0;
- size_t n1, n2, n3;
- unsigned char *p;
-
- /*
- * Generate X as large as possible ( < P )
- */
- do
- {
- mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
-
- while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
- mpi_shift_r( &ctx->X, 1 );
-
- if( count++ > 10 )
- return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED );
- }
- while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
-
- /*
- * Calculate GX = G^X mod P
- */
- MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
- &ctx->P , &ctx->RP ) );
-
- if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
- return( ret );
-
- /*
- * export P, G, GX
- */
-#define DHM_MPI_EXPORT(X,n) \
- MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
- *p++ = (unsigned char)( n >> 8 ); \
- *p++ = (unsigned char)( n ); p += n;
-
- n1 = mpi_size( &ctx->P );
- n2 = mpi_size( &ctx->G );
- n3 = mpi_size( &ctx->GX );
-
- p = output;
- DHM_MPI_EXPORT( &ctx->P , n1 );
- DHM_MPI_EXPORT( &ctx->G , n2 );
- DHM_MPI_EXPORT( &ctx->GX, n3 );
-
- *olen = p - output;
-
- ctx->len = n1;
-
-cleanup:
-
- if( ret != 0 )
- return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret );
-
- return( 0 );
-}
-
-/*
- * Import the peer's public value G^Y
- */
-int dhm_read_public( dhm_context *ctx,
- const unsigned char *input, size_t ilen )
-{
- int ret;
-
- if( ctx == NULL || ilen < 1 || ilen > ctx->len )
- return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
-
- if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
- return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret );
-
- return( 0 );
-}
-
-/*
- * Create own private value X and export G^X
- */
-int dhm_make_public( dhm_context *ctx, int x_size,
- unsigned char *output, size_t olen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
-{
- int ret, count = 0;
-
- if( ctx == NULL || olen < 1 || olen > ctx->len )
- return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
-
- /*
- * generate X and calculate GX = G^X mod P
- */
- do
- {
- mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
-
- while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
- mpi_shift_r( &ctx->X, 1 );
-
- if( count++ > 10 )
- return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED );
- }
- while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
-
- MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
- &ctx->P , &ctx->RP ) );
-
- if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
- return( ret );
-
- MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
-
-cleanup:
-
- if( ret != 0 )
- return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
-
- return( 0 );
-}
-
-/*
- * Derive and export the shared secret (G^Y)^X mod P
- */
-int dhm_calc_secret( dhm_context *ctx,
- unsigned char *output, size_t *olen )
-{
- int ret;
-
- if( ctx == NULL || *olen < ctx->len )
- return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
-
- MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
- &ctx->P, &ctx->RP ) );
-
- if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
- return( ret );
-
- *olen = mpi_size( &ctx->K );
-
- MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
-
-cleanup:
-
- if( ret != 0 )
- return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
-
- return( 0 );
-}
-
-/*
- * Free the components of a DHM key
- */
-void dhm_free( dhm_context *ctx )
-{
- mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
- mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
- mpi_free( &ctx->P );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-/*
- * Checkup routine
- */
-int dhm_self_test( int verbose )
-{
- return( verbose++ );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/entropy.c b/polarssl/src/library/entropy.c
deleted file mode 100644
index 9662454..0000000
--- a/polarssl/src/library/entropy.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Entropy accumulator implementation
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_ENTROPY_C)
-
-#include "polarssl/entropy.h"
-#include "polarssl/entropy_poll.h"
-
-#if defined(POLARSSL_HAVEGE_C)
-#include "polarssl/havege.h"
-#endif
-
-#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
-
-void entropy_init( entropy_context *ctx )
-{
- memset( ctx, 0, sizeof(entropy_context) );
-
- sha4_starts( &ctx->accumulator, 0 );
-#if defined(POLARSSL_HAVEGE_C)
- havege_init( &ctx->havege_data );
-#endif
-
-#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
-#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
- entropy_add_source( ctx, platform_entropy_poll, NULL,
- ENTROPY_MIN_PLATFORM );
-#endif
-#if defined(POLARSSL_TIMING_C)
- entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
-#endif
-#if defined(POLARSSL_HAVEGE_C)
- entropy_add_source( ctx, havege_poll, &ctx->havege_data,
- ENTROPY_MIN_HAVEGE );
-#endif
-#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
-}
-
-int entropy_add_source( entropy_context *ctx,
- f_source_ptr f_source, void *p_source,
- size_t threshold )
-{
- int index = ctx->source_count;
-
- if( index >= ENTROPY_MAX_SOURCES )
- return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
-
- ctx->source[index].f_source = f_source;
- ctx->source[index].p_source = p_source;
- ctx->source[index].threshold = threshold;
-
- ctx->source_count++;
-
- return( 0 );
-}
-
-/*
- * Entropy accumulator update
- */
-int entropy_update( entropy_context *ctx, unsigned char source_id,
- const unsigned char *data, size_t len )
-{
- unsigned char header[2];
- unsigned char tmp[ENTROPY_BLOCK_SIZE];
- size_t use_len = len;
- const unsigned char *p = data;
-
- if( use_len > ENTROPY_BLOCK_SIZE )
- {
- sha4( data, len, tmp, 0 );
-
- p = tmp;
- use_len = ENTROPY_BLOCK_SIZE;
- }
-
- header[0] = source_id;
- header[1] = use_len & 0xFF;
-
- sha4_update( &ctx->accumulator, header, 2 );
- sha4_update( &ctx->accumulator, p, use_len );
-
- return( 0 );
-}
-
-int entropy_update_manual( entropy_context *ctx,
- const unsigned char *data, size_t len )
-{
- return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
-}
-
-/*
- * Run through the different sources to add entropy to our accumulator
- */
-int entropy_gather( entropy_context *ctx )
-{
- int ret, i;
- unsigned char buf[ENTROPY_MAX_GATHER];
- size_t olen;
-
- if( ctx->source_count == 0 )
- return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
-
- /*
- * Run through our entropy sources
- */
- for( i = 0; i < ctx->source_count; i++ )
- {
- olen = 0;
- if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
- buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
- {
- return( ret );
- }
-
- /*
- * Add if we actually gathered something
- */
- if( olen > 0 )
- {
- entropy_update( ctx, (unsigned char) i, buf, olen );
- ctx->source[i].size += olen;
- }
- }
-
- return( 0 );
-}
-
-int entropy_func( void *data, unsigned char *output, size_t len )
-{
- int ret, count = 0, i, reached;
- entropy_context *ctx = (entropy_context *) data;
- unsigned char buf[ENTROPY_BLOCK_SIZE];
-
- if( len > ENTROPY_BLOCK_SIZE )
- return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
-
- /*
- * Always gather extra entropy before a call
- */
- do
- {
- if( count++ > ENTROPY_MAX_LOOP )
- return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
-
- if( ( ret = entropy_gather( ctx ) ) != 0 )
- return( ret );
-
- reached = 0;
-
- for( i = 0; i < ctx->source_count; i++ )
- if( ctx->source[i].size >= ctx->source[i].threshold )
- reached++;
- }
- while( reached != ctx->source_count );
-
- memset( buf, 0, ENTROPY_BLOCK_SIZE );
-
- sha4_finish( &ctx->accumulator, buf );
-
- /*
- * Perform second SHA-512 on entropy
- */
- sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
-
- /*
- * Reset accumulator and counters and recycle existing entropy
- */
- memset( &ctx->accumulator, 0, sizeof( sha4_context ) );
- sha4_starts( &ctx->accumulator, 0 );
- sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
-
- for( i = 0; i < ctx->source_count; i++ )
- ctx->source[i].size = 0;
-
- memcpy( output, buf, len );
-
- return( 0 );
-}
-
-#endif
diff --git a/polarssl/src/library/entropy_poll.c b/polarssl/src/library/entropy_poll.c
deleted file mode 100644
index a0c9b7b..0000000
--- a/polarssl/src/library/entropy_poll.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Platform-specific and custom entropy polling functions
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_ENTROPY_C)
-
-#include "polarssl/entropy.h"
-#include "polarssl/entropy_poll.h"
-
-#if defined(POLARSSL_TIMING_C)
-#include "polarssl/timing.h"
-#endif
-#if defined(POLARSSL_HAVEGE_C)
-#include "polarssl/havege.h"
-#endif
-
-#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
-#if defined(_WIN32)
-
-#include <windows.h>
-#if !defined(_WIN32_WINNT)
-#define _WIN32_WINNT 0x0400
-#endif
-#include <wincrypt.h>
-
-int platform_entropy_poll( void *data, unsigned char *output, size_t len,
- size_t *olen )
-{
- HCRYPTPROV provider;
- ((void) data);
- *olen = 0;
-
- if( CryptAcquireContext( &provider, NULL, NULL,
- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
- {
- return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
- }
-
- if( CryptGenRandom( provider, len, output ) == FALSE )
- return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
-
- CryptReleaseContext( provider, 0 );
- *olen = len;
-
- return( 0 );
-}
-#else
-
-#include <stdio.h>
-
-int platform_entropy_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- FILE *file;
- size_t ret;
- ((void) data);
-
- *olen = 0;
-
- file = fopen( "/dev/urandom", "rb" );
- if( file == NULL )
- return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
-
- ret = fread( output, 1, len, file );
- if( ret != len )
- {
- fclose( file );
- return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
- }
-
- fclose( file );
- *olen = len;
-
- return( 0 );
-}
-#endif
-#endif
-
-#if defined(POLARSSL_TIMING_C)
-int hardclock_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- unsigned long timer = hardclock();
- ((void) data);
- *olen = 0;
-
- if( len < sizeof(unsigned long) )
- return( 0 );
-
- memcpy( output, &timer, sizeof(unsigned long) );
- *olen = sizeof(unsigned long);
-
- return( 0 );
-}
-#endif
-
-#if defined(POLARSSL_HAVEGE_C)
-int havege_poll( void *data,
- unsigned char *output, size_t len, size_t *olen )
-{
- havege_state *hs = (havege_state *) data;
- *olen = 0;
-
- if( havege_random( hs, output, len ) != 0 )
- return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
-
- *olen = len;
-
- return( 0 );
-}
-#endif
-
-#endif /* POLARSSL_ENTROPY_C */
diff --git a/polarssl/src/library/error.c b/polarssl/src/library/error.c
deleted file mode 100644
index 61ff9c7..0000000
--- a/polarssl/src/library/error.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Error message information
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_ERROR_C)
-
-#if defined(POLARSSL_AES_C)
-#include "polarssl/aes.h"
-#endif
-
-#if defined(POLARSSL_BASE64_C)
-#include "polarssl/base64.h"
-#endif
-
-#if defined(POLARSSL_BIGNUM_C)
-#include "polarssl/bignum.h"
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-#include "polarssl/camellia.h"
-#endif
-
-#if defined(POLARSSL_CIPHER_C)
-#include "polarssl/cipher.h"
-#endif
-
-#if defined(POLARSSL_CTR_DRBG_C)
-#include "polarssl/ctr_drbg.h"
-#endif
-
-#if defined(POLARSSL_DES_C)
-#include "polarssl/des.h"
-#endif
-
-#if defined(POLARSSL_DHM_C)
-#include "polarssl/dhm.h"
-#endif
-
-#if defined(POLARSSL_ENTROPY_C)
-#include "polarssl/entropy.h"
-#endif
-
-#if defined(POLARSSL_GCM_C)
-#include "polarssl/gcm.h"
-#endif
-
-#if defined(POLARSSL_MD_C)
-#include "polarssl/md.h"
-#endif
-
-#if defined(POLARSSL_MD2_C)
-#include "polarssl/md2.h"
-#endif
-
-#if defined(POLARSSL_MD4_C)
-#include "polarssl/md4.h"
-#endif
-
-#if defined(POLARSSL_MD5_C)
-#include "polarssl/md5.h"
-#endif
-
-#if defined(POLARSSL_NET_C)
-#include "polarssl/net.h"
-#endif
-
-#if defined(POLARSSL_PADLOCK_C)
-#include "polarssl/padlock.h"
-#endif
-
-#if defined(POLARSSL_PEM_C)
-#include "polarssl/pem.h"
-#endif
-
-#if defined(POLARSSL_RSA_C)
-#include "polarssl/rsa.h"
-#endif
-
-#if defined(POLARSSL_SHA1_C)
-#include "polarssl/sha1.h"
-#endif
-
-#if defined(POLARSSL_SHA2_C)
-#include "polarssl/sha2.h"
-#endif
-
-#if defined(POLARSSL_SHA4_C)
-#include "polarssl/sha4.h"
-#endif
-
-#if defined(POLARSSL_SSL_TLS_C)
-#include "polarssl/ssl.h"
-#endif
-
-#if defined(POLARSSL_X509_PARSE_C)
-#include "polarssl/x509.h"
-#endif
-
-#if defined(POLARSSL_XTEA_C)
-#include "polarssl/xtea.h"
-#endif
-
-
-#include <string.h>
-
-#if defined _MSC_VER && !defined snprintf
-#define snprintf _snprintf
-#endif
-
-void error_strerror( int ret, char *buf, size_t buflen )
-{
- size_t len;
- int use_ret;
-
- memset( buf, 0x00, buflen );
-
- if( ret < 0 )
- ret = -ret;
-
- if( ret & 0xFF80 )
- {
- use_ret = ret & 0xFF80;
-
- // High level error codes
- //
-#if defined(POLARSSL_CIPHER_C)
- if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) )
- snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
- if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) )
- snprintf( buf, buflen, "CIPHER - Bad input parameters to function" );
- if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) )
- snprintf( buf, buflen, "CIPHER - Failed to allocate memory" );
- if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) )
- snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" );
- if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) )
- snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" );
-#endif /* POLARSSL_CIPHER_C */
-
-#if defined(POLARSSL_DHM_C)
- if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) )
- snprintf( buf, buflen, "DHM - Bad input parameters to function" );
- if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) )
- snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" );
- if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) )
- snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" );
- if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) )
- snprintf( buf, buflen, "DHM - Reading of the public values failed" );
- if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) )
- snprintf( buf, buflen, "DHM - Makeing of the public value failed" );
- if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
- snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
-#endif /* POLARSSL_DHM_C */
-
-#if defined(POLARSSL_MD_C)
- if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) )
- snprintf( buf, buflen, "MD - The selected feature is not available" );
- if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) )
- snprintf( buf, buflen, "MD - Bad input parameters to function" );
- if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) )
- snprintf( buf, buflen, "MD - Failed to allocate memory" );
- if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) )
- snprintf( buf, buflen, "MD - Opening or reading of file failed" );
-#endif /* POLARSSL_MD_C */
-
-#if defined(POLARSSL_PEM_C)
- if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_PRESENT) )
- snprintf( buf, buflen, "PEM - No PEM header found" );
- if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) )
- snprintf( buf, buflen, "PEM - PEM string is not as expected" );
- if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) )
- snprintf( buf, buflen, "PEM - Failed to allocate memory" );
- if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) )
- snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" );
- if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) )
- snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" );
- if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) )
- snprintf( buf, buflen, "PEM - Private key password can't be empty" );
- if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) )
- snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" );
- if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) )
- snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" );
-#endif /* POLARSSL_PEM_C */
-
-#if defined(POLARSSL_RSA_C)
- if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) )
- snprintf( buf, buflen, "RSA - Bad input parameters to function" );
- if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) )
- snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" );
- if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) )
- snprintf( buf, buflen, "RSA - Something failed during generation of a key" );
- if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) )
- snprintf( buf, buflen, "RSA - Key failed to pass the libraries validity check" );
- if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) )
- snprintf( buf, buflen, "RSA - The public key operation failed" );
- if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) )
- snprintf( buf, buflen, "RSA - The private key operation failed" );
- if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) )
- snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" );
- if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) )
- snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
- if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) )
- snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" );
-#endif /* POLARSSL_RSA_C */
-
-#if defined(POLARSSL_SSL_TLS_C)
- if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) )
- snprintf( buf, buflen, "SSL - The requested feature is not available" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) )
- snprintf( buf, buflen, "SSL - Bad input parameters to function" );
- if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) )
- snprintf( buf, buflen, "SSL - Verification of the message MAC failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) )
- snprintf( buf, buflen, "SSL - An invalid SSL record was received" );
- if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) )
- snprintf( buf, buflen, "SSL - The connection indicated an EOF" );
- if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) )
- snprintf( buf, buflen, "SSL - An unknown cipher was received" );
- if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) )
- snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" );
- if( use_ret == -(POLARSSL_ERR_SSL_NO_SESSION_FOUND) )
- snprintf( buf, buflen, "SSL - No session to recover was found" );
- if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) )
- snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" );
- if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) )
- snprintf( buf, buflen, "SSL - DESCRIPTION MISSING" );
- if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) )
- snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" );
- if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) )
- snprintf( buf, buflen, "SSL - The own private key is not set, but needed" );
- if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) )
- snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" );
- if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) )
- snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" );
- if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) )
- snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" );
- if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) )
- snprintf( buf, buflen, "SSL - Verification of our peer failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) )
- snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) )
- snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) )
- snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) )
- snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) )
- snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) )
- snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) )
- snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) )
- snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP) )
- snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Read Public" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS) )
- snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) )
- snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) )
- snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) )
- snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" );
- if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) )
- snprintf( buf, buflen, "SSL - Memory allocation failed" );
-#endif /* POLARSSL_SSL_TLS_C */
-
-#if defined(POLARSSL_X509_PARSE_C)
- if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) )
- snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PEM) )
- snprintf( buf, buflen, "X509 - The PEM-encoded certificate contains invalid elements, e.g. invalid character" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_FORMAT) )
- snprintf( buf, buflen, "X509 - The certificate format is invalid, e.g. different type expected" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_VERSION) )
- snprintf( buf, buflen, "X509 - The certificate version element is invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SERIAL) )
- snprintf( buf, buflen, "X509 - The serial tag or value is invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_ALG) )
- snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_NAME) )
- snprintf( buf, buflen, "X509 - The name tag or value is invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_DATE) )
- snprintf( buf, buflen, "X509 - The date tag or value is invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PUBKEY) )
- snprintf( buf, buflen, "X509 - The pubkey tag or value is invalid (only RSA is supported)" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE) )
- snprintf( buf, buflen, "X509 - The signature tag or value invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS) )
- snprintf( buf, buflen, "X509 - The extension tag or value is invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION) )
- snprintf( buf, buflen, "X509 - Certificate or CRL has an unsupported version number" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG) )
- snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" );
- if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_PK_ALG) )
- snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA is supported)" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_SIG_MISMATCH) )
- snprintf( buf, buflen, "X509 - Certificate signature algorithms do not match. (see \\c ::x509_cert sig_oid)" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) )
- snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
- if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_VERSION) )
- snprintf( buf, buflen, "X509 - Unsupported RSA key version" );
- if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_FORMAT) )
- snprintf( buf, buflen, "X509 - Invalid RSA key tag or value" );
- if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) )
- snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" );
- if( use_ret == -(POLARSSL_ERR_X509_INVALID_INPUT) )
- snprintf( buf, buflen, "X509 - Input invalid" );
- if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) )
- snprintf( buf, buflen, "X509 - Allocation of memory failed" );
- if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) )
- snprintf( buf, buflen, "X509 - Read/write of file failed" );
-#endif /* POLARSSL_X509_PARSE_C */
-
- if( strlen( buf ) == 0 )
- snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
- }
-
- use_ret = ret & ~0xFF80;
-
- if( use_ret == 0 )
- return;
-
- // If high level code is present, make a concatenation between both
- // error strings.
- //
- len = strlen( buf );
-
- if( len > 0 )
- {
- if( buflen - len < 5 )
- return;
-
- snprintf( buf + len, buflen - len, " : " );
-
- buf += len + 3;
- buflen -= len + 3;
- }
-
- // Low level error codes
- //
-#if defined(POLARSSL_AES_C)
- if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) )
- snprintf( buf, buflen, "AES - Invalid key length" );
- if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) )
- snprintf( buf, buflen, "AES - Invalid data input length" );
-#endif /* POLARSSL_AES_C */
-
-#if defined(POLARSSL_ASN1_PARSE_C)
- if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) )
- snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
- if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) )
- snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" );
- if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) )
- snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" );
- if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) )
- snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
- if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) )
- snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
- if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) )
- snprintf( buf, buflen, "ASN1 - Memory allocation failed" );
- if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) )
- snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" );
-#endif /* POLARSSL_ASN1_PARSE_C */
-
-#if defined(POLARSSL_BASE64_C)
- if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) )
- snprintf( buf, buflen, "BASE64 - Output buffer too small" );
- if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) )
- snprintf( buf, buflen, "BASE64 - Invalid character in input" );
-#endif /* POLARSSL_BASE64_C */
-
-#if defined(POLARSSL_BIGNUM_C)
- if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) )
- snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" );
- if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) )
- snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" );
- if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) )
- snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" );
- if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) )
- snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" );
- if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) )
- snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" );
- if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) )
- snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" );
- if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) )
- snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" );
- if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) )
- snprintf( buf, buflen, "BIGNUM - Memory allocation failed" );
-#endif /* POLARSSL_BIGNUM_C */
-
-#if defined(POLARSSL_CAMELLIA_C)
- if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) )
- snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
- if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
- snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
-#endif /* POLARSSL_CAMELLIA_C */
-
-#if defined(POLARSSL_CTR_DRBG_C)
- if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) )
- snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" );
- if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) )
- snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" );
- if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) )
- snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" );
- if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) )
- snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" );
-#endif /* POLARSSL_CTR_DRBG_C */
-
-#if defined(POLARSSL_DES_C)
- if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) )
- snprintf( buf, buflen, "DES - The data input has an invalid length" );
-#endif /* POLARSSL_DES_C */
-
-#if defined(POLARSSL_ENTROPY_C)
- if( use_ret == -(POLARSSL_ERR_ENTROPY_SOURCE_FAILED) )
- snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" );
- if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) )
- snprintf( buf, buflen, "ENTROPY - No more sources can be added" );
- if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) )
- snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" );
-#endif /* POLARSSL_ENTROPY_C */
-
-#if defined(POLARSSL_GCM_C)
- if( use_ret == -(POLARSSL_ERR_GCM_AUTH_FAILED) )
- snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
- if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) )
- snprintf( buf, buflen, "GCM - Bad input parameters to function" );
-#endif /* POLARSSL_GCM_C */
-
-#if defined(POLARSSL_MD2_C)
- if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) )
- snprintf( buf, buflen, "MD2 - Read/write error in file" );
-#endif /* POLARSSL_MD2_C */
-
-#if defined(POLARSSL_MD4_C)
- if( use_ret == -(POLARSSL_ERR_MD4_FILE_IO_ERROR) )
- snprintf( buf, buflen, "MD4 - Read/write error in file" );
-#endif /* POLARSSL_MD4_C */
-
-#if defined(POLARSSL_MD5_C)
- if( use_ret == -(POLARSSL_ERR_MD5_FILE_IO_ERROR) )
- snprintf( buf, buflen, "MD5 - Read/write error in file" );
-#endif /* POLARSSL_MD5_C */
-
-#if defined(POLARSSL_NET_C)
- if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) )
- snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" );
- if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) )
- snprintf( buf, buflen, "NET - Failed to open a socket" );
- if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) )
- snprintf( buf, buflen, "NET - The connection to the given server / port failed" );
- if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) )
- snprintf( buf, buflen, "NET - Binding of the socket failed" );
- if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) )
- snprintf( buf, buflen, "NET - Could not listen on the socket" );
- if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) )
- snprintf( buf, buflen, "NET - Could not accept the incoming connection" );
- if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) )
- snprintf( buf, buflen, "NET - Reading information from the socket failed" );
- if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) )
- snprintf( buf, buflen, "NET - Sending information through the socket failed" );
- if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) )
- snprintf( buf, buflen, "NET - Connection was reset by peer" );
- if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) )
- snprintf( buf, buflen, "NET - Connection requires a read call" );
- if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) )
- snprintf( buf, buflen, "NET - Connection requires a write call" );
-#endif /* POLARSSL_NET_C */
-
-#if defined(POLARSSL_PADLOCK_C)
- if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) )
- snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
-#endif /* POLARSSL_PADLOCK_C */
-
-#if defined(POLARSSL_SHA1_C)
- if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) )
- snprintf( buf, buflen, "SHA1 - Read/write error in file" );
-#endif /* POLARSSL_SHA1_C */
-
-#if defined(POLARSSL_SHA2_C)
- if( use_ret == -(POLARSSL_ERR_SHA2_FILE_IO_ERROR) )
- snprintf( buf, buflen, "SHA2 - Read/write error in file" );
-#endif /* POLARSSL_SHA2_C */
-
-#if defined(POLARSSL_SHA4_C)
- if( use_ret == -(POLARSSL_ERR_SHA4_FILE_IO_ERROR) )
- snprintf( buf, buflen, "SHA4 - Read/write error in file" );
-#endif /* POLARSSL_SHA4_C */
-
-#if defined(POLARSSL_XTEA_C)
- if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) )
- snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
-#endif /* POLARSSL_XTEA_C */
-
- if( strlen( buf ) != 0 )
- return;
-
- snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
-}
-
-#endif /* POLARSSL_VERBOSE_ERROR */
diff --git a/polarssl/src/library/gcm.c b/polarssl/src/library/gcm.c
deleted file mode 100644
index 616f724..0000000
--- a/polarssl/src/library/gcm.c
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * NIST SP800-38D compliant GCM implementation
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
- */
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_GCM_C)
-
-#include "polarssl/gcm.h"
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) ); \
-}
-#endif
-
-static void gcm_gen_table( gcm_context *ctx )
-{
- int i, j;
- uint64_t hi, lo;
- uint64_t vl, vh;
- unsigned char h[16];
-
- memset( h, 0, 16 );
- aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, h, h );
-
- ctx->HH[0] = 0;
- ctx->HL[0] = 0;
-
- GET_ULONG_BE( hi, h, 0 );
- GET_ULONG_BE( lo, h, 4 );
- vh = (uint64_t) hi << 32 | lo;
-
- GET_ULONG_BE( hi, h, 8 );
- GET_ULONG_BE( lo, h, 12 );
- vl = (uint64_t) hi << 32 | lo;
-
- ctx->HL[8] = vl;
- ctx->HH[8] = vh;
-
- for( i = 4; i > 0; i >>= 1 )
- {
- uint32_t T = ( vl & 1 ) ? 0xe1000000U : 0;
- vl = ( vh << 63 ) | ( vl >> 1 );
- vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
-
- ctx->HL[i] = vl;
- ctx->HH[i] = vh;
- }
-
- for (i = 2; i < 16; i <<= 1 )
- {
- uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
- vh = *HiH;
- vl = *HiL;
- for( j = 1; j < i; j++ )
- {
- HiH[j] = vh ^ ctx->HH[j];
- HiL[j] = vl ^ ctx->HL[j];
- }
- }
-
-}
-
-int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize )
-{
- int ret;
-
- memset( ctx, 0, sizeof(gcm_context) );
-
- if( ( ret = aes_setkey_enc( &ctx->aes_ctx, key, keysize ) ) != 0 )
- return( ret );
-
- gcm_gen_table( ctx );
-
- return( 0 );
-}
-
-static const uint64_t last4[16] =
-{
- 0x0000, 0x1c20, 0x3840, 0x2460,
- 0x7080, 0x6ca0, 0x48c0, 0x54e0,
- 0xe100, 0xfd20, 0xd940, 0xc560,
- 0x9180, 0x8da0, 0xa9c0, 0xb5e0
-};
-
-void gcm_mult( gcm_context *ctx, const unsigned char x[16], unsigned char output[16] )
-{
- int i = 0;
- unsigned char z[16];
- unsigned char v[16];
- unsigned char lo, hi, rem;
- uint64_t zh, zl;
-
- memset( z, 0x00, 16 );
- memcpy( v, x, 16 );
-
- lo = x[15] & 0xf;
- hi = x[15] >> 4;
-
- zh = ctx->HH[lo];
- zl = ctx->HL[lo];
-
- for( i = 15; i >= 0; i-- )
- {
- lo = x[i] & 0xf;
- hi = x[i] >> 4;
-
- if( i != 15 )
- {
- rem = zl & 0xf;
- zl = ( zh << 60 ) | ( zl >> 4 );
- zh = ( zh >> 4 );
- zh ^= (uint64_t) last4[rem] << 48;
- zh ^= ctx->HH[lo];
- zl ^= ctx->HL[lo];
-
- }
-
- rem = zl & 0xf;
- zl = ( zh << 60 ) | ( zl >> 4 );
- zh = ( zh >> 4 );
- zh ^= (uint64_t) last4[rem] << 48;
- zh ^= ctx->HH[hi];
- zl ^= ctx->HL[hi];
- }
-
- PUT_ULONG_BE( zh >> 32, output, 0 );
- PUT_ULONG_BE( zh, output, 4 );
- PUT_ULONG_BE( zl >> 32, output, 8 );
- PUT_ULONG_BE( zl, output, 12 );
-}
-
-int gcm_crypt_and_tag( gcm_context *ctx,
- int mode,
- size_t length,
- const unsigned char *iv,
- size_t iv_len,
- const unsigned char *add,
- size_t add_len,
- const unsigned char *input,
- unsigned char *output,
- size_t tag_len,
- unsigned char *tag )
-{
- unsigned char y[16];
- unsigned char ectr[16];
- unsigned char buf[16];
- unsigned char work_buf[16];
- size_t i;
- const unsigned char *p;
- unsigned char *out_p = output;
- size_t use_len;
- size_t orig_len = length * 8;
- size_t orig_add_len = add_len * 8;
- unsigned char **xor_p;
-
- memset( y, 0x00, 16 );
- memset( work_buf, 0x00, 16 );
- memset( tag, 0x00, tag_len );
- memset( buf, 0x00, 16 );
-
- if( ( mode == GCM_DECRYPT && output <= input && ( input - output ) < 8 ) ||
- ( output > input && (size_t) ( output - input ) < length ) )
- {
- return( POLARSSL_ERR_GCM_BAD_INPUT );
- }
-
- if( mode == GCM_ENCRYPT )
- xor_p = (unsigned char **) &out_p;
- else
- xor_p = (unsigned char **) &p;
-
- if( iv_len == 12 )
- {
- memcpy( y, iv, iv_len );
- y[15] = 1;
- }
- else
- {
- memset( work_buf, 0x00, 16 );
- PUT_ULONG_BE( iv_len * 8, work_buf, 12 );
-
- p = iv;
- while( iv_len > 0 )
- {
- use_len = ( iv_len < 16 ) ? iv_len : 16;
-
- if( use_len == 16 )
- {
- ((uint64_t *) y)[0] ^= ((uint64_t *) p)[0];
- ((uint64_t *) y)[1] ^= ((uint64_t *) p)[1];
- }
- else
- for( i = 0; i < use_len; i++ )
- y[i] ^= p[i];
-
- gcm_mult( ctx, y, y );
-
- iv_len -= use_len;
- p += use_len;
- }
-
- ((uint64_t *) y)[0] ^= ((uint64_t *) work_buf)[0];
- ((uint64_t *) y)[1] ^= ((uint64_t *) work_buf)[1];
-
- gcm_mult( ctx, y, y );
- }
-
- aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
- memcpy( tag, ectr, tag_len );
-
- p = add;
- while( add_len > 0 )
- {
- use_len = ( add_len < 16 ) ? add_len : 16;
-
- if( use_len == 16 )
- {
- ((uint64_t *) buf)[0] ^= ((uint64_t *) p)[0];
- ((uint64_t *) buf)[1] ^= ((uint64_t *) p)[1];
- }
- else
- for( i = 0; i < use_len; i++ )
- buf[i] ^= p[i];
-
- gcm_mult( ctx, buf, buf );
-
- add_len -= use_len;
- p += use_len;
- }
-
- p = input;
- while( length > 0 )
- {
- use_len = ( length < 16 ) ? length : 16;
-
- for( i = 16; i > 0; i-- )
- if( ++y[i - 1] != 0 )
- break;
-
- aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
-
- if( use_len == 16 )
- {
- ((uint64_t *) out_p)[0] = ((uint64_t *) ectr)[0] ^
- ((uint64_t *) p)[0];
- ((uint64_t *) buf)[0] ^= ((uint64_t *) (*xor_p))[0];
-
- ((uint64_t *) out_p)[1] = ((uint64_t *) ectr)[1] ^
- ((uint64_t *) p)[1];
- ((uint64_t *) buf)[1] ^= ((uint64_t *) (*xor_p))[1];
- }
- else
- for( i = 0; i < use_len; i++ )
- {
- out_p[i] = ectr[i] ^ p[i];
- buf[i] ^= (*xor_p)[i];
- }
-
- gcm_mult( ctx, buf, buf );
-
- length -= use_len;
- p += use_len;
- out_p += use_len;
- }
-
- if( orig_len || orig_add_len )
- {
- memset( work_buf, 0x00, 16 );
-
- PUT_ULONG_BE( orig_add_len , work_buf, 4 );
- PUT_ULONG_BE( orig_len , work_buf, 12 );
-
- ((uint64_t *) buf)[0] ^= ((uint64_t *) work_buf)[0];
- ((uint64_t *) buf)[1] ^= ((uint64_t *) work_buf)[1];
-
- gcm_mult( ctx, buf, buf );
-
- if( tag_len == 16 )
- {
- ((uint64_t *) tag)[0] ^= ((uint64_t *) buf)[0];
- ((uint64_t *) tag)[1] ^= ((uint64_t *) buf)[1];
- }
- else
- for( i = 0; i < tag_len; i++ )
- tag[i] ^= buf[i];
- }
-
- return( 0 );
-}
-
-int gcm_auth_decrypt( gcm_context *ctx,
- size_t length,
- const unsigned char *iv,
- size_t iv_len,
- const unsigned char *add,
- size_t add_len,
- const unsigned char *tag,
- size_t tag_len,
- const unsigned char *input,
- unsigned char *output )
-{
- unsigned char check_tag[16];
-
- gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag );
-
- if( memcmp( check_tag, tag, tag_len ) == 0 )
- return( 0 );
-
- memset( output, 0, length );
-
- return( POLARSSL_ERR_GCM_AUTH_FAILED );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <stdio.h>
-
-/*
- * GCM test vectors from:
- *
- * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
- */
-#define MAX_TESTS 6
-
-int key_index[MAX_TESTS] =
- { 0, 0, 1, 1, 1, 1 };
-
-unsigned char key[MAX_TESTS][32] =
-{
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
-};
-
-size_t iv_len[MAX_TESTS] =
- { 12, 12, 12, 12, 8, 60 };
-
-int iv_index[MAX_TESTS] =
- { 0, 0, 1, 1, 1, 2 };
-
-unsigned char iv[MAX_TESTS][64] =
-{
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00 },
- { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
- 0xde, 0xca, 0xf8, 0x88 },
- { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
- 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
- 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
- 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
- 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
- 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
- 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
- 0xa6, 0x37, 0xb3, 0x9b },
-};
-
-size_t add_len[MAX_TESTS] =
- { 0, 0, 0, 20, 20, 20 };
-
-int add_index[MAX_TESTS] =
- { 0, 0, 0, 1, 1, 1 };
-
-unsigned char additional[MAX_TESTS][64] =
-{
- { 0x00 },
- { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
- 0xab, 0xad, 0xda, 0xd2 },
-};
-
-size_t pt_len[MAX_TESTS] =
- { 0, 16, 64, 60, 60, 60 };
-
-int pt_index[MAX_TESTS] =
- { 0, 0, 1, 1, 1, 1 };
-
-unsigned char pt[MAX_TESTS][64] =
-{
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
- 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
-};
-
-unsigned char ct[MAX_TESTS * 3][64] =
-{
- { 0x00 },
- { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
- 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
- { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
- 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
- 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
- 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
- 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
- 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
- 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
- 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
- { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
- 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
- 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
- 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
- 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
- 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
- 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
- 0x3d, 0x58, 0xe0, 0x91 },
- { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
- 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
- 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
- 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
- 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
- 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
- 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
- 0xc2, 0x3f, 0x45, 0x98 },
- { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
- 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
- 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
- 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
- 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
- 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
- 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
- 0x4c, 0x34, 0xae, 0xe5 },
- { 0x00 },
- { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
- 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
- { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
- 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
- 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
- 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
- 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
- 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
- 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
- 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
- { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
- 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
- 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
- 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
- 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
- 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
- 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
- 0xcc, 0xda, 0x27, 0x10 },
- { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
- 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
- 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
- 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
- 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
- 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
- 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
- 0xa0, 0xf0, 0x62, 0xf7 },
- { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
- 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
- 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
- 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
- 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
- 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
- 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
- 0xe9, 0xb7, 0x37, 0x3b },
- { 0x00 },
- { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
- 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
- { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
- 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
- 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
- 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
- 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
- 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
- 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
- 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
- { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
- 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
- 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
- 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
- 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
- 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
- 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
- 0xbc, 0xc9, 0xf6, 0x62 },
- { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
- 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
- 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
- 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
- 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
- 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
- 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
- 0xf4, 0x7c, 0x9b, 0x1f },
- { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
- 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
- 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
- 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
- 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
- 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
- 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
- 0x44, 0xae, 0x7e, 0x3f },
-};
-
-unsigned char tag[MAX_TESTS * 3][16] =
-{
- { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
- 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
- { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
- 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
- { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
- 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
- { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
- 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
- { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
- 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
- { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
- 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
- { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
- 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
- { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
- 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
- { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
- 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
- { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
- 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
- { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
- 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
- { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
- 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
- { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
- 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
- { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
- 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
- { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
- 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
- { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
- 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
- { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
- 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
- { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
- 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
-};
-
-int gcm_self_test( int verbose )
-{
- gcm_context ctx;
- unsigned char buf[64];
- unsigned char tag_buf[16];
- int i, j, ret;
-
- for( j = 0; j < 3; j++ )
- {
- int key_len = 128 + 64 * j;
-
- for( i = 0; i < MAX_TESTS; i++ )
- {
- printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
- gcm_init( &ctx, key[key_index[i]], key_len );
-
- ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
- pt_len[i],
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i],
- pt[pt_index[i]], buf, 16, tag_buf );
-
- if( ret != 0 ||
- memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
- memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
-
- printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
- gcm_init( &ctx, key[key_index[i]], key_len );
-
- ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
- pt_len[i],
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i],
- ct[j * 6 + i], buf, 16, tag_buf );
-
- if( ret != 0 ||
- memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
- memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
- }
-
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/havege.c b/polarssl/src/library/havege.c
deleted file mode 100644
index ff302c5..0000000
--- a/polarssl/src/library/havege.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/**
- * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The HAVEGE RNG was designed by Andre Seznec in 2002.
- *
- * http://www.irisa.fr/caps/projects/hipsor/publi.php
- *
- * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_HAVEGE_C)
-
-#include "polarssl/havege.h"
-#include "polarssl/timing.h"
-
-#include <string.h>
-#include <time.h>
-
-/* ------------------------------------------------------------------------
- * On average, one iteration accesses two 8-word blocks in the havege WALK
- * table, and generates 16 words in the RES array.
- *
- * The data read in the WALK table is updated and permuted after each use.
- * The result of the hardware clock counter read is used for this update.
- *
- * 25 conditional tests are present. The conditional tests are grouped in
- * two nested groups of 12 conditional tests and 1 test that controls the
- * permutation; on average, there should be 6 tests executed and 3 of them
- * should be mispredicted.
- * ------------------------------------------------------------------------
- */
-
-#define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
-
-#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
-#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
-
-#define TST1_LEAVE U1++; }
-#define TST2_LEAVE U2++; }
-
-#define ONE_ITERATION \
- \
- PTEST = PT1 >> 20; \
- \
- TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
- TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
- TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
- \
- TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
- TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
- TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
- \
- PTX = (PT1 >> 18) & 7; \
- PT1 &= 0x1FFF; \
- PT2 &= 0x1FFF; \
- CLK = (int) hardclock(); \
- \
- i = 0; \
- A = &WALK[PT1 ]; RES[i++] ^= *A; \
- B = &WALK[PT2 ]; RES[i++] ^= *B; \
- C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
- D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
- \
- IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
- *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
- *B = IN ^ U1; \
- *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
- *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
- \
- A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
- B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
- C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
- D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
- \
- if( PTEST & 1 ) SWAP( A, C ); \
- \
- IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
- *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
- *B = IN; CLK = (int) hardclock(); \
- *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
- *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
- \
- A = &WALK[PT1 ^ 4]; \
- B = &WALK[PT2 ^ 1]; \
- \
- PTEST = PT2 >> 1; \
- \
- PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
- PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
- PTY = (PT2 >> 10) & 7; \
- \
- TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
- TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
- TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
- \
- TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
- TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
- TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
- \
- C = &WALK[PT1 ^ 5]; \
- D = &WALK[PT2 ^ 5]; \
- \
- RES[i++] ^= *A; \
- RES[i++] ^= *B; \
- RES[i++] ^= *C; \
- RES[i++] ^= *D; \
- \
- IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
- *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
- *B = IN ^ U2; \
- *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
- *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
- \
- A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
- B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
- C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
- D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
- \
- IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
- *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
- *B = IN; \
- *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
- *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
- \
- PT1 = ( RES[(i - 8) ^ PTX] ^ \
- WALK[PT1 ^ PTX ^ 7] ) & (~1); \
- PT1 ^= (PT2 ^ 0x10) & 0x10; \
- \
- for( n++, i = 0; i < 16; i++ ) \
- hs->pool[n % COLLECT_SIZE] ^= RES[i];
-
-/*
- * Entropy gathering function
- */
-static void havege_fill( havege_state *hs )
-{
- int i, n = 0;
- int U1, U2, *A, *B, *C, *D;
- int PT1, PT2, *WALK, RES[16];
- int PTX, PTY, CLK, PTEST, IN;
-
- WALK = hs->WALK;
- PT1 = hs->PT1;
- PT2 = hs->PT2;
-
- PTX = U1 = 0;
- PTY = U2 = 0;
-
- memset( RES, 0, sizeof( RES ) );
-
- while( n < COLLECT_SIZE * 4 )
- {
- ONE_ITERATION
- ONE_ITERATION
- ONE_ITERATION
- ONE_ITERATION
- }
-
- hs->PT1 = PT1;
- hs->PT2 = PT2;
-
- hs->offset[0] = 0;
- hs->offset[1] = COLLECT_SIZE / 2;
-}
-
-/*
- * HAVEGE initialization
- */
-void havege_init( havege_state *hs )
-{
- memset( hs, 0, sizeof( havege_state ) );
-
- havege_fill( hs );
-}
-
-/*
- * HAVEGE rand function
- */
-int havege_random( void *p_rng, unsigned char *buf, size_t len )
-{
- int val;
- size_t use_len;
- havege_state *hs = (havege_state *) p_rng;
- unsigned char *p = buf;
-
- while( len > 0 )
- {
- use_len = len;
- if( use_len > sizeof(int) )
- use_len = sizeof(int);
-
- if( hs->offset[1] >= COLLECT_SIZE )
- havege_fill( hs );
-
- val = hs->pool[hs->offset[0]++];
- val ^= hs->pool[hs->offset[1]++];
-
- memcpy( p, &val, use_len );
-
- len -= use_len;
- p += use_len;
- }
-
- return( 0 );
-}
-
-#endif
diff --git a/polarssl/src/library/md.c b/polarssl/src/library/md.c
deleted file mode 100644
index 96065c9..0000000
--- a/polarssl/src/library/md.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/**
- * \file md.c
- *
- * \brief Generic message digest wrapper for PolarSSL
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_MD_C)
-
-#include "polarssl/md.h"
-#include "polarssl/md_wrap.h"
-
-#include <stdlib.h>
-
-#if defined _MSC_VER && !defined strcasecmp
-#define strcasecmp _stricmp
-#endif
-
-static const int supported_digests[] = {
-
-#if defined(POLARSSL_MD2_C)
- POLARSSL_MD_MD2,
-#endif
-
-#if defined(POLARSSL_MD4_C)
- POLARSSL_MD_MD4,
-#endif
-
-#if defined(POLARSSL_MD5_C)
- POLARSSL_MD_MD5,
-#endif
-
-#if defined(POLARSSL_SHA1_C)
- POLARSSL_MD_SHA1,
-#endif
-
-#if defined(POLARSSL_SHA2_C)
- POLARSSL_MD_SHA224,
- POLARSSL_MD_SHA256,
-#endif
-
-#if defined(POLARSSL_SHA4_C)
- POLARSSL_MD_SHA384,
- POLARSSL_MD_SHA512,
-#endif
-
- 0
-};
-
-const int *md_list( void )
-{
- return supported_digests;
-}
-
-const md_info_t *md_info_from_string( const char *md_name )
-{
- if( NULL == md_name )
- return NULL;
-
- /* Get the appropriate digest information */
-#if defined(POLARSSL_MD2_C)
- if( !strcasecmp( "MD2", md_name ) )
- return md_info_from_type( POLARSSL_MD_MD2 );
-#endif
-#if defined(POLARSSL_MD4_C)
- if( !strcasecmp( "MD4", md_name ) )
- return md_info_from_type( POLARSSL_MD_MD4 );
-#endif
-#if defined(POLARSSL_MD5_C)
- if( !strcasecmp( "MD5", md_name ) )
- return md_info_from_type( POLARSSL_MD_MD5 );
-#endif
-#if defined(POLARSSL_SHA1_C)
- if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) )
- return md_info_from_type( POLARSSL_MD_SHA1 );
-#endif
-#if defined(POLARSSL_SHA2_C)
- if( !strcasecmp( "SHA224", md_name ) )
- return md_info_from_type( POLARSSL_MD_SHA224 );
- if( !strcasecmp( "SHA256", md_name ) )
- return md_info_from_type( POLARSSL_MD_SHA256 );
-#endif
-#if defined(POLARSSL_SHA4_C)
- if( !strcasecmp( "SHA384", md_name ) )
- return md_info_from_type( POLARSSL_MD_SHA384 );
- if( !strcasecmp( "SHA512", md_name ) )
- return md_info_from_type( POLARSSL_MD_SHA512 );
-#endif
- return NULL;
-}
-
-const md_info_t *md_info_from_type( md_type_t md_type )
-{
- switch( md_type )
- {
-#if defined(POLARSSL_MD2_C)
- case POLARSSL_MD_MD2:
- return &md2_info;
-#endif
-#if defined(POLARSSL_MD4_C)
- case POLARSSL_MD_MD4:
- return &md4_info;
-#endif
-#if defined(POLARSSL_MD5_C)
- case POLARSSL_MD_MD5:
- return &md5_info;
-#endif
-#if defined(POLARSSL_SHA1_C)
- case POLARSSL_MD_SHA1:
- return &sha1_info;
-#endif
-#if defined(POLARSSL_SHA2_C)
- case POLARSSL_MD_SHA224:
- return &sha224_info;
- case POLARSSL_MD_SHA256:
- return &sha256_info;
-#endif
-#if defined(POLARSSL_SHA4_C)
- case POLARSSL_MD_SHA384:
- return &sha384_info;
- case POLARSSL_MD_SHA512:
- return &sha512_info;
-#endif
- default:
- return NULL;
- }
-}
-
-int md_init_ctx( md_context_t *ctx, const md_info_t *md_info )
-{
- if( md_info == NULL || ctx == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- memset( ctx, 0, sizeof( md_context_t ) );
-
- if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
- return POLARSSL_ERR_MD_ALLOC_FAILED;
-
- ctx->md_info = md_info;
-
- md_info->starts_func( ctx->md_ctx );
-
- return 0;
-}
-
-int md_free_ctx( md_context_t *ctx )
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->ctx_free_func( ctx->md_ctx );
- ctx->md_ctx = NULL;
-
- return 0;
-}
-
-int md_starts( md_context_t *ctx )
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->starts_func( ctx->md_ctx );
-
- return 0;
-}
-
-int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->update_func( ctx->md_ctx, input, ilen );
-
- return 0;
-}
-
-int md_finish( md_context_t *ctx, unsigned char *output )
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->finish_func( ctx->md_ctx, output );
-
- return 0;
-}
-
-int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- if ( md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- md_info->digest_func( input, ilen, output );
-
- return 0;
-}
-
-int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- int ret;
-#endif
-
- if( md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
-#if defined(POLARSSL_FS_IO)
- ret = md_info->file_func( path, output );
- if( ret != 0 )
- return( POLARSSL_ERR_MD_FILE_IO_ERROR + ret );
-
- return( ret );
-#else
- ((void) path);
- ((void) output);
-
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen )
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen);
-
- return 0;
-}
-
-int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen );
-
- return 0;
-}
-
-int md_hmac_finish( md_context_t *ctx, unsigned char *output)
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->hmac_finish_func( ctx->md_ctx, output);
-
- return 0;
-}
-
-int md_hmac_reset( md_context_t *ctx )
-{
- if( ctx == NULL || ctx->md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- ctx->md_info->hmac_reset_func( ctx->md_ctx);
-
- return 0;
-}
-
-int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- if( md_info == NULL )
- return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
- md_info->hmac_func( key, keylen, input, ilen, output );
-
- return 0;
-}
-
-#endif
diff --git a/polarssl/src/library/md2.c b/polarssl/src/library/md2.c
deleted file mode 100644
index 954aa07..0000000
--- a/polarssl/src/library/md2.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * RFC 1115/1319 compliant MD2 implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The MD2 algorithm was designed by Ron Rivest in 1989.
- *
- * http://www.ietf.org/rfc/rfc1115.txt
- * http://www.ietf.org/rfc/rfc1319.txt
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_MD2_C)
-
-#include "polarssl/md2.h"
-
-#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
-#include <stdio.h>
-#endif
-
-static const unsigned char PI_SUBST[256] =
-{
- 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
- 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
- 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
- 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
- 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
- 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
- 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
- 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
- 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
- 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
- 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
- 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
- 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
- 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
- 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
- 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
- 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
- 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
- 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
- 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
- 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
- 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
- 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
- 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
- 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
- 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
-};
-
-/*
- * MD2 context setup
- */
-void md2_starts( md2_context *ctx )
-{
- memset( ctx->cksum, 0, 16 );
- memset( ctx->state, 0, 46 );
- memset( ctx->buffer, 0, 16 );
- ctx->left = 0;
-}
-
-static void md2_process( md2_context *ctx )
-{
- int i, j;
- unsigned char t = 0;
-
- for( i = 0; i < 16; i++ )
- {
- ctx->state[i + 16] = ctx->buffer[i];
- ctx->state[i + 32] =
- (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
- }
-
- for( i = 0; i < 18; i++ )
- {
- for( j = 0; j < 48; j++ )
- {
- ctx->state[j] = (unsigned char)
- ( ctx->state[j] ^ PI_SUBST[t] );
- t = ctx->state[j];
- }
-
- t = (unsigned char)( t + i );
- }
-
- t = ctx->cksum[15];
-
- for( i = 0; i < 16; i++ )
- {
- ctx->cksum[i] = (unsigned char)
- ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
- t = ctx->cksum[i];
- }
-}
-
-/*
- * MD2 process buffer
- */
-void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen )
-{
- size_t fill;
-
- while( ilen > 0 )
- {
- if( ctx->left + ilen > 16 )
- fill = 16 - ctx->left;
- else
- fill = ilen;
-
- memcpy( ctx->buffer + ctx->left, input, fill );
-
- ctx->left += fill;
- input += fill;
- ilen -= fill;
-
- if( ctx->left == 16 )
- {
- ctx->left = 0;
- md2_process( ctx );
- }
- }
-}
-
-/*
- * MD2 final digest
- */
-void md2_finish( md2_context *ctx, unsigned char output[16] )
-{
- size_t i;
- unsigned char x;
-
- x = (unsigned char)( 16 - ctx->left );
-
- for( i = ctx->left; i < 16; i++ )
- ctx->buffer[i] = x;
-
- md2_process( ctx );
-
- memcpy( ctx->buffer, ctx->cksum, 16 );
- md2_process( ctx );
-
- memcpy( output, ctx->state, 16 );
-}
-
-/*
- * output = MD2( input buffer )
- */
-void md2( const unsigned char *input, size_t ilen, unsigned char output[16] )
-{
- md2_context ctx;
-
- md2_starts( &ctx );
- md2_update( &ctx, input, ilen );
- md2_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md2_context ) );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * output = MD2( file contents )
- */
-int md2_file( const char *path, unsigned char output[16] )
-{
- FILE *f;
- size_t n;
- md2_context ctx;
- unsigned char buf[1024];
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
-
- md2_starts( &ctx );
-
- while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
- md2_update( &ctx, buf, n );
-
- md2_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md2_context ) );
-
- if( ferror( f ) != 0 )
- {
- fclose( f );
- return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
- }
-
- fclose( f );
- return( 0 );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * MD2 HMAC context setup
- */
-void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen )
-{
- size_t i;
- unsigned char sum[16];
-
- if( keylen > 16 )
- {
- md2( key, keylen, sum );
- keylen = 16;
- key = sum;
- }
-
- memset( ctx->ipad, 0x36, 16 );
- memset( ctx->opad, 0x5C, 16 );
-
- for( i = 0; i < keylen; i++ )
- {
- ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
- ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
- }
-
- md2_starts( ctx );
- md2_update( ctx, ctx->ipad, 16 );
-
- memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * MD2 HMAC process buffer
- */
-void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen )
-{
- md2_update( ctx, input, ilen );
-}
-
-/*
- * MD2 HMAC final digest
- */
-void md2_hmac_finish( md2_context *ctx, unsigned char output[16] )
-{
- unsigned char tmpbuf[16];
-
- md2_finish( ctx, tmpbuf );
- md2_starts( ctx );
- md2_update( ctx, ctx->opad, 16 );
- md2_update( ctx, tmpbuf, 16 );
- md2_finish( ctx, output );
-
- memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * MD2 HMAC context reset
- */
-void md2_hmac_reset( md2_context *ctx )
-{
- md2_starts( ctx );
- md2_update( ctx, ctx->ipad, 16 );
-}
-
-/*
- * output = HMAC-MD2( hmac key, input buffer )
- */
-void md2_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[16] )
-{
- md2_context ctx;
-
- md2_hmac_starts( &ctx, key, keylen );
- md2_hmac_update( &ctx, input, ilen );
- md2_hmac_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md2_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-/*
- * RFC 1319 test vectors
- */
-static const char md2_test_str[7][81] =
-{
- { "" },
- { "a" },
- { "abc" },
- { "message digest" },
- { "abcdefghijklmnopqrstuvwxyz" },
- { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
- { "12345678901234567890123456789012345678901234567890123456789012" \
- "345678901234567890" }
-};
-
-static const unsigned char md2_test_sum[7][16] =
-{
- { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
- 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
- { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
- 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
- { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
- 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
- { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
- 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
- { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
- 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
- { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
- 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
- { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
- 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
-};
-
-/*
- * Checkup routine
- */
-int md2_self_test( int verbose )
-{
- int i;
- unsigned char md2sum[16];
-
- for( i = 0; i < 7; i++ )
- {
- if( verbose != 0 )
- printf( " MD2 test #%d: ", i + 1 );
-
- md2( (unsigned char *) md2_test_str[i],
- strlen( md2_test_str[i] ), md2sum );
-
- if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/md4.c b/polarssl/src/library/md4.c
deleted file mode 100644
index ad52e5e..0000000
--- a/polarssl/src/library/md4.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * RFC 1186/1320 compliant MD4 implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The MD4 algorithm was designed by Ron Rivest in 1990.
- *
- * http://www.ietf.org/rfc/rfc1186.txt
- * http://www.ietf.org/rfc/rfc1320.txt
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_MD4_C)
-
-#include "polarssl/md4.h"
-
-#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
-#include <stdio.h>
-#endif
-
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_ULONG_LE
-#define GET_ULONG_LE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] ) \
- | ( (unsigned long) (b)[(i) + 1] << 8 ) \
- | ( (unsigned long) (b)[(i) + 2] << 16 ) \
- | ( (unsigned long) (b)[(i) + 3] << 24 ); \
-}
-#endif
-
-#ifndef PUT_ULONG_LE
-#define PUT_ULONG_LE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
-}
-#endif
-
-/*
- * MD4 context setup
- */
-void md4_starts( md4_context *ctx )
-{
- ctx->total[0] = 0;
- ctx->total[1] = 0;
-
- ctx->state[0] = 0x67452301;
- ctx->state[1] = 0xEFCDAB89;
- ctx->state[2] = 0x98BADCFE;
- ctx->state[3] = 0x10325476;
-}
-
-static void md4_process( md4_context *ctx, const unsigned char data[64] )
-{
- unsigned long X[16], A, B, C, D;
-
- GET_ULONG_LE( X[ 0], data, 0 );
- GET_ULONG_LE( X[ 1], data, 4 );
- GET_ULONG_LE( X[ 2], data, 8 );
- GET_ULONG_LE( X[ 3], data, 12 );
- GET_ULONG_LE( X[ 4], data, 16 );
- GET_ULONG_LE( X[ 5], data, 20 );
- GET_ULONG_LE( X[ 6], data, 24 );
- GET_ULONG_LE( X[ 7], data, 28 );
- GET_ULONG_LE( X[ 8], data, 32 );
- GET_ULONG_LE( X[ 9], data, 36 );
- GET_ULONG_LE( X[10], data, 40 );
- GET_ULONG_LE( X[11], data, 44 );
- GET_ULONG_LE( X[12], data, 48 );
- GET_ULONG_LE( X[13], data, 52 );
- GET_ULONG_LE( X[14], data, 56 );
- GET_ULONG_LE( X[15], data, 60 );
-
-#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
-
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
-
-#define F(x, y, z) ((x & y) | ((~x) & z))
-#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
-
- P( A, B, C, D, X[ 0], 3 );
- P( D, A, B, C, X[ 1], 7 );
- P( C, D, A, B, X[ 2], 11 );
- P( B, C, D, A, X[ 3], 19 );
- P( A, B, C, D, X[ 4], 3 );
- P( D, A, B, C, X[ 5], 7 );
- P( C, D, A, B, X[ 6], 11 );
- P( B, C, D, A, X[ 7], 19 );
- P( A, B, C, D, X[ 8], 3 );
- P( D, A, B, C, X[ 9], 7 );
- P( C, D, A, B, X[10], 11 );
- P( B, C, D, A, X[11], 19 );
- P( A, B, C, D, X[12], 3 );
- P( D, A, B, C, X[13], 7 );
- P( C, D, A, B, X[14], 11 );
- P( B, C, D, A, X[15], 19 );
-
-#undef P
-#undef F
-
-#define F(x,y,z) ((x & y) | (x & z) | (y & z))
-#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
-
- P( A, B, C, D, X[ 0], 3 );
- P( D, A, B, C, X[ 4], 5 );
- P( C, D, A, B, X[ 8], 9 );
- P( B, C, D, A, X[12], 13 );
- P( A, B, C, D, X[ 1], 3 );
- P( D, A, B, C, X[ 5], 5 );
- P( C, D, A, B, X[ 9], 9 );
- P( B, C, D, A, X[13], 13 );
- P( A, B, C, D, X[ 2], 3 );
- P( D, A, B, C, X[ 6], 5 );
- P( C, D, A, B, X[10], 9 );
- P( B, C, D, A, X[14], 13 );
- P( A, B, C, D, X[ 3], 3 );
- P( D, A, B, C, X[ 7], 5 );
- P( C, D, A, B, X[11], 9 );
- P( B, C, D, A, X[15], 13 );
-
-#undef P
-#undef F
-
-#define F(x,y,z) (x ^ y ^ z)
-#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
-
- P( A, B, C, D, X[ 0], 3 );
- P( D, A, B, C, X[ 8], 9 );
- P( C, D, A, B, X[ 4], 11 );
- P( B, C, D, A, X[12], 15 );
- P( A, B, C, D, X[ 2], 3 );
- P( D, A, B, C, X[10], 9 );
- P( C, D, A, B, X[ 6], 11 );
- P( B, C, D, A, X[14], 15 );
- P( A, B, C, D, X[ 1], 3 );
- P( D, A, B, C, X[ 9], 9 );
- P( C, D, A, B, X[ 5], 11 );
- P( B, C, D, A, X[13], 15 );
- P( A, B, C, D, X[ 3], 3 );
- P( D, A, B, C, X[11], 9 );
- P( C, D, A, B, X[ 7], 11 );
- P( B, C, D, A, X[15], 15 );
-
-#undef F
-#undef P
-
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
-}
-
-/*
- * MD4 process buffer
- */
-void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
-{
- size_t fill;
- unsigned long left;
-
- if( ilen <= 0 )
- return;
-
- left = ctx->total[0] & 0x3F;
- fill = 64 - left;
-
- ctx->total[0] += (unsigned long) ilen;
- ctx->total[0] &= 0xFFFFFFFF;
-
- if( ctx->total[0] < (unsigned long) ilen )
- ctx->total[1]++;
-
- if( left && ilen >= fill )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, fill );
- md4_process( ctx, ctx->buffer );
- input += fill;
- ilen -= fill;
- left = 0;
- }
-
- while( ilen >= 64 )
- {
- md4_process( ctx, input );
- input += 64;
- ilen -= 64;
- }
-
- if( ilen > 0 )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, ilen );
- }
-}
-
-static const unsigned char md4_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * MD4 final digest
- */
-void md4_finish( md4_context *ctx, unsigned char output[16] )
-{
- unsigned long last, padn;
- unsigned long high, low;
- unsigned char msglen[8];
-
- high = ( ctx->total[0] >> 29 )
- | ( ctx->total[1] << 3 );
- low = ( ctx->total[0] << 3 );
-
- PUT_ULONG_LE( low, msglen, 0 );
- PUT_ULONG_LE( high, msglen, 4 );
-
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
- md4_update( ctx, (unsigned char *) md4_padding, padn );
- md4_update( ctx, msglen, 8 );
-
- PUT_ULONG_LE( ctx->state[0], output, 0 );
- PUT_ULONG_LE( ctx->state[1], output, 4 );
- PUT_ULONG_LE( ctx->state[2], output, 8 );
- PUT_ULONG_LE( ctx->state[3], output, 12 );
-}
-
-/*
- * output = MD4( input buffer )
- */
-void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
-{
- md4_context ctx;
-
- md4_starts( &ctx );
- md4_update( &ctx, input, ilen );
- md4_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md4_context ) );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * output = MD4( file contents )
- */
-int md4_file( const char *path, unsigned char output[16] )
-{
- FILE *f;
- size_t n;
- md4_context ctx;
- unsigned char buf[1024];
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
-
- md4_starts( &ctx );
-
- while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
- md4_update( &ctx, buf, n );
-
- md4_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md4_context ) );
-
- if( ferror( f ) != 0 )
- {
- fclose( f );
- return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
- }
-
- fclose( f );
- return( 0 );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * MD4 HMAC context setup
- */
-void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen )
-{
- size_t i;
- unsigned char sum[16];
-
- if( keylen > 64 )
- {
- md4( key, keylen, sum );
- keylen = 16;
- key = sum;
- }
-
- memset( ctx->ipad, 0x36, 64 );
- memset( ctx->opad, 0x5C, 64 );
-
- for( i = 0; i < keylen; i++ )
- {
- ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
- ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
- }
-
- md4_starts( ctx );
- md4_update( ctx, ctx->ipad, 64 );
-
- memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * MD4 HMAC process buffer
- */
-void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen )
-{
- md4_update( ctx, input, ilen );
-}
-
-/*
- * MD4 HMAC final digest
- */
-void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
-{
- unsigned char tmpbuf[16];
-
- md4_finish( ctx, tmpbuf );
- md4_starts( ctx );
- md4_update( ctx, ctx->opad, 64 );
- md4_update( ctx, tmpbuf, 16 );
- md4_finish( ctx, output );
-
- memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * MD4 HMAC context reset
- */
-void md4_hmac_reset( md4_context *ctx )
-{
- md4_starts( ctx );
- md4_update( ctx, ctx->ipad, 64 );
-}
-
-/*
- * output = HMAC-MD4( hmac key, input buffer )
- */
-void md4_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[16] )
-{
- md4_context ctx;
-
- md4_hmac_starts( &ctx, key, keylen );
- md4_hmac_update( &ctx, input, ilen );
- md4_hmac_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md4_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-/*
- * RFC 1320 test vectors
- */
-static const char md4_test_str[7][81] =
-{
- { "" },
- { "a" },
- { "abc" },
- { "message digest" },
- { "abcdefghijklmnopqrstuvwxyz" },
- { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
- { "12345678901234567890123456789012345678901234567890123456789012" \
- "345678901234567890" }
-};
-
-static const unsigned char md4_test_sum[7][16] =
-{
- { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
- 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
- { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
- 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
- { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
- 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
- { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
- 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
- { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
- 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
- { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
- 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
- { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
- 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
-};
-
-/*
- * Checkup routine
- */
-int md4_self_test( int verbose )
-{
- int i;
- unsigned char md4sum[16];
-
- for( i = 0; i < 7; i++ )
- {
- if( verbose != 0 )
- printf( " MD4 test #%d: ", i + 1 );
-
- md4( (unsigned char *) md4_test_str[i],
- strlen( md4_test_str[i] ), md4sum );
-
- if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/md5.c b/polarssl/src/library/md5.c
deleted file mode 100644
index 7a449b2..0000000
--- a/polarssl/src/library/md5.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * RFC 1321 compliant MD5 implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The MD5 algorithm was designed by Ron Rivest in 1991.
- *
- * http://www.ietf.org/rfc/rfc1321.txt
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_MD5_C)
-
-#include "polarssl/md5.h"
-
-#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
-#include <stdio.h>
-#endif
-
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_ULONG_LE
-#define GET_ULONG_LE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] ) \
- | ( (unsigned long) (b)[(i) + 1] << 8 ) \
- | ( (unsigned long) (b)[(i) + 2] << 16 ) \
- | ( (unsigned long) (b)[(i) + 3] << 24 ); \
-}
-#endif
-
-#ifndef PUT_ULONG_LE
-#define PUT_ULONG_LE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
-}
-#endif
-
-/*
- * MD5 context setup
- */
-void md5_starts( md5_context *ctx )
-{
- ctx->total[0] = 0;
- ctx->total[1] = 0;
-
- ctx->state[0] = 0x67452301;
- ctx->state[1] = 0xEFCDAB89;
- ctx->state[2] = 0x98BADCFE;
- ctx->state[3] = 0x10325476;
-}
-
-static void md5_process( md5_context *ctx, const unsigned char data[64] )
-{
- unsigned long X[16], A, B, C, D;
-
- GET_ULONG_LE( X[ 0], data, 0 );
- GET_ULONG_LE( X[ 1], data, 4 );
- GET_ULONG_LE( X[ 2], data, 8 );
- GET_ULONG_LE( X[ 3], data, 12 );
- GET_ULONG_LE( X[ 4], data, 16 );
- GET_ULONG_LE( X[ 5], data, 20 );
- GET_ULONG_LE( X[ 6], data, 24 );
- GET_ULONG_LE( X[ 7], data, 28 );
- GET_ULONG_LE( X[ 8], data, 32 );
- GET_ULONG_LE( X[ 9], data, 36 );
- GET_ULONG_LE( X[10], data, 40 );
- GET_ULONG_LE( X[11], data, 44 );
- GET_ULONG_LE( X[12], data, 48 );
- GET_ULONG_LE( X[13], data, 52 );
- GET_ULONG_LE( X[14], data, 56 );
- GET_ULONG_LE( X[15], data, 60 );
-
-#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
-
-#define P(a,b,c,d,k,s,t) \
-{ \
- a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
-}
-
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
-
-#define F(x,y,z) (z ^ (x & (y ^ z)))
-
- P( A, B, C, D, 0, 7, 0xD76AA478 );
- P( D, A, B, C, 1, 12, 0xE8C7B756 );
- P( C, D, A, B, 2, 17, 0x242070DB );
- P( B, C, D, A, 3, 22, 0xC1BDCEEE );
- P( A, B, C, D, 4, 7, 0xF57C0FAF );
- P( D, A, B, C, 5, 12, 0x4787C62A );
- P( C, D, A, B, 6, 17, 0xA8304613 );
- P( B, C, D, A, 7, 22, 0xFD469501 );
- P( A, B, C, D, 8, 7, 0x698098D8 );
- P( D, A, B, C, 9, 12, 0x8B44F7AF );
- P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
- P( B, C, D, A, 11, 22, 0x895CD7BE );
- P( A, B, C, D, 12, 7, 0x6B901122 );
- P( D, A, B, C, 13, 12, 0xFD987193 );
- P( C, D, A, B, 14, 17, 0xA679438E );
- P( B, C, D, A, 15, 22, 0x49B40821 );
-
-#undef F
-
-#define F(x,y,z) (y ^ (z & (x ^ y)))
-
- P( A, B, C, D, 1, 5, 0xF61E2562 );
- P( D, A, B, C, 6, 9, 0xC040B340 );
- P( C, D, A, B, 11, 14, 0x265E5A51 );
- P( B, C, D, A, 0, 20, 0xE9B6C7AA );
- P( A, B, C, D, 5, 5, 0xD62F105D );
- P( D, A, B, C, 10, 9, 0x02441453 );
- P( C, D, A, B, 15, 14, 0xD8A1E681 );
- P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
- P( A, B, C, D, 9, 5, 0x21E1CDE6 );
- P( D, A, B, C, 14, 9, 0xC33707D6 );
- P( C, D, A, B, 3, 14, 0xF4D50D87 );
- P( B, C, D, A, 8, 20, 0x455A14ED );
- P( A, B, C, D, 13, 5, 0xA9E3E905 );
- P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
- P( C, D, A, B, 7, 14, 0x676F02D9 );
- P( B, C, D, A, 12, 20, 0x8D2A4C8A );
-
-#undef F
-
-#define F(x,y,z) (x ^ y ^ z)
-
- P( A, B, C, D, 5, 4, 0xFFFA3942 );
- P( D, A, B, C, 8, 11, 0x8771F681 );
- P( C, D, A, B, 11, 16, 0x6D9D6122 );
- P( B, C, D, A, 14, 23, 0xFDE5380C );
- P( A, B, C, D, 1, 4, 0xA4BEEA44 );
- P( D, A, B, C, 4, 11, 0x4BDECFA9 );
- P( C, D, A, B, 7, 16, 0xF6BB4B60 );
- P( B, C, D, A, 10, 23, 0xBEBFBC70 );
- P( A, B, C, D, 13, 4, 0x289B7EC6 );
- P( D, A, B, C, 0, 11, 0xEAA127FA );
- P( C, D, A, B, 3, 16, 0xD4EF3085 );
- P( B, C, D, A, 6, 23, 0x04881D05 );
- P( A, B, C, D, 9, 4, 0xD9D4D039 );
- P( D, A, B, C, 12, 11, 0xE6DB99E5 );
- P( C, D, A, B, 15, 16, 0x1FA27CF8 );
- P( B, C, D, A, 2, 23, 0xC4AC5665 );
-
-#undef F
-
-#define F(x,y,z) (y ^ (x | ~z))
-
- P( A, B, C, D, 0, 6, 0xF4292244 );
- P( D, A, B, C, 7, 10, 0x432AFF97 );
- P( C, D, A, B, 14, 15, 0xAB9423A7 );
- P( B, C, D, A, 5, 21, 0xFC93A039 );
- P( A, B, C, D, 12, 6, 0x655B59C3 );
- P( D, A, B, C, 3, 10, 0x8F0CCC92 );
- P( C, D, A, B, 10, 15, 0xFFEFF47D );
- P( B, C, D, A, 1, 21, 0x85845DD1 );
- P( A, B, C, D, 8, 6, 0x6FA87E4F );
- P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
- P( C, D, A, B, 6, 15, 0xA3014314 );
- P( B, C, D, A, 13, 21, 0x4E0811A1 );
- P( A, B, C, D, 4, 6, 0xF7537E82 );
- P( D, A, B, C, 11, 10, 0xBD3AF235 );
- P( C, D, A, B, 2, 15, 0x2AD7D2BB );
- P( B, C, D, A, 9, 21, 0xEB86D391 );
-
-#undef F
-
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
-}
-
-/*
- * MD5 process buffer
- */
-void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
-{
- size_t fill;
- unsigned long left;
-
- if( ilen <= 0 )
- return;
-
- left = ctx->total[0] & 0x3F;
- fill = 64 - left;
-
- ctx->total[0] += (unsigned long) ilen;
- ctx->total[0] &= 0xFFFFFFFF;
-
- if( ctx->total[0] < (unsigned long) ilen )
- ctx->total[1]++;
-
- if( left && ilen >= fill )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, fill );
- md5_process( ctx, ctx->buffer );
- input += fill;
- ilen -= fill;
- left = 0;
- }
-
- while( ilen >= 64 )
- {
- md5_process( ctx, input );
- input += 64;
- ilen -= 64;
- }
-
- if( ilen > 0 )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, ilen );
- }
-}
-
-static const unsigned char md5_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * MD5 final digest
- */
-void md5_finish( md5_context *ctx, unsigned char output[16] )
-{
- unsigned long last, padn;
- unsigned long high, low;
- unsigned char msglen[8];
-
- high = ( ctx->total[0] >> 29 )
- | ( ctx->total[1] << 3 );
- low = ( ctx->total[0] << 3 );
-
- PUT_ULONG_LE( low, msglen, 0 );
- PUT_ULONG_LE( high, msglen, 4 );
-
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
- md5_update( ctx, (unsigned char *) md5_padding, padn );
- md5_update( ctx, msglen, 8 );
-
- PUT_ULONG_LE( ctx->state[0], output, 0 );
- PUT_ULONG_LE( ctx->state[1], output, 4 );
- PUT_ULONG_LE( ctx->state[2], output, 8 );
- PUT_ULONG_LE( ctx->state[3], output, 12 );
-}
-
-/*
- * output = MD5( input buffer )
- */
-void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
-{
- md5_context ctx;
-
- md5_starts( &ctx );
- md5_update( &ctx, input, ilen );
- md5_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md5_context ) );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * output = MD5( file contents )
- */
-int md5_file( const char *path, unsigned char output[16] )
-{
- FILE *f;
- size_t n;
- md5_context ctx;
- unsigned char buf[1024];
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
-
- md5_starts( &ctx );
-
- while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
- md5_update( &ctx, buf, n );
-
- md5_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md5_context ) );
-
- if( ferror( f ) != 0 )
- {
- fclose( f );
- return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
- }
-
- fclose( f );
- return( 0 );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * MD5 HMAC context setup
- */
-void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
-{
- size_t i;
- unsigned char sum[16];
-
- if( keylen > 64 )
- {
- md5( key, keylen, sum );
- keylen = 16;
- key = sum;
- }
-
- memset( ctx->ipad, 0x36, 64 );
- memset( ctx->opad, 0x5C, 64 );
-
- for( i = 0; i < keylen; i++ )
- {
- ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
- ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
- }
-
- md5_starts( ctx );
- md5_update( ctx, ctx->ipad, 64 );
-
- memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * MD5 HMAC process buffer
- */
-void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
-{
- md5_update( ctx, input, ilen );
-}
-
-/*
- * MD5 HMAC final digest
- */
-void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
-{
- unsigned char tmpbuf[16];
-
- md5_finish( ctx, tmpbuf );
- md5_starts( ctx );
- md5_update( ctx, ctx->opad, 64 );
- md5_update( ctx, tmpbuf, 16 );
- md5_finish( ctx, output );
-
- memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * MD5 HMAC context reset
- */
-void md5_hmac_reset( md5_context *ctx )
-{
- md5_starts( ctx );
- md5_update( ctx, ctx->ipad, 64 );
-}
-
-/*
- * output = HMAC-MD5( hmac key, input buffer )
- */
-void md5_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[16] )
-{
- md5_context ctx;
-
- md5_hmac_starts( &ctx, key, keylen );
- md5_hmac_update( &ctx, input, ilen );
- md5_hmac_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( md5_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-/*
- * RFC 1321 test vectors
- */
-static unsigned char md5_test_buf[7][81] =
-{
- { "" },
- { "a" },
- { "abc" },
- { "message digest" },
- { "abcdefghijklmnopqrstuvwxyz" },
- { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
- { "12345678901234567890123456789012345678901234567890123456789012" \
- "345678901234567890" }
-};
-
-static const int md5_test_buflen[7] =
-{
- 0, 1, 3, 14, 26, 62, 80
-};
-
-static const unsigned char md5_test_sum[7][16] =
-{
- { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
- 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
- { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
- 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
- { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
- 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
- { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
- 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
- { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
- 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
- { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
- 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
- { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
- 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
-};
-
-/*
- * RFC 2202 test vectors
- */
-static unsigned char md5_hmac_test_key[7][26] =
-{
- { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
- { "Jefe" },
- { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
- { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
- "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
- { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
- { "" }, /* 0xAA 80 times */
- { "" }
-};
-
-static const int md5_hmac_test_keylen[7] =
-{
- 16, 4, 16, 25, 16, 80, 80
-};
-
-static unsigned char md5_hmac_test_buf[7][74] =
-{
- { "Hi There" },
- { "what do ya want for nothing?" },
- { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
- { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
- { "Test With Truncation" },
- { "Test Using Larger Than Block-Size Key - Hash Key First" },
- { "Test Using Larger Than Block-Size Key and Larger"
- " Than One Block-Size Data" }
-};
-
-static const int md5_hmac_test_buflen[7] =
-{
- 8, 28, 50, 50, 20, 54, 73
-};
-
-static const unsigned char md5_hmac_test_sum[7][16] =
-{
- { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
- 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
- { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
- 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
- { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
- 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
- { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
- 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
- { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
- 0xF9, 0xBA, 0xB9, 0x95 },
- { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
- 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
- { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
- 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
-};
-
-/*
- * Checkup routine
- */
-int md5_self_test( int verbose )
-{
- int i, buflen;
- unsigned char buf[1024];
- unsigned char md5sum[16];
- md5_context ctx;
-
- for( i = 0; i < 7; i++ )
- {
- if( verbose != 0 )
- printf( " MD5 test #%d: ", i + 1 );
-
- md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
-
- if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- for( i = 0; i < 7; i++ )
- {
- if( verbose != 0 )
- printf( " HMAC-MD5 test #%d: ", i + 1 );
-
- if( i == 5 || i == 6 )
- {
- memset( buf, '\xAA', buflen = 80 );
- md5_hmac_starts( &ctx, buf, buflen );
- }
- else
- md5_hmac_starts( &ctx, md5_hmac_test_key[i],
- md5_hmac_test_keylen[i] );
-
- md5_hmac_update( &ctx, md5_hmac_test_buf[i],
- md5_hmac_test_buflen[i] );
-
- md5_hmac_finish( &ctx, md5sum );
-
- buflen = ( i == 4 ) ? 12 : 16;
-
- if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/md_wrap.c b/polarssl/src/library/md_wrap.c
deleted file mode 100644
index f276db5..0000000
--- a/polarssl/src/library/md_wrap.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/**
- * \file md_wrap.c
-
- * \brief Generic message digest wrapper for PolarSSL
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_MD_C)
-
-#include "polarssl/md_wrap.h"
-
-#if defined(POLARSSL_MD2_C)
-#include "polarssl/md2.h"
-#endif
-
-#if defined(POLARSSL_MD4_C)
-#include "polarssl/md4.h"
-#endif
-
-#if defined(POLARSSL_MD5_C)
-#include "polarssl/md5.h"
-#endif
-
-#if defined(POLARSSL_SHA1_C)
-#include "polarssl/sha1.h"
-#endif
-
-#if defined(POLARSSL_SHA2_C)
-#include "polarssl/sha2.h"
-#endif
-
-#if defined(POLARSSL_SHA4_C)
-#include "polarssl/sha4.h"
-#endif
-
-#include <stdlib.h>
-
-#if defined(POLARSSL_MD2_C)
-
-static void md2_starts_wrap( void *ctx )
-{
- md2_starts( (md2_context *) ctx );
-}
-
-static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- md2_update( (md2_context *) ctx, input, ilen );
-}
-
-static void md2_finish_wrap( void *ctx, unsigned char *output )
-{
- md2_finish( (md2_context *) ctx, output );
-}
-
-int md2_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return md2_file( path, output );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- md2_hmac_starts( (md2_context *) ctx, key, keylen );
-}
-
-static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- md2_hmac_update( (md2_context *) ctx, input, ilen );
-}
-
-static void md2_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- md2_hmac_finish( (md2_context *) ctx, output );
-}
-
-static void md2_hmac_reset_wrap( void *ctx )
-{
- md2_hmac_reset( (md2_context *) ctx );
-}
-
-static void * md2_ctx_alloc( void )
-{
- return malloc( sizeof( md2_context ) );
-}
-
-static void md2_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t md2_info = {
- POLARSSL_MD_MD2,
- "MD2",
- 16,
- md2_starts_wrap,
- md2_update_wrap,
- md2_finish_wrap,
- md2,
- md2_file_wrap,
- md2_hmac_starts_wrap,
- md2_hmac_update_wrap,
- md2_hmac_finish_wrap,
- md2_hmac_reset_wrap,
- md2_hmac,
- md2_ctx_alloc,
- md2_ctx_free,
-};
-
-#endif
-
-#if defined(POLARSSL_MD4_C)
-
-void md4_starts_wrap( void *ctx )
-{
- md4_starts( (md4_context *) ctx );
-}
-
-void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- md4_update( (md4_context *) ctx, input, ilen );
-}
-
-void md4_finish_wrap( void *ctx, unsigned char *output )
-{
- md4_finish( (md4_context *) ctx, output );
-}
-
-int md4_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return md4_file( path, output );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- md4_hmac_starts( (md4_context *) ctx, key, keylen );
-}
-
-void md4_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- md4_hmac_update( (md4_context *) ctx, input, ilen );
-}
-
-void md4_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- md4_hmac_finish( (md4_context *) ctx, output );
-}
-
-void md4_hmac_reset_wrap( void *ctx )
-{
- md4_hmac_reset( (md4_context *) ctx );
-}
-
-void *md4_ctx_alloc( void )
-{
- return malloc( sizeof( md4_context ) );
-}
-
-void md4_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t md4_info = {
- POLARSSL_MD_MD4,
- "MD4",
- 16,
- md4_starts_wrap,
- md4_update_wrap,
- md4_finish_wrap,
- md4,
- md4_file_wrap,
- md4_hmac_starts_wrap,
- md4_hmac_update_wrap,
- md4_hmac_finish_wrap,
- md4_hmac_reset_wrap,
- md4_hmac,
- md4_ctx_alloc,
- md4_ctx_free,
-};
-
-#endif
-
-#if defined(POLARSSL_MD5_C)
-
-static void md5_starts_wrap( void *ctx )
-{
- md5_starts( (md5_context *) ctx );
-}
-
-static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- md5_update( (md5_context *) ctx, input, ilen );
-}
-
-static void md5_finish_wrap( void *ctx, unsigned char *output )
-{
- md5_finish( (md5_context *) ctx, output );
-}
-
-int md5_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return md5_file( path, output );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- md5_hmac_starts( (md5_context *) ctx, key, keylen );
-}
-
-static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- md5_hmac_update( (md5_context *) ctx, input, ilen );
-}
-
-static void md5_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- md5_hmac_finish( (md5_context *) ctx, output );
-}
-
-static void md5_hmac_reset_wrap( void *ctx )
-{
- md5_hmac_reset( (md5_context *) ctx );
-}
-
-static void * md5_ctx_alloc( void )
-{
- return malloc( sizeof( md5_context ) );
-}
-
-static void md5_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t md5_info = {
- POLARSSL_MD_MD5,
- "MD5",
- 16,
- md5_starts_wrap,
- md5_update_wrap,
- md5_finish_wrap,
- md5,
- md5_file_wrap,
- md5_hmac_starts_wrap,
- md5_hmac_update_wrap,
- md5_hmac_finish_wrap,
- md5_hmac_reset_wrap,
- md5_hmac,
- md5_ctx_alloc,
- md5_ctx_free,
-};
-
-#endif
-
-#if defined(POLARSSL_SHA1_C)
-
-void sha1_starts_wrap( void *ctx )
-{
- sha1_starts( (sha1_context *) ctx );
-}
-
-void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha1_update( (sha1_context *) ctx, input, ilen );
-}
-
-void sha1_finish_wrap( void *ctx, unsigned char *output )
-{
- sha1_finish( (sha1_context *) ctx, output );
-}
-
-int sha1_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return sha1_file( path, output );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- sha1_hmac_starts( (sha1_context *) ctx, key, keylen );
-}
-
-void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha1_hmac_update( (sha1_context *) ctx, input, ilen );
-}
-
-void sha1_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- sha1_hmac_finish( (sha1_context *) ctx, output );
-}
-
-void sha1_hmac_reset_wrap( void *ctx )
-{
- sha1_hmac_reset( (sha1_context *) ctx );
-}
-
-void * sha1_ctx_alloc( void )
-{
- return malloc( sizeof( sha1_context ) );
-}
-
-void sha1_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t sha1_info = {
- POLARSSL_MD_SHA1,
- "SHA1",
- 20,
- sha1_starts_wrap,
- sha1_update_wrap,
- sha1_finish_wrap,
- sha1,
- sha1_file_wrap,
- sha1_hmac_starts_wrap,
- sha1_hmac_update_wrap,
- sha1_hmac_finish_wrap,
- sha1_hmac_reset_wrap,
- sha1_hmac,
- sha1_ctx_alloc,
- sha1_ctx_free,
-};
-
-#endif
-
-/*
- * Wrappers for generic message digests
- */
-#if defined(POLARSSL_SHA2_C)
-
-void sha224_starts_wrap( void *ctx )
-{
- sha2_starts( (sha2_context *) ctx, 1 );
-}
-
-void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha2_update( (sha2_context *) ctx, input, ilen );
-}
-
-void sha224_finish_wrap( void *ctx, unsigned char *output )
-{
- sha2_finish( (sha2_context *) ctx, output );
-}
-
-void sha224_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha2( input, ilen, output, 1 );
-}
-
-int sha224_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return sha2_file( path, output, 1 );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 1 );
-}
-
-void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha2_hmac_update( (sha2_context *) ctx, input, ilen );
-}
-
-void sha224_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- sha2_hmac_finish( (sha2_context *) ctx, output );
-}
-
-void sha224_hmac_reset_wrap( void *ctx )
-{
- sha2_hmac_reset( (sha2_context *) ctx );
-}
-
-void sha224_hmac_wrap( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha2_hmac( key, keylen, input, ilen, output, 1 );
-}
-
-void * sha224_ctx_alloc( void )
-{
- return malloc( sizeof( sha2_context ) );
-}
-
-void sha224_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t sha224_info = {
- POLARSSL_MD_SHA224,
- "SHA224",
- 28,
- sha224_starts_wrap,
- sha224_update_wrap,
- sha224_finish_wrap,
- sha224_wrap,
- sha224_file_wrap,
- sha224_hmac_starts_wrap,
- sha224_hmac_update_wrap,
- sha224_hmac_finish_wrap,
- sha224_hmac_reset_wrap,
- sha224_hmac_wrap,
- sha224_ctx_alloc,
- sha224_ctx_free,
-};
-
-void sha256_starts_wrap( void *ctx )
-{
- sha2_starts( (sha2_context *) ctx, 0 );
-}
-
-void sha256_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha2_update( (sha2_context *) ctx, input, ilen );
-}
-
-void sha256_finish_wrap( void *ctx, unsigned char *output )
-{
- sha2_finish( (sha2_context *) ctx, output );
-}
-
-void sha256_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha2( input, ilen, output, 0 );
-}
-
-int sha256_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return sha2_file( path, output, 0 );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 0 );
-}
-
-void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha2_hmac_update( (sha2_context *) ctx, input, ilen );
-}
-
-void sha256_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- sha2_hmac_finish( (sha2_context *) ctx, output );
-}
-
-void sha256_hmac_reset_wrap( void *ctx )
-{
- sha2_hmac_reset( (sha2_context *) ctx );
-}
-
-void sha256_hmac_wrap( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha2_hmac( key, keylen, input, ilen, output, 0 );
-}
-
-void * sha256_ctx_alloc( void )
-{
- return malloc( sizeof( sha2_context ) );
-}
-
-void sha256_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t sha256_info = {
- POLARSSL_MD_SHA256,
- "SHA256",
- 32,
- sha256_starts_wrap,
- sha256_update_wrap,
- sha256_finish_wrap,
- sha256_wrap,
- sha256_file_wrap,
- sha256_hmac_starts_wrap,
- sha256_hmac_update_wrap,
- sha256_hmac_finish_wrap,
- sha256_hmac_reset_wrap,
- sha256_hmac_wrap,
- sha256_ctx_alloc,
- sha256_ctx_free,
-};
-
-#endif
-
-#if defined(POLARSSL_SHA4_C)
-
-void sha384_starts_wrap( void *ctx )
-{
- sha4_starts( (sha4_context *) ctx, 1 );
-}
-
-void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha4_update( (sha4_context *) ctx, input, ilen );
-}
-
-void sha384_finish_wrap( void *ctx, unsigned char *output )
-{
- sha4_finish( (sha4_context *) ctx, output );
-}
-
-void sha384_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha4( input, ilen, output, 1 );
-}
-
-int sha384_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return sha4_file( path, output, 1 );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 1 );
-}
-
-void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha4_hmac_update( (sha4_context *) ctx, input, ilen );
-}
-
-void sha384_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- sha4_hmac_finish( (sha4_context *) ctx, output );
-}
-
-void sha384_hmac_reset_wrap( void *ctx )
-{
- sha4_hmac_reset( (sha4_context *) ctx );
-}
-
-void sha384_hmac_wrap( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha4_hmac( key, keylen, input, ilen, output, 1 );
-}
-
-void * sha384_ctx_alloc( void )
-{
- return malloc( sizeof( sha4_context ) );
-}
-
-void sha384_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t sha384_info = {
- POLARSSL_MD_SHA384,
- "SHA384",
- 48,
- sha384_starts_wrap,
- sha384_update_wrap,
- sha384_finish_wrap,
- sha384_wrap,
- sha384_file_wrap,
- sha384_hmac_starts_wrap,
- sha384_hmac_update_wrap,
- sha384_hmac_finish_wrap,
- sha384_hmac_reset_wrap,
- sha384_hmac_wrap,
- sha384_ctx_alloc,
- sha384_ctx_free,
-};
-
-void sha512_starts_wrap( void *ctx )
-{
- sha4_starts( (sha4_context *) ctx, 0 );
-}
-
-void sha512_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha4_update( (sha4_context *) ctx, input, ilen );
-}
-
-void sha512_finish_wrap( void *ctx, unsigned char *output )
-{
- sha4_finish( (sha4_context *) ctx, output );
-}
-
-void sha512_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha4( input, ilen, output, 0 );
-}
-
-int sha512_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(POLARSSL_FS_IO)
- return sha4_file( path, output, 0 );
-#else
- ((void) path);
- ((void) output);
- return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
-}
-
-void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
-{
- sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 0 );
-}
-
-void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
-{
- sha4_hmac_update( (sha4_context *) ctx, input, ilen );
-}
-
-void sha512_hmac_finish_wrap( void *ctx, unsigned char *output )
-{
- sha4_hmac_finish( (sha4_context *) ctx, output );
-}
-
-void sha512_hmac_reset_wrap( void *ctx )
-{
- sha4_hmac_reset( (sha4_context *) ctx );
-}
-
-void sha512_hmac_wrap( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- sha4_hmac( key, keylen, input, ilen, output, 0 );
-}
-
-void * sha512_ctx_alloc( void )
-{
- return malloc( sizeof( sha4_context ) );
-}
-
-void sha512_ctx_free( void *ctx )
-{
- free( ctx );
-}
-
-const md_info_t sha512_info = {
- POLARSSL_MD_SHA512,
- "SHA512",
- 64,
- sha512_starts_wrap,
- sha512_update_wrap,
- sha512_finish_wrap,
- sha512_wrap,
- sha512_file_wrap,
- sha512_hmac_starts_wrap,
- sha512_hmac_update_wrap,
- sha512_hmac_finish_wrap,
- sha512_hmac_reset_wrap,
- sha512_hmac_wrap,
- sha512_ctx_alloc,
- sha512_ctx_free,
-};
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/net.c b/polarssl/src/library/net.c
deleted file mode 100644
index e30aebb..0000000
--- a/polarssl/src/library/net.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * TCP networking functions
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_NET_C)
-
-#include "polarssl/net.h"
-
-#if defined(_WIN32) || defined(_WIN32_WCE)
-
-#include <winsock2.h>
-#include <windows.h>
-
-#if defined(_WIN32_WCE)
-#pragma comment( lib, "ws2.lib" )
-#else
-#pragma comment( lib, "ws2_32.lib" )
-#endif
-
-#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
-#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
-#define close(fd) closesocket(fd)
-
-static int wsa_init_done = 0;
-
-#else
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <errno.h>
-
-#if defined(__FreeBSD__) || defined(__OpenBSD__)
-#include <sys/endian.h>
-#elif defined(__APPLE__)
-#include <machine/endian.h>
-#elif defined(sun)
-#include <sys/isa_defs.h>
-#else
-#include <endian.h>
-#endif
-
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-/*
- * htons() is not always available.
- * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and __BIG_ENDIAN
- * to help determine endianess.
- */
-#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
-#define POLARSSL_HTONS(n) (n)
-#else
-#define POLARSSL_HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
-#endif
-
-unsigned short net_htons(unsigned short n);
-#define net_htons(n) POLARSSL_HTONS(n)
-
-/*
- * Initiate a TCP connection with host:port
- */
-int net_connect( int *fd, const char *host, int port )
-{
- struct sockaddr_in server_addr;
- struct hostent *server_host;
-
-#if defined(_WIN32) || defined(_WIN32_WCE)
- WSADATA wsaData;
-
- if( wsa_init_done == 0 )
- {
- if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
- return( POLARSSL_ERR_NET_SOCKET_FAILED );
-
- wsa_init_done = 1;
- }
-#else
- signal( SIGPIPE, SIG_IGN );
-#endif
-
- if( ( server_host = gethostbyname( host ) ) == NULL )
- return( POLARSSL_ERR_NET_UNKNOWN_HOST );
-
- if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
- return( POLARSSL_ERR_NET_SOCKET_FAILED );
-
- memcpy( (void *) &server_addr.sin_addr,
- (void *) server_host->h_addr,
- server_host->h_length );
-
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = net_htons( port );
-
- if( connect( *fd, (struct sockaddr *) &server_addr,
- sizeof( server_addr ) ) < 0 )
- {
- close( *fd );
- return( POLARSSL_ERR_NET_CONNECT_FAILED );
- }
-
- return( 0 );
-}
-
-/*
- * Create a listening socket on bind_ip:port
- */
-int net_bind( int *fd, const char *bind_ip, int port )
-{
- int n, c[4];
- struct sockaddr_in server_addr;
-
-#if defined(_WIN32) || defined(_WIN32_WCE)
- WSADATA wsaData;
-
- if( wsa_init_done == 0 )
- {
- if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
- return( POLARSSL_ERR_NET_SOCKET_FAILED );
-
- wsa_init_done = 1;
- }
-#else
- signal( SIGPIPE, SIG_IGN );
-#endif
-
- if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
- return( POLARSSL_ERR_NET_SOCKET_FAILED );
-
- n = 1;
- setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
- (const char *) &n, sizeof( n ) );
-
- server_addr.sin_addr.s_addr = INADDR_ANY;
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = net_htons( port );
-
- if( bind_ip != NULL )
- {
- memset( c, 0, sizeof( c ) );
- sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
-
- for( n = 0; n < 4; n++ )
- if( c[n] < 0 || c[n] > 255 )
- break;
-
- if( n == 4 )
- server_addr.sin_addr.s_addr =
- ( (unsigned long) c[0] << 24 ) |
- ( (unsigned long) c[1] << 16 ) |
- ( (unsigned long) c[2] << 8 ) |
- ( (unsigned long) c[3] );
- }
-
- if( bind( *fd, (struct sockaddr *) &server_addr,
- sizeof( server_addr ) ) < 0 )
- {
- close( *fd );
- return( POLARSSL_ERR_NET_BIND_FAILED );
- }
-
- if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
- {
- close( *fd );
- return( POLARSSL_ERR_NET_LISTEN_FAILED );
- }
-
- return( 0 );
-}
-
-/*
- * Check if the current operation is blocking
- */
-static int net_is_blocking( void )
-{
-#if defined(_WIN32) || defined(_WIN32_WCE)
- return( WSAGetLastError() == WSAEWOULDBLOCK );
-#else
- switch( errno )
- {
-#if defined EAGAIN
- case EAGAIN:
-#endif
-#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- return( 1 );
- }
- return( 0 );
-#endif
-}
-
-/*
- * Accept a connection from a remote client
- */
-int net_accept( int bind_fd, int *client_fd, void *client_ip )
-{
- struct sockaddr_in client_addr;
-
-#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
- defined(_SOCKLEN_T_DECLARED)
- socklen_t n = (socklen_t) sizeof( client_addr );
-#else
- int n = (int) sizeof( client_addr );
-#endif
-
- *client_fd = accept( bind_fd, (struct sockaddr *)
- &client_addr, &n );
-
- if( *client_fd < 0 )
- {
- if( net_is_blocking() != 0 )
- return( POLARSSL_ERR_NET_WANT_READ );
-
- return( POLARSSL_ERR_NET_ACCEPT_FAILED );
- }
-
- if( client_ip != NULL )
- memcpy( client_ip, &client_addr.sin_addr.s_addr,
- sizeof( client_addr.sin_addr.s_addr ) );
-
- return( 0 );
-}
-
-/*
- * Set the socket blocking or non-blocking
- */
-int net_set_block( int fd )
-{
-#if defined(_WIN32) || defined(_WIN32_WCE)
- u_long n = 0;
- return( ioctlsocket( fd, FIONBIO, &n ) );
-#else
- return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
-#endif
-}
-
-int net_set_nonblock( int fd )
-{
-#if defined(_WIN32) || defined(_WIN32_WCE)
- u_long n = 1;
- return( ioctlsocket( fd, FIONBIO, &n ) );
-#else
- return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
-#endif
-}
-
-/*
- * Portable usleep helper
- */
-void net_usleep( unsigned long usec )
-{
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = usec;
- select( 0, NULL, NULL, NULL, &tv );
-}
-
-/*
- * Read at most 'len' characters
- */
-int net_recv( void *ctx, unsigned char *buf, size_t len )
-{
- int ret = read( *((int *) ctx), buf, len );
-
- if( ret < 0 )
- {
- if( net_is_blocking() != 0 )
- return( POLARSSL_ERR_NET_WANT_READ );
-
-#if defined(_WIN32) || defined(_WIN32_WCE)
- if( WSAGetLastError() == WSAECONNRESET )
- return( POLARSSL_ERR_NET_CONN_RESET );
-#else
- if( errno == EPIPE || errno == ECONNRESET )
- return( POLARSSL_ERR_NET_CONN_RESET );
-
- if( errno == EINTR )
- return( POLARSSL_ERR_NET_WANT_READ );
-#endif
-
- return( POLARSSL_ERR_NET_RECV_FAILED );
- }
-
- return( ret );
-}
-
-/*
- * Write at most 'len' characters
- */
-int net_send( void *ctx, const unsigned char *buf, size_t len )
-{
- int ret = write( *((int *) ctx), buf, len );
-
- if( ret < 0 )
- {
- if( net_is_blocking() != 0 )
- return( POLARSSL_ERR_NET_WANT_WRITE );
-
-#if defined(_WIN32) || defined(_WIN32_WCE)
- if( WSAGetLastError() == WSAECONNRESET )
- return( POLARSSL_ERR_NET_CONN_RESET );
-#else
- if( errno == EPIPE || errno == ECONNRESET )
- return( POLARSSL_ERR_NET_CONN_RESET );
-
- if( errno == EINTR )
- return( POLARSSL_ERR_NET_WANT_WRITE );
-#endif
-
- return( POLARSSL_ERR_NET_SEND_FAILED );
- }
-
- return( ret );
-}
-
-/*
- * Gracefully close the connection
- */
-void net_close( int fd )
-{
- shutdown( fd, 2 );
- close( fd );
-}
-
-#endif
diff --git a/polarssl/src/library/padlock.c b/polarssl/src/library/padlock.c
deleted file mode 100644
index 2e2e477..0000000
--- a/polarssl/src/library/padlock.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * VIA PadLock support functions
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * This implementation is based on the VIA PadLock Programming Guide:
- *
- * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
- * programming_guide.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_PADLOCK_C)
-
-#include "polarssl/padlock.h"
-
-#if defined(POLARSSL_HAVE_X86)
-
-/*
- * PadLock detection routine
- */
-int padlock_supports( int feature )
-{
- static int flags = -1;
- int ebx, edx;
-
- if( flags == -1 )
- {
- asm( "movl %%ebx, %0 \n" \
- "movl $0xC0000000, %%eax \n" \
- "cpuid \n" \
- "cmpl $0xC0000001, %%eax \n" \
- "movl $0, %%edx \n" \
- "jb unsupported \n" \
- "movl $0xC0000001, %%eax \n" \
- "cpuid \n" \
- "unsupported: \n" \
- "movl %%edx, %1 \n" \
- "movl %2, %%ebx \n"
- : "=m" (ebx), "=m" (edx)
- : "m" (ebx)
- : "eax", "ecx", "edx" );
-
- flags = edx;
- }
-
- return( flags & feature );
-}
-
-/*
- * PadLock AES-ECB block en(de)cryption
- */
-int padlock_xcryptecb( aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] )
-{
- int ebx;
- unsigned long *rk;
- unsigned long *blk;
- unsigned long *ctrl;
- unsigned char buf[256];
-
- rk = ctx->rk;
- blk = PADLOCK_ALIGN16( buf );
- memcpy( blk, input, 16 );
-
- ctrl = blk + 4;
- *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
-
- asm( "pushfl; popfl \n" \
- "movl %%ebx, %0 \n" \
- "movl $1, %%ecx \n" \
- "movl %2, %%edx \n" \
- "movl %3, %%ebx \n" \
- "movl %4, %%esi \n" \
- "movl %4, %%edi \n" \
- ".byte 0xf3,0x0f,0xa7,0xc8\n" \
- "movl %1, %%ebx \n"
- : "=m" (ebx)
- : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
- : "ecx", "edx", "esi", "edi" );
-
- memcpy( output, blk, 16 );
-
- return( 0 );
-}
-
-/*
- * PadLock AES-CBC buffer en(de)cryption
- */
-int padlock_xcryptcbc( aes_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int ebx;
- size_t count;
- unsigned long *rk;
- unsigned long *iw;
- unsigned long *ctrl;
- unsigned char buf[256];
-
- if( ( (long) input & 15 ) != 0 ||
- ( (long) output & 15 ) != 0 )
- return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED );
-
- rk = ctx->rk;
- iw = PADLOCK_ALIGN16( buf );
- memcpy( iw, iv, 16 );
-
- ctrl = iw + 4;
- *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
-
- count = (length + 15) >> 4;
-
- asm( "pushfl; popfl \n" \
- "movl %%ebx, %0 \n" \
- "movl %2, %%ecx \n" \
- "movl %3, %%edx \n" \
- "movl %4, %%ebx \n" \
- "movl %5, %%esi \n" \
- "movl %6, %%edi \n" \
- "movl %7, %%eax \n" \
- ".byte 0xf3,0x0f,0xa7,0xd0\n" \
- "movl %1, %%ebx \n"
- : "=m" (ebx)
- : "m" (ebx), "m" (count), "m" (ctrl),
- "m" (rk), "m" (input), "m" (output), "m" (iw)
- : "eax", "ecx", "edx", "esi", "edi" );
-
- memcpy( iv, iw, 16 );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/pem.c b/polarssl/src/library/pem.c
deleted file mode 100644
index 33e74ab..0000000
--- a/polarssl/src/library/pem.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Privacy Enhanced Mail (PEM) decoding
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_PEM_C)
-
-#include "polarssl/pem.h"
-#include "polarssl/base64.h"
-#include "polarssl/des.h"
-#include "polarssl/aes.h"
-#include "polarssl/md5.h"
-#include "polarssl/cipher.h"
-
-#include <stdlib.h>
-
-void pem_init( pem_context *ctx )
-{
- memset( ctx, 0, sizeof( pem_context ) );
-}
-
-#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
-/*
- * Read a 16-byte hex string and convert it to binary
- */
-static int pem_get_iv( const unsigned char *s, unsigned char *iv, size_t iv_len )
-{
- size_t i, j, k;
-
- memset( iv, 0, iv_len );
-
- for( i = 0; i < iv_len * 2; i++, s++ )
- {
- if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
- if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
- if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
- return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
-
- k = ( ( i & 1 ) != 0 ) ? j : j << 4;
-
- iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
- }
-
- return( 0 );
-}
-
-static void pem_pbkdf1( unsigned char *key, size_t keylen,
- unsigned char *iv,
- const unsigned char *pwd, size_t pwdlen )
-{
- md5_context md5_ctx;
- unsigned char md5sum[16];
- size_t use_len;
-
- /*
- * key[ 0..15] = MD5(pwd || IV)
- */
- md5_starts( &md5_ctx );
- md5_update( &md5_ctx, pwd, pwdlen );
- md5_update( &md5_ctx, iv, 8 );
- md5_finish( &md5_ctx, md5sum );
-
- if( keylen <= 16 )
- {
- memcpy( key, md5sum, keylen );
-
- memset( &md5_ctx, 0, sizeof( md5_ctx ) );
- memset( md5sum, 0, 16 );
- return;
- }
-
- memcpy( key, md5sum, 16 );
-
- /*
- * key[16..23] = MD5(key[ 0..15] || pwd || IV])
- */
- md5_starts( &md5_ctx );
- md5_update( &md5_ctx, md5sum, 16 );
- md5_update( &md5_ctx, pwd, pwdlen );
- md5_update( &md5_ctx, iv, 8 );
- md5_finish( &md5_ctx, md5sum );
-
- use_len = 16;
- if( keylen < 32 )
- use_len = keylen - 16;
-
- memcpy( key + 16, md5sum, use_len );
-
- memset( &md5_ctx, 0, sizeof( md5_ctx ) );
- memset( md5sum, 0, 16 );
-}
-
-#if defined(POLARSSL_DES_C)
-/*
- * Decrypt with DES-CBC, using PBKDF1 for key derivation
- */
-static void pem_des_decrypt( unsigned char des_iv[8],
- unsigned char *buf, size_t buflen,
- const unsigned char *pwd, size_t pwdlen )
-{
- des_context des_ctx;
- unsigned char des_key[8];
-
- pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
-
- des_setkey_dec( &des_ctx, des_key );
- des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
- des_iv, buf, buf );
-
- memset( &des_ctx, 0, sizeof( des_ctx ) );
- memset( des_key, 0, 8 );
-}
-
-/*
- * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
- */
-static void pem_des3_decrypt( unsigned char des3_iv[8],
- unsigned char *buf, size_t buflen,
- const unsigned char *pwd, size_t pwdlen )
-{
- des3_context des3_ctx;
- unsigned char des3_key[24];
-
- pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
-
- des3_set3key_dec( &des3_ctx, des3_key );
- des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
- des3_iv, buf, buf );
-
- memset( &des3_ctx, 0, sizeof( des3_ctx ) );
- memset( des3_key, 0, 24 );
-}
-#endif /* POLARSSL_DES_C */
-
-#if defined(POLARSSL_AES_C)
-/*
- * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
- */
-static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
- unsigned char *buf, size_t buflen,
- const unsigned char *pwd, size_t pwdlen )
-{
- aes_context aes_ctx;
- unsigned char aes_key[32];
-
- pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
-
- aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
- aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
- aes_iv, buf, buf );
-
- memset( &aes_ctx, 0, sizeof( aes_ctx ) );
- memset( aes_key, 0, keylen );
-}
-#endif /* POLARSSL_AES_C */
-
-#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
-
-int pem_read_buffer( pem_context *ctx, char *header, char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len )
-{
- int ret, enc;
- size_t len;
- unsigned char *buf;
- unsigned char *s1, *s2;
-#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
- unsigned char pem_iv[16];
- cipher_type_t enc_alg = POLARSSL_CIPHER_NONE;
-#else
- ((void) pwd);
- ((void) pwdlen);
-#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
-
- if( ctx == NULL )
- return( POLARSSL_ERR_PEM_INVALID_DATA );
-
- s1 = (unsigned char *) strstr( (char *) data, header );
-
- if( s1 == NULL )
- return( POLARSSL_ERR_PEM_NO_HEADER_PRESENT );
-
- s2 = (unsigned char *) strstr( (char *) data, footer );
-
- if( s2 == NULL || s2 <= s1 )
- return( POLARSSL_ERR_PEM_INVALID_DATA );
-
- s1 += strlen( header );
- if( *s1 == '\r' ) s1++;
- if( *s1 == '\n' ) s1++;
- else return( POLARSSL_ERR_PEM_INVALID_DATA );
-
- enc = 0;
-
- if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
- {
-#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
- enc++;
-
- s1 += 22;
- if( *s1 == '\r' ) s1++;
- if( *s1 == '\n' ) s1++;
- else return( POLARSSL_ERR_PEM_INVALID_DATA );
-
-
-#if defined(POLARSSL_DES_C)
- if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
- {
- enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC;
-
- s1 += 23;
- if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
- return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
-
- s1 += 16;
- }
- else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
- {
- enc_alg = POLARSSL_CIPHER_DES_CBC;
-
- s1 += 18;
- if( pem_get_iv( s1, pem_iv, 8) != 0 )
- return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
-
- s1 += 16;
- }
-#endif /* POLARSSL_DES_C */
-
-#if defined(POLARSSL_AES_C)
- if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
- {
- if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
- enc_alg = POLARSSL_CIPHER_AES_128_CBC;
- else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
- enc_alg = POLARSSL_CIPHER_AES_192_CBC;
- else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
- enc_alg = POLARSSL_CIPHER_AES_256_CBC;
- else
- return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
-
- s1 += 22;
- if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
- return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
-
- s1 += 32;
- }
-#endif /* POLARSSL_AES_C */
-
- if( enc_alg == POLARSSL_CIPHER_NONE )
- return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
-
- if( *s1 == '\r' ) s1++;
- if( *s1 == '\n' ) s1++;
- else return( POLARSSL_ERR_PEM_INVALID_DATA );
-#else
- return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
-#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
- }
-
- len = 0;
- ret = base64_decode( NULL, &len, s1, s2 - s1 );
-
- if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
- return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
-
- if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
- return( POLARSSL_ERR_PEM_MALLOC_FAILED );
-
- if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
- {
- free( buf );
- return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
- }
-
- if( enc != 0 )
- {
-#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
- if( pwd == NULL )
- {
- free( buf );
- return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED );
- }
-
-#if defined(POLARSSL_DES_C)
- if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC )
- pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
- else if( enc_alg == POLARSSL_CIPHER_DES_CBC )
- pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
-#endif /* POLARSSL_DES_C */
-
-#if defined(POLARSSL_AES_C)
- if( enc_alg == POLARSSL_CIPHER_AES_128_CBC )
- pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
- else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC )
- pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
- else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC )
- pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
-#endif /* POLARSSL_AES_C */
-
- if( buf[0] != 0x30 || buf[1] != 0x82 ||
- buf[4] != 0x02 || buf[5] != 0x01 )
- {
- free( buf );
- return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH );
- }
-#else
- return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
-#endif
- }
-
- ctx->buf = buf;
- ctx->buflen = len;
- s2 += strlen( footer );
- if( *s2 == '\r' ) s2++;
- if( *s2 == '\n' ) s2++;
- *use_len = s2 - data;
-
- return( 0 );
-}
-
-void pem_free( pem_context *ctx )
-{
- if( ctx->buf )
- free( ctx->buf );
-
- if( ctx->info )
- free( ctx->info );
-
- memset( ctx, 0, sizeof( pem_context ) );
-}
-
-#endif
diff --git a/polarssl/src/library/pkcs11.c b/polarssl/src/library/pkcs11.c
deleted file mode 100644
index b71415a..0000000
--- a/polarssl/src/library/pkcs11.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/**
- * \file pkcs11.c
- *
- * \brief Wrapper for PKCS#11 library libpkcs11-helper
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/pkcs11.h"
-
-#if defined(POLARSSL_PKCS11_C)
-
-#include <stdlib.h>
-
-int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11_cert )
-{
- int ret = 1;
- unsigned char *cert_blob = NULL;
- size_t cert_blob_size = 0;
-
- if( cert == NULL )
- {
- ret = 2;
- goto cleanup;
- }
-
- if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, &cert_blob_size ) != CKR_OK )
- {
- ret = 3;
- goto cleanup;
- }
-
- cert_blob = malloc( cert_blob_size );
- if( NULL == cert_blob )
- {
- ret = 4;
- goto cleanup;
- }
-
- if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, &cert_blob_size ) != CKR_OK )
- {
- ret = 5;
- goto cleanup;
- }
-
- if( 0 != x509parse_crt(cert, cert_blob, cert_blob_size ) )
- {
- ret = 6;
- goto cleanup;
- }
-
- ret = 0;
-
-cleanup:
- if( NULL != cert_blob )
- free( cert_blob );
-
- return ret;
-}
-
-
-int pkcs11_priv_key_init( pkcs11_context *priv_key,
- pkcs11h_certificate_t pkcs11_cert )
-{
- int ret = 1;
- x509_cert cert;
-
- memset( &cert, 0, sizeof( cert ) );
-
- if( priv_key == NULL )
- goto cleanup;
-
- if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) )
- goto cleanup;
-
- priv_key->len = cert.rsa.len;
- priv_key->pkcs11h_cert = pkcs11_cert;
-
- ret = 0;
-
-cleanup:
- x509_free( &cert );
-
- return ret;
-}
-
-void pkcs11_priv_key_free( pkcs11_context *priv_key )
-{
- if( NULL != priv_key )
- pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert );
-}
-
-int pkcs11_decrypt( pkcs11_context *ctx,
- int mode, size_t *olen,
- const unsigned char *input,
- unsigned char *output,
- unsigned int output_max_len )
-{
- size_t input_len, output_len;
-
- if( NULL == ctx )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- if( RSA_PUBLIC == mode )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- output_len = input_len = ctx->len;
-
- if( input_len < 16 || input_len > output_max_len )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- /* Determine size of output buffer */
- if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
- input_len, NULL, &output_len ) != CKR_OK )
- {
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- if( output_len > output_max_len )
- return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
-
- if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
- input_len, output, &output_len ) != CKR_OK )
- {
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
- *olen = output_len;
- return( 0 );
-}
-
-int pkcs11_sign( pkcs11_context *ctx,
- int mode,
- int hash_id,
- unsigned int hashlen,
- const unsigned char *hash,
- unsigned char *sig )
-{
- size_t olen, asn_len;
- unsigned char *p = sig;
-
- if( NULL == ctx )
- return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
-
- if( RSA_PUBLIC == mode )
- return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
-
- olen = ctx->len;
-
- switch( hash_id )
- {
- case SIG_RSA_RAW:
- asn_len = 0;
- memcpy( p, hash, hashlen );
- break;
-
- case SIG_RSA_MD2:
- asn_len = OID_SIZE(ASN1_HASH_MDX);
- memcpy( p, ASN1_HASH_MDX, asn_len );
- memcpy( p + asn_len, hash, hashlen );
- p[13] = 2; break;
-
- case SIG_RSA_MD4:
- asn_len = OID_SIZE(ASN1_HASH_MDX);
- memcpy( p, ASN1_HASH_MDX, asn_len );
- memcpy( p + asn_len, hash, hashlen );
- p[13] = 4; break;
-
- case SIG_RSA_MD5:
- asn_len = OID_SIZE(ASN1_HASH_MDX);
- memcpy( p, ASN1_HASH_MDX, asn_len );
- memcpy( p + asn_len, hash, hashlen );
- p[13] = 5; break;
-
- case SIG_RSA_SHA1:
- asn_len = OID_SIZE(ASN1_HASH_SHA1);
- memcpy( p, ASN1_HASH_SHA1, asn_len );
- memcpy( p + 15, hash, hashlen );
- break;
-
- case SIG_RSA_SHA224:
- asn_len = OID_SIZE(ASN1_HASH_SHA2X);
- memcpy( p, ASN1_HASH_SHA2X, asn_len );
- memcpy( p + asn_len, hash, hashlen );
- p[1] += hashlen; p[14] = 4; p[18] += hashlen; break;
-
- case SIG_RSA_SHA256:
- asn_len = OID_SIZE(ASN1_HASH_SHA2X);
- memcpy( p, ASN1_HASH_SHA2X, asn_len );
- memcpy( p + asn_len, hash, hashlen );
- p[1] += hashlen; p[14] = 1; p[18] += hashlen; break;
-
- case SIG_RSA_SHA384:
- asn_len = OID_SIZE(ASN1_HASH_SHA2X);
- memcpy( p, ASN1_HASH_SHA2X, asn_len );
- memcpy( p + asn_len, hash, hashlen );
- p[1] += hashlen; p[14] = 2; p[18] += hashlen; break;
-
- case SIG_RSA_SHA512:
- asn_len = OID_SIZE(ASN1_HASH_SHA2X);
- memcpy( p, ASN1_HASH_SHA2X, asn_len );
- memcpy( p + asn_len, hash, hashlen );
- p[1] += hashlen; p[14] = 3; p[18] += hashlen; break;
-
- default:
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
- asn_len + hashlen, sig, &olen ) != CKR_OK )
- {
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- return( 0 );
-}
-
-#endif /* defined(POLARSSL_PKCS11_C) */
diff --git a/polarssl/src/library/rsa.c b/polarssl/src/library/rsa.c
deleted file mode 100644
index 72806e1..0000000
--- a/polarssl/src/library/rsa.c
+++ /dev/null
@@ -1,1219 +0,0 @@
-/*
- * The RSA public-key cryptosystem
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
- *
- * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
- * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_RSA_C)
-
-#include "polarssl/rsa.h"
-#include "polarssl/md.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-/*
- * Initialize an RSA context
- */
-void rsa_init( rsa_context *ctx,
- int padding,
- int hash_id )
-{
- memset( ctx, 0, sizeof( rsa_context ) );
-
- ctx->padding = padding;
- ctx->hash_id = hash_id;
-}
-
-#if defined(POLARSSL_GENPRIME)
-
-/*
- * Generate an RSA keypair
- */
-int rsa_gen_key( rsa_context *ctx,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng,
- unsigned int nbits, int exponent )
-{
- int ret;
- mpi P1, Q1, H, G;
-
- if( f_rng == NULL || nbits < 128 || exponent < 3 )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G );
-
- /*
- * find primes P and Q with Q < P so that:
- * GCD( E, (P-1)*(Q-1) ) == 1
- */
- MPI_CHK( mpi_lset( &ctx->E, exponent ) );
-
- do
- {
- MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
- f_rng, p_rng ) );
-
- MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
- f_rng, p_rng ) );
-
- if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
- mpi_swap( &ctx->P, &ctx->Q );
-
- if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
- continue;
-
- MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
- if( mpi_msb( &ctx->N ) != nbits )
- continue;
-
- MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
- MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
- MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
- MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
- }
- while( mpi_cmp_int( &G, 1 ) != 0 );
-
- /*
- * D = E^-1 mod ((P-1)*(Q-1))
- * DP = D mod (P - 1)
- * DQ = D mod (Q - 1)
- * QP = Q^-1 mod P
- */
- MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
- MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
- MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
- MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
-
- ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
-
-cleanup:
-
- mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G );
-
- if( ret != 0 )
- {
- rsa_free( ctx );
- return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret );
- }
-
- return( 0 );
-}
-
-#endif
-
-/*
- * Check a public RSA key
- */
-int rsa_check_pubkey( const rsa_context *ctx )
-{
- if( !ctx->N.p || !ctx->E.p )
- return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
-
- if( ( ctx->N.p[0] & 1 ) == 0 ||
- ( ctx->E.p[0] & 1 ) == 0 )
- return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
-
- if( mpi_msb( &ctx->N ) < 128 ||
- mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS )
- return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
-
- if( mpi_msb( &ctx->E ) < 2 ||
- mpi_msb( &ctx->E ) > 64 )
- return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
-
- return( 0 );
-}
-
-/*
- * Check a private RSA key
- */
-int rsa_check_privkey( const rsa_context *ctx )
-{
- int ret;
- mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2;
-
- if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
- return( ret );
-
- if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
- return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
-
- mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 );
- mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 );
- mpi_init( &L1 ); mpi_init( &L2 );
-
- MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
- MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
- MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
- MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
- MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
- MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
-
- MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
- MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
- MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) );
-
- /*
- * Check for a valid PKCS1v2 private key
- */
- if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
- mpi_cmp_int( &L2, 0 ) != 0 ||
- mpi_cmp_int( &I, 1 ) != 0 ||
- mpi_cmp_int( &G, 1 ) != 0 )
- {
- ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED;
- }
-
-
-cleanup:
-
- mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 );
- mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 );
- mpi_free( &L1 ); mpi_free( &L2 );
-
- if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED )
- return( ret );
-
- if( ret != 0 )
- return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret );
-
- return( 0 );
-}
-
-/*
- * Do an RSA public key operation
- */
-int rsa_public( rsa_context *ctx,
- const unsigned char *input,
- unsigned char *output )
-{
- int ret;
- size_t olen;
- mpi T;
-
- mpi_init( &T );
-
- MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
-
- if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
- {
- mpi_free( &T );
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- olen = ctx->len;
- MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
- MPI_CHK( mpi_write_binary( &T, output, olen ) );
-
-cleanup:
-
- mpi_free( &T );
-
- if( ret != 0 )
- return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );
-
- return( 0 );
-}
-
-/*
- * Do an RSA private key operation
- */
-int rsa_private( rsa_context *ctx,
- const unsigned char *input,
- unsigned char *output )
-{
- int ret;
- size_t olen;
- mpi T, T1, T2;
-
- mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
-
- MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
-
- if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
- {
- mpi_free( &T );
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
-#if defined(POLARSSL_RSA_NO_CRT)
- MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
-#else
- /*
- * faster decryption using the CRT
- *
- * T1 = input ^ dP mod P
- * T2 = input ^ dQ mod Q
- */
- MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
- MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
-
- /*
- * T = (T1 - T2) * (Q^-1 mod P) mod P
- */
- MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
- MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
- MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
-
- /*
- * output = T2 + T * Q
- */
- MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
- MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
-#endif
-
- olen = ctx->len;
- MPI_CHK( mpi_write_binary( &T, output, olen ) );
-
-cleanup:
-
- mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
-
- if( ret != 0 )
- return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
-
- return( 0 );
-}
-
-#if defined(POLARSSL_PKCS1_V21)
-/**
- * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
- *
- * \param dst buffer to mask
- * \param dlen length of destination buffer
- * \param src source of the mask generation
- * \param slen length of the source buffer
- * \param md_ctx message digest context to use
- */
-static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen,
- md_context_t *md_ctx )
-{
- unsigned char mask[POLARSSL_MD_MAX_SIZE];
- unsigned char counter[4];
- unsigned char *p;
- unsigned int hlen;
- size_t i, use_len;
-
- memset( mask, 0, POLARSSL_MD_MAX_SIZE );
- memset( counter, 0, 4 );
-
- hlen = md_ctx->md_info->size;
-
- // Generate and apply dbMask
- //
- p = dst;
-
- while( dlen > 0 )
- {
- use_len = hlen;
- if( dlen < hlen )
- use_len = dlen;
-
- md_starts( md_ctx );
- md_update( md_ctx, src, slen );
- md_update( md_ctx, counter, 4 );
- md_finish( md_ctx, mask );
-
- for( i = 0; i < use_len; ++i )
- *p++ ^= mask[i];
-
- counter[3]++;
-
- dlen -= use_len;
- }
-}
-#endif
-
-/*
- * Add the message padding, then do an RSA operation
- */
-int rsa_pkcs1_encrypt( rsa_context *ctx,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng,
- int mode, size_t ilen,
- const unsigned char *input,
- unsigned char *output )
-{
- size_t nb_pad, olen;
- int ret;
- unsigned char *p = output;
-#if defined(POLARSSL_PKCS1_V21)
- unsigned int hlen;
- const md_info_t *md_info;
- md_context_t md_ctx;
-#endif
-
- olen = ctx->len;
-
- if( f_rng == NULL )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- switch( ctx->padding )
- {
- case RSA_PKCS_V15:
-
- if( olen < ilen + 11 )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- nb_pad = olen - 3 - ilen;
-
- *p++ = 0;
- *p++ = RSA_CRYPT;
-
- while( nb_pad-- > 0 )
- {
- int rng_dl = 100;
-
- do {
- ret = f_rng( p_rng, p, 1 );
- } while( *p == 0 && --rng_dl && ret == 0 );
-
- // Check if RNG failed to generate data
- //
- if( rng_dl == 0 || ret != 0)
- return POLARSSL_ERR_RSA_RNG_FAILED + ret;
-
- p++;
- }
- *p++ = 0;
- memcpy( p, input, ilen );
- break;
-
-#if defined(POLARSSL_PKCS1_V21)
- case RSA_PKCS_V21:
-
- md_info = md_info_from_type( ctx->hash_id );
- if( md_info == NULL )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- hlen = md_get_size( md_info );
-
- if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- memset( output, 0, olen );
- memset( &md_ctx, 0, sizeof( md_context_t ) );
-
- md_init_ctx( &md_ctx, md_info );
-
- *p++ = 0;
-
- // Generate a random octet string seed
- //
- if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
- return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
-
- p += hlen;
-
- // Construct DB
- //
- md( md_info, p, 0, p );
- p += hlen;
- p += olen - 2 * hlen - 2 - ilen;
- *p++ = 1;
- memcpy( p, input, ilen );
-
- // maskedDB: Apply dbMask to DB
- //
- mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
- &md_ctx );
-
- // maskedSeed: Apply seedMask to seed
- //
- mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
- &md_ctx );
- break;
-#endif
-
- default:
-
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
- }
-
- return( ( mode == RSA_PUBLIC )
- ? rsa_public( ctx, output, output )
- : rsa_private( ctx, output, output ) );
-}
-
-/*
- * Do an RSA operation, then remove the message padding
- */
-int rsa_pkcs1_decrypt( rsa_context *ctx,
- int mode, size_t *olen,
- const unsigned char *input,
- unsigned char *output,
- size_t output_max_len)
-{
- int ret;
- size_t ilen;
- unsigned char *p;
- unsigned char buf[1024];
-#if defined(POLARSSL_PKCS1_V21)
- unsigned char lhash[POLARSSL_MD_MAX_SIZE];
- unsigned int hlen;
- const md_info_t *md_info;
- md_context_t md_ctx;
-#endif
-
- ilen = ctx->len;
-
- if( ilen < 16 || ilen > sizeof( buf ) )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- ret = ( mode == RSA_PUBLIC )
- ? rsa_public( ctx, input, buf )
- : rsa_private( ctx, input, buf );
-
- if( ret != 0 )
- return( ret );
-
- p = buf;
-
- switch( ctx->padding )
- {
- case RSA_PKCS_V15:
-
- if( *p++ != 0 || *p++ != RSA_CRYPT )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- while( *p != 0 )
- {
- if( p >= buf + ilen - 1 )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
- p++;
- }
- p++;
- break;
-
-#if defined(POLARSSL_PKCS1_V21)
- case RSA_PKCS_V21:
-
- if( *p++ != 0 )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- md_info = md_info_from_type( ctx->hash_id );
- if( md_info == NULL )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- hlen = md_get_size( md_info );
- memset( &md_ctx, 0, sizeof( md_context_t ) );
-
- md_init_ctx( &md_ctx, md_info );
-
- // Generate lHash
- //
- md( md_info, lhash, 0, lhash );
-
- // seed: Apply seedMask to maskedSeed
- //
- mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
- &md_ctx );
-
- // DB: Apply dbMask to maskedDB
- //
- mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
- &md_ctx );
-
- p += hlen;
-
- // Check validity
- //
- if( memcmp( lhash, p, hlen ) != 0 )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- p += hlen;
-
- while( *p == 0 && p < buf + ilen )
- p++;
-
- if( p == buf + ilen )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- if( *p++ != 0x01 )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- break;
-#endif
-
- default:
-
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
- }
-
- if (ilen - (p - buf) > output_max_len)
- return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
-
- *olen = ilen - (p - buf);
- memcpy( output, p, *olen );
-
- return( 0 );
-}
-
-/*
- * Do an RSA operation to sign the message digest
- */
-int rsa_pkcs1_sign( rsa_context *ctx,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng,
- int mode,
- int hash_id,
- unsigned int hashlen,
- const unsigned char *hash,
- unsigned char *sig )
-{
- size_t nb_pad, olen;
- unsigned char *p = sig;
-#if defined(POLARSSL_PKCS1_V21)
- unsigned char salt[POLARSSL_MD_MAX_SIZE];
- unsigned int slen, hlen, offset = 0;
- int ret;
- size_t msb;
- const md_info_t *md_info;
- md_context_t md_ctx;
-#else
- (void) f_rng;
- (void) p_rng;
-#endif
-
- olen = ctx->len;
-
- switch( ctx->padding )
- {
- case RSA_PKCS_V15:
-
- switch( hash_id )
- {
- case SIG_RSA_RAW:
- nb_pad = olen - 3 - hashlen;
- break;
-
- case SIG_RSA_MD2:
- case SIG_RSA_MD4:
- case SIG_RSA_MD5:
- nb_pad = olen - 3 - 34;
- break;
-
- case SIG_RSA_SHA1:
- nb_pad = olen - 3 - 35;
- break;
-
- case SIG_RSA_SHA224:
- nb_pad = olen - 3 - 47;
- break;
-
- case SIG_RSA_SHA256:
- nb_pad = olen - 3 - 51;
- break;
-
- case SIG_RSA_SHA384:
- nb_pad = olen - 3 - 67;
- break;
-
- case SIG_RSA_SHA512:
- nb_pad = olen - 3 - 83;
- break;
-
-
- default:
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- if( nb_pad < 8 )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- *p++ = 0;
- *p++ = RSA_SIGN;
- memset( p, 0xFF, nb_pad );
- p += nb_pad;
- *p++ = 0;
-
- switch( hash_id )
- {
- case SIG_RSA_RAW:
- memcpy( p, hash, hashlen );
- break;
-
- case SIG_RSA_MD2:
- memcpy( p, ASN1_HASH_MDX, 18 );
- memcpy( p + 18, hash, 16 );
- p[13] = 2; break;
-
- case SIG_RSA_MD4:
- memcpy( p, ASN1_HASH_MDX, 18 );
- memcpy( p + 18, hash, 16 );
- p[13] = 4; break;
-
- case SIG_RSA_MD5:
- memcpy( p, ASN1_HASH_MDX, 18 );
- memcpy( p + 18, hash, 16 );
- p[13] = 5; break;
-
- case SIG_RSA_SHA1:
- memcpy( p, ASN1_HASH_SHA1, 15 );
- memcpy( p + 15, hash, 20 );
- break;
-
- case SIG_RSA_SHA224:
- memcpy( p, ASN1_HASH_SHA2X, 19 );
- memcpy( p + 19, hash, 28 );
- p[1] += 28; p[14] = 4; p[18] += 28; break;
-
- case SIG_RSA_SHA256:
- memcpy( p, ASN1_HASH_SHA2X, 19 );
- memcpy( p + 19, hash, 32 );
- p[1] += 32; p[14] = 1; p[18] += 32; break;
-
- case SIG_RSA_SHA384:
- memcpy( p, ASN1_HASH_SHA2X, 19 );
- memcpy( p + 19, hash, 48 );
- p[1] += 48; p[14] = 2; p[18] += 48; break;
-
- case SIG_RSA_SHA512:
- memcpy( p, ASN1_HASH_SHA2X, 19 );
- memcpy( p + 19, hash, 64 );
- p[1] += 64; p[14] = 3; p[18] += 64; break;
-
- default:
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- break;
-
-#if defined(POLARSSL_PKCS1_V21)
- case RSA_PKCS_V21:
-
- if( f_rng == NULL )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- switch( hash_id )
- {
- case SIG_RSA_MD2:
- case SIG_RSA_MD4:
- case SIG_RSA_MD5:
- hashlen = 16;
- break;
-
- case SIG_RSA_SHA1:
- hashlen = 20;
- break;
-
- case SIG_RSA_SHA224:
- hashlen = 28;
- break;
-
- case SIG_RSA_SHA256:
- hashlen = 32;
- break;
-
- case SIG_RSA_SHA384:
- hashlen = 48;
- break;
-
- case SIG_RSA_SHA512:
- hashlen = 64;
- break;
-
- default:
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- md_info = md_info_from_type( ctx->hash_id );
- if( md_info == NULL )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- hlen = md_get_size( md_info );
- slen = hlen;
-
- memset( sig, 0, olen );
- memset( &md_ctx, 0, sizeof( md_context_t ) );
-
- md_init_ctx( &md_ctx, md_info );
-
- msb = mpi_msb( &ctx->N ) - 1;
-
- // Generate salt of length slen
- //
- if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
- return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
-
- // Note: EMSA-PSS encoding is over the length of N - 1 bits
- //
- msb = mpi_msb( &ctx->N ) - 1;
- p += olen - hlen * 2 - 2;
- *p++ = 0x01;
- memcpy( p, salt, slen );
- p += slen;
-
- // Generate H = Hash( M' )
- //
- md_starts( &md_ctx );
- md_update( &md_ctx, p, 8 );
- md_update( &md_ctx, hash, hashlen );
- md_update( &md_ctx, salt, slen );
- md_finish( &md_ctx, p );
-
- // Compensate for boundary condition when applying mask
- //
- if( msb % 8 == 0 )
- offset = 1;
-
- // maskedDB: Apply dbMask to DB
- //
- mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
-
- msb = mpi_msb( &ctx->N ) - 1;
- sig[0] &= 0xFF >> ( olen * 8 - msb );
-
- p += hlen;
- *p++ = 0xBC;
- break;
-#endif
-
- default:
-
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
- }
-
- return( ( mode == RSA_PUBLIC )
- ? rsa_public( ctx, sig, sig )
- : rsa_private( ctx, sig, sig ) );
-}
-
-/*
- * Do an RSA operation and check the message digest
- */
-int rsa_pkcs1_verify( rsa_context *ctx,
- int mode,
- int hash_id,
- unsigned int hashlen,
- const unsigned char *hash,
- unsigned char *sig )
-{
- int ret;
- size_t len, siglen;
- unsigned char *p, c;
- unsigned char buf[1024];
-#if defined(POLARSSL_PKCS1_V21)
- unsigned char result[POLARSSL_MD_MAX_SIZE];
- unsigned char zeros[8];
- unsigned int hlen;
- size_t slen, msb;
- const md_info_t *md_info;
- md_context_t md_ctx;
-#endif
- siglen = ctx->len;
-
- if( siglen < 16 || siglen > sizeof( buf ) )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- ret = ( mode == RSA_PUBLIC )
- ? rsa_public( ctx, sig, buf )
- : rsa_private( ctx, sig, buf );
-
- if( ret != 0 )
- return( ret );
-
- p = buf;
-
- switch( ctx->padding )
- {
- case RSA_PKCS_V15:
-
- if( *p++ != 0 || *p++ != RSA_SIGN )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- while( *p != 0 )
- {
- if( p >= buf + siglen - 1 || *p != 0xFF )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
- p++;
- }
- p++;
-
- len = siglen - ( p - buf );
-
- if( len == 33 && hash_id == SIG_RSA_SHA1 )
- {
- if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 &&
- memcmp( p + 13, hash, 20 ) == 0 )
- return( 0 );
- else
- return( POLARSSL_ERR_RSA_VERIFY_FAILED );
- }
- if( len == 34 )
- {
- c = p[13];
- p[13] = 0;
-
- if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
- return( POLARSSL_ERR_RSA_VERIFY_FAILED );
-
- if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
- ( c == 4 && hash_id == SIG_RSA_MD4 ) ||
- ( c == 5 && hash_id == SIG_RSA_MD5 ) )
- {
- if( memcmp( p + 18, hash, 16 ) == 0 )
- return( 0 );
- else
- return( POLARSSL_ERR_RSA_VERIFY_FAILED );
- }
- }
-
- if( len == 35 && hash_id == SIG_RSA_SHA1 )
- {
- if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
- memcmp( p + 15, hash, 20 ) == 0 )
- return( 0 );
- else
- return( POLARSSL_ERR_RSA_VERIFY_FAILED );
- }
- if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
- ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
- ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
- ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
- {
- c = p[1] - 17;
- p[1] = 17;
- p[14] = 0;
-
- if( p[18] == c &&
- memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
- memcmp( p + 19, hash, c ) == 0 )
- return( 0 );
- else
- return( POLARSSL_ERR_RSA_VERIFY_FAILED );
- }
-
- if( len == hashlen && hash_id == SIG_RSA_RAW )
- {
- if( memcmp( p, hash, hashlen ) == 0 )
- return( 0 );
- else
- return( POLARSSL_ERR_RSA_VERIFY_FAILED );
- }
-
- break;
-
-#if defined(POLARSSL_PKCS1_V21)
- case RSA_PKCS_V21:
-
- if( buf[siglen - 1] != 0xBC )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- switch( hash_id )
- {
- case SIG_RSA_MD2:
- case SIG_RSA_MD4:
- case SIG_RSA_MD5:
- hashlen = 16;
- break;
-
- case SIG_RSA_SHA1:
- hashlen = 20;
- break;
-
- case SIG_RSA_SHA224:
- hashlen = 28;
- break;
-
- case SIG_RSA_SHA256:
- hashlen = 32;
- break;
-
- case SIG_RSA_SHA384:
- hashlen = 48;
- break;
-
- case SIG_RSA_SHA512:
- hashlen = 64;
- break;
-
- default:
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
- }
-
- md_info = md_info_from_type( ctx->hash_id );
- if( md_info == NULL )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- hlen = md_get_size( md_info );
- slen = siglen - hlen - 1;
-
- memset( &md_ctx, 0, sizeof( md_context_t ) );
- memset( zeros, 0, 8 );
-
- md_init_ctx( &md_ctx, md_info );
-
- // Note: EMSA-PSS verification is over the length of N - 1 bits
- //
- msb = mpi_msb( &ctx->N ) - 1;
-
- // Compensate for boundary condition when applying mask
- //
- if( msb % 8 == 0 )
- {
- p++;
- siglen -= 1;
- }
- if( buf[0] >> ( 8 - siglen * 8 + msb ) )
- return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
- mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
-
- buf[0] &= 0xFF >> ( siglen * 8 - msb );
-
- while( *p == 0 && p < buf + siglen )
- p++;
-
- if( p == buf + siglen )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- if( *p++ != 0x01 )
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
- slen -= p - buf;
-
- // Generate H = Hash( M' )
- //
- md_starts( &md_ctx );
- md_update( &md_ctx, zeros, 8 );
- md_update( &md_ctx, hash, hashlen );
- md_update( &md_ctx, p, slen );
- md_finish( &md_ctx, result );
-
- if( memcmp( p + slen, result, hlen ) == 0 )
- return( 0 );
- else
- return( POLARSSL_ERR_RSA_VERIFY_FAILED );
-#endif
-
- default:
-
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
- }
-
- return( POLARSSL_ERR_RSA_INVALID_PADDING );
-}
-
-/*
- * Free the components of an RSA key
- */
-void rsa_free( rsa_context *ctx )
-{
- mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
- mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
- mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D );
- mpi_free( &ctx->E ); mpi_free( &ctx->N );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include "polarssl/sha1.h"
-
-/*
- * Example RSA-1024 keypair, for test purposes
- */
-#define KEY_LEN 128
-
-#define RSA_N "9292758453063D803DD603D5E777D788" \
- "8ED1D5BF35786190FA2F23EBC0848AEA" \
- "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
- "7130B9CED7ACDF54CFC7555AC14EEBAB" \
- "93A89813FBF3C4F8066D2D800F7C38A8" \
- "1AE31942917403FF4946B0A83D3D3E05" \
- "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
- "5E94BB77B07507233A0BC7BAC8F90F79"
-
-#define RSA_E "10001"
-
-#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
- "66CA472BC44D253102F8B4A9D3BFA750" \
- "91386C0077937FE33FA3252D28855837" \
- "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
- "DF79C5CE07EE72C7F123142198164234" \
- "CABB724CF78B8173B9F880FC86322407" \
- "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
- "071513A1E85B5DFA031F21ECAE91A34D"
-
-#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
- "2C01CAD19EA484A87EA4377637E75500" \
- "FCB2005C5C7DD6EC4AC023CDA285D796" \
- "C3D9E75E1EFC42488BB4F1D13AC30A57"
-
-#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
- "E211C2B9E5DB1ED0BF61D0D9899620F4" \
- "910E4168387E3C30AA1E00C339A79508" \
- "8452DD96A9A5EA5D9DCA68DA636032AF"
-
-#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
- "3C94D22288ACD763FD8E5600ED4A702D" \
- "F84198A5F06C2E72236AE490C93F07F8" \
- "3CC559CD27BC2D1CA488811730BB5725"
-
-#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
- "D8AAEA56749EA28623272E4F7D0592AF" \
- "7C1F1313CAC9471B5C523BFE592F517B" \
- "407A1BD76C164B93DA2D32A383E58357"
-
-#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
- "F38D18D2B2F0E2DD275AA977E2BF4411" \
- "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
- "A74206CEC169D74BF5A8C50D6F48EA08"
-
-#define PT_LEN 24
-#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
- "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
-
-static int myrand( void *rng_state, unsigned char *output, size_t len )
-{
- size_t i;
-
- if( rng_state != NULL )
- rng_state = NULL;
-
- for( i = 0; i < len; ++i )
- output[i] = rand();
-
- return( 0 );
-}
-
-/*
- * Checkup routine
- */
-int rsa_self_test( int verbose )
-{
- size_t len;
- rsa_context rsa;
- unsigned char rsa_plaintext[PT_LEN];
- unsigned char rsa_decrypted[PT_LEN];
- unsigned char rsa_ciphertext[KEY_LEN];
-#if defined(POLARSSL_SHA1_C)
- unsigned char sha1sum[20];
-#endif
-
- rsa_init( &rsa, RSA_PKCS_V15, 0 );
-
- rsa.len = KEY_LEN;
- mpi_read_string( &rsa.N , 16, RSA_N );
- mpi_read_string( &rsa.E , 16, RSA_E );
- mpi_read_string( &rsa.D , 16, RSA_D );
- mpi_read_string( &rsa.P , 16, RSA_P );
- mpi_read_string( &rsa.Q , 16, RSA_Q );
- mpi_read_string( &rsa.DP, 16, RSA_DP );
- mpi_read_string( &rsa.DQ, 16, RSA_DQ );
- mpi_read_string( &rsa.QP, 16, RSA_QP );
-
- if( verbose != 0 )
- printf( " RSA key validation: " );
-
- if( rsa_check_pubkey( &rsa ) != 0 ||
- rsa_check_privkey( &rsa ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n PKCS#1 encryption : " );
-
- memcpy( rsa_plaintext, RSA_PT, PT_LEN );
-
- if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN,
- rsa_plaintext, rsa_ciphertext ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n PKCS#1 decryption : " );
-
- if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
- rsa_ciphertext, rsa_decrypted,
- sizeof(rsa_decrypted) ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
-#if defined(POLARSSL_SHA1_C)
- if( verbose != 0 )
- printf( "passed\n PKCS#1 data sign : " );
-
- sha1( rsa_plaintext, PT_LEN, sha1sum );
-
- if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20,
- sha1sum, rsa_ciphertext ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n PKCS#1 sig. verify: " );
-
- if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20,
- sha1sum, rsa_ciphertext ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n\n" );
-#endif /* POLARSSL_SHA1_C */
-
- rsa_free( &rsa );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/sha1.c b/polarssl/src/library/sha1.c
deleted file mode 100644
index 72ca063..0000000
--- a/polarssl/src/library/sha1.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * FIPS-180-1 compliant SHA-1 implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The SHA-1 standard was published by NIST in 1993.
- *
- * http://www.itl.nist.gov/fipspubs/fip180-1.htm
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SHA1_C)
-
-#include "polarssl/sha1.h"
-
-#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
-#include <stdio.h>
-#endif
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) ); \
-}
-#endif
-
-/*
- * SHA-1 context setup
- */
-void sha1_starts( sha1_context *ctx )
-{
- ctx->total[0] = 0;
- ctx->total[1] = 0;
-
- ctx->state[0] = 0x67452301;
- ctx->state[1] = 0xEFCDAB89;
- ctx->state[2] = 0x98BADCFE;
- ctx->state[3] = 0x10325476;
- ctx->state[4] = 0xC3D2E1F0;
-}
-
-static void sha1_process( sha1_context *ctx, const unsigned char data[64] )
-{
- unsigned long temp, W[16], A, B, C, D, E;
-
- GET_ULONG_BE( W[ 0], data, 0 );
- GET_ULONG_BE( W[ 1], data, 4 );
- GET_ULONG_BE( W[ 2], data, 8 );
- GET_ULONG_BE( W[ 3], data, 12 );
- GET_ULONG_BE( W[ 4], data, 16 );
- GET_ULONG_BE( W[ 5], data, 20 );
- GET_ULONG_BE( W[ 6], data, 24 );
- GET_ULONG_BE( W[ 7], data, 28 );
- GET_ULONG_BE( W[ 8], data, 32 );
- GET_ULONG_BE( W[ 9], data, 36 );
- GET_ULONG_BE( W[10], data, 40 );
- GET_ULONG_BE( W[11], data, 44 );
- GET_ULONG_BE( W[12], data, 48 );
- GET_ULONG_BE( W[13], data, 52 );
- GET_ULONG_BE( W[14], data, 56 );
- GET_ULONG_BE( W[15], data, 60 );
-
-#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
-
-#define R(t) \
-( \
- temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
- W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
- ( W[t & 0x0F] = S(temp,1) ) \
-)
-
-#define P(a,b,c,d,e,x) \
-{ \
- e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
-}
-
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
- E = ctx->state[4];
-
-#define F(x,y,z) (z ^ (x & (y ^ z)))
-#define K 0x5A827999
-
- P( A, B, C, D, E, W[0] );
- P( E, A, B, C, D, W[1] );
- P( D, E, A, B, C, W[2] );
- P( C, D, E, A, B, W[3] );
- P( B, C, D, E, A, W[4] );
- P( A, B, C, D, E, W[5] );
- P( E, A, B, C, D, W[6] );
- P( D, E, A, B, C, W[7] );
- P( C, D, E, A, B, W[8] );
- P( B, C, D, E, A, W[9] );
- P( A, B, C, D, E, W[10] );
- P( E, A, B, C, D, W[11] );
- P( D, E, A, B, C, W[12] );
- P( C, D, E, A, B, W[13] );
- P( B, C, D, E, A, W[14] );
- P( A, B, C, D, E, W[15] );
- P( E, A, B, C, D, R(16) );
- P( D, E, A, B, C, R(17) );
- P( C, D, E, A, B, R(18) );
- P( B, C, D, E, A, R(19) );
-
-#undef K
-#undef F
-
-#define F(x,y,z) (x ^ y ^ z)
-#define K 0x6ED9EBA1
-
- P( A, B, C, D, E, R(20) );
- P( E, A, B, C, D, R(21) );
- P( D, E, A, B, C, R(22) );
- P( C, D, E, A, B, R(23) );
- P( B, C, D, E, A, R(24) );
- P( A, B, C, D, E, R(25) );
- P( E, A, B, C, D, R(26) );
- P( D, E, A, B, C, R(27) );
- P( C, D, E, A, B, R(28) );
- P( B, C, D, E, A, R(29) );
- P( A, B, C, D, E, R(30) );
- P( E, A, B, C, D, R(31) );
- P( D, E, A, B, C, R(32) );
- P( C, D, E, A, B, R(33) );
- P( B, C, D, E, A, R(34) );
- P( A, B, C, D, E, R(35) );
- P( E, A, B, C, D, R(36) );
- P( D, E, A, B, C, R(37) );
- P( C, D, E, A, B, R(38) );
- P( B, C, D, E, A, R(39) );
-
-#undef K
-#undef F
-
-#define F(x,y,z) ((x & y) | (z & (x | y)))
-#define K 0x8F1BBCDC
-
- P( A, B, C, D, E, R(40) );
- P( E, A, B, C, D, R(41) );
- P( D, E, A, B, C, R(42) );
- P( C, D, E, A, B, R(43) );
- P( B, C, D, E, A, R(44) );
- P( A, B, C, D, E, R(45) );
- P( E, A, B, C, D, R(46) );
- P( D, E, A, B, C, R(47) );
- P( C, D, E, A, B, R(48) );
- P( B, C, D, E, A, R(49) );
- P( A, B, C, D, E, R(50) );
- P( E, A, B, C, D, R(51) );
- P( D, E, A, B, C, R(52) );
- P( C, D, E, A, B, R(53) );
- P( B, C, D, E, A, R(54) );
- P( A, B, C, D, E, R(55) );
- P( E, A, B, C, D, R(56) );
- P( D, E, A, B, C, R(57) );
- P( C, D, E, A, B, R(58) );
- P( B, C, D, E, A, R(59) );
-
-#undef K
-#undef F
-
-#define F(x,y,z) (x ^ y ^ z)
-#define K 0xCA62C1D6
-
- P( A, B, C, D, E, R(60) );
- P( E, A, B, C, D, R(61) );
- P( D, E, A, B, C, R(62) );
- P( C, D, E, A, B, R(63) );
- P( B, C, D, E, A, R(64) );
- P( A, B, C, D, E, R(65) );
- P( E, A, B, C, D, R(66) );
- P( D, E, A, B, C, R(67) );
- P( C, D, E, A, B, R(68) );
- P( B, C, D, E, A, R(69) );
- P( A, B, C, D, E, R(70) );
- P( E, A, B, C, D, R(71) );
- P( D, E, A, B, C, R(72) );
- P( C, D, E, A, B, R(73) );
- P( B, C, D, E, A, R(74) );
- P( A, B, C, D, E, R(75) );
- P( E, A, B, C, D, R(76) );
- P( D, E, A, B, C, R(77) );
- P( C, D, E, A, B, R(78) );
- P( B, C, D, E, A, R(79) );
-
-#undef K
-#undef F
-
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
- ctx->state[4] += E;
-}
-
-/*
- * SHA-1 process buffer
- */
-void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
-{
- size_t fill;
- unsigned long left;
-
- if( ilen <= 0 )
- return;
-
- left = ctx->total[0] & 0x3F;
- fill = 64 - left;
-
- ctx->total[0] += (unsigned long) ilen;
- ctx->total[0] &= 0xFFFFFFFF;
-
- if( ctx->total[0] < (unsigned long) ilen )
- ctx->total[1]++;
-
- if( left && ilen >= fill )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, fill );
- sha1_process( ctx, ctx->buffer );
- input += fill;
- ilen -= fill;
- left = 0;
- }
-
- while( ilen >= 64 )
- {
- sha1_process( ctx, input );
- input += 64;
- ilen -= 64;
- }
-
- if( ilen > 0 )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, ilen );
- }
-}
-
-static const unsigned char sha1_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * SHA-1 final digest
- */
-void sha1_finish( sha1_context *ctx, unsigned char output[20] )
-{
- unsigned long last, padn;
- unsigned long high, low;
- unsigned char msglen[8];
-
- high = ( ctx->total[0] >> 29 )
- | ( ctx->total[1] << 3 );
- low = ( ctx->total[0] << 3 );
-
- PUT_ULONG_BE( high, msglen, 0 );
- PUT_ULONG_BE( low, msglen, 4 );
-
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
- sha1_update( ctx, (unsigned char *) sha1_padding, padn );
- sha1_update( ctx, msglen, 8 );
-
- PUT_ULONG_BE( ctx->state[0], output, 0 );
- PUT_ULONG_BE( ctx->state[1], output, 4 );
- PUT_ULONG_BE( ctx->state[2], output, 8 );
- PUT_ULONG_BE( ctx->state[3], output, 12 );
- PUT_ULONG_BE( ctx->state[4], output, 16 );
-}
-
-/*
- * output = SHA-1( input buffer )
- */
-void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
-{
- sha1_context ctx;
-
- sha1_starts( &ctx );
- sha1_update( &ctx, input, ilen );
- sha1_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha1_context ) );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * output = SHA-1( file contents )
- */
-int sha1_file( const char *path, unsigned char output[20] )
-{
- FILE *f;
- size_t n;
- sha1_context ctx;
- unsigned char buf[1024];
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
-
- sha1_starts( &ctx );
-
- while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
- sha1_update( &ctx, buf, n );
-
- sha1_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha1_context ) );
-
- if( ferror( f ) != 0 )
- {
- fclose( f );
- return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
- }
-
- fclose( f );
- return( 0 );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * SHA-1 HMAC context setup
- */
-void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
-{
- size_t i;
- unsigned char sum[20];
-
- if( keylen > 64 )
- {
- sha1( key, keylen, sum );
- keylen = 20;
- key = sum;
- }
-
- memset( ctx->ipad, 0x36, 64 );
- memset( ctx->opad, 0x5C, 64 );
-
- for( i = 0; i < keylen; i++ )
- {
- ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
- ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
- }
-
- sha1_starts( ctx );
- sha1_update( ctx, ctx->ipad, 64 );
-
- memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * SHA-1 HMAC process buffer
- */
-void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
-{
- sha1_update( ctx, input, ilen );
-}
-
-/*
- * SHA-1 HMAC final digest
- */
-void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
-{
- unsigned char tmpbuf[20];
-
- sha1_finish( ctx, tmpbuf );
- sha1_starts( ctx );
- sha1_update( ctx, ctx->opad, 64 );
- sha1_update( ctx, tmpbuf, 20 );
- sha1_finish( ctx, output );
-
- memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * SHA1 HMAC context reset
- */
-void sha1_hmac_reset( sha1_context *ctx )
-{
- sha1_starts( ctx );
- sha1_update( ctx, ctx->ipad, 64 );
-}
-
-/*
- * output = HMAC-SHA-1( hmac key, input buffer )
- */
-void sha1_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[20] )
-{
- sha1_context ctx;
-
- sha1_hmac_starts( &ctx, key, keylen );
- sha1_hmac_update( &ctx, input, ilen );
- sha1_hmac_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha1_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-/*
- * FIPS-180-1 test vectors
- */
-static unsigned char sha1_test_buf[3][57] =
-{
- { "abc" },
- { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
- { "" }
-};
-
-static const int sha1_test_buflen[3] =
-{
- 3, 56, 1000
-};
-
-static const unsigned char sha1_test_sum[3][20] =
-{
- { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
- 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
- { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
- 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
- { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
- 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
-};
-
-/*
- * RFC 2202 test vectors
- */
-static unsigned char sha1_hmac_test_key[7][26] =
-{
- { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
- "\x0B\x0B\x0B\x0B" },
- { "Jefe" },
- { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
- "\xAA\xAA\xAA\xAA" },
- { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
- "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
- { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
- "\x0C\x0C\x0C\x0C" },
- { "" }, /* 0xAA 80 times */
- { "" }
-};
-
-static const int sha1_hmac_test_keylen[7] =
-{
- 20, 4, 20, 25, 20, 80, 80
-};
-
-static unsigned char sha1_hmac_test_buf[7][74] =
-{
- { "Hi There" },
- { "what do ya want for nothing?" },
- { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
- { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
- { "Test With Truncation" },
- { "Test Using Larger Than Block-Size Key - Hash Key First" },
- { "Test Using Larger Than Block-Size Key and Larger"
- " Than One Block-Size Data" }
-};
-
-static const int sha1_hmac_test_buflen[7] =
-{
- 8, 28, 50, 50, 20, 54, 73
-};
-
-static const unsigned char sha1_hmac_test_sum[7][20] =
-{
- { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
- 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
- { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
- 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
- { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
- 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
- { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
- 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
- { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
- 0x7B, 0xE1 },
- { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
- 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
- { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
- 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
-};
-
-/*
- * Checkup routine
- */
-int sha1_self_test( int verbose )
-{
- int i, j, buflen;
- unsigned char buf[1024];
- unsigned char sha1sum[20];
- sha1_context ctx;
-
- /*
- * SHA-1
- */
- for( i = 0; i < 3; i++ )
- {
- if( verbose != 0 )
- printf( " SHA-1 test #%d: ", i + 1 );
-
- sha1_starts( &ctx );
-
- if( i == 2 )
- {
- memset( buf, 'a', buflen = 1000 );
-
- for( j = 0; j < 1000; j++ )
- sha1_update( &ctx, buf, buflen );
- }
- else
- sha1_update( &ctx, sha1_test_buf[i],
- sha1_test_buflen[i] );
-
- sha1_finish( &ctx, sha1sum );
-
- if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- for( i = 0; i < 7; i++ )
- {
- if( verbose != 0 )
- printf( " HMAC-SHA-1 test #%d: ", i + 1 );
-
- if( i == 5 || i == 6 )
- {
- memset( buf, '\xAA', buflen = 80 );
- sha1_hmac_starts( &ctx, buf, buflen );
- }
- else
- sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
- sha1_hmac_test_keylen[i] );
-
- sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
- sha1_hmac_test_buflen[i] );
-
- sha1_hmac_finish( &ctx, sha1sum );
-
- buflen = ( i == 4 ) ? 12 : 20;
-
- if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/sha2.c b/polarssl/src/library/sha2.c
deleted file mode 100644
index 4b5e696..0000000
--- a/polarssl/src/library/sha2.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * FIPS-180-2 compliant SHA-256 implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The SHA-256 Secure Hash Standard was published by NIST in 2002.
- *
- * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SHA2_C)
-
-#include "polarssl/sha2.h"
-
-#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
-#include <stdio.h>
-#endif
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) ); \
-}
-#endif
-
-/*
- * SHA-256 context setup
- */
-void sha2_starts( sha2_context *ctx, int is224 )
-{
- ctx->total[0] = 0;
- ctx->total[1] = 0;
-
- if( is224 == 0 )
- {
- /* SHA-256 */
- ctx->state[0] = 0x6A09E667;
- ctx->state[1] = 0xBB67AE85;
- ctx->state[2] = 0x3C6EF372;
- ctx->state[3] = 0xA54FF53A;
- ctx->state[4] = 0x510E527F;
- ctx->state[5] = 0x9B05688C;
- ctx->state[6] = 0x1F83D9AB;
- ctx->state[7] = 0x5BE0CD19;
- }
- else
- {
- /* SHA-224 */
- ctx->state[0] = 0xC1059ED8;
- ctx->state[1] = 0x367CD507;
- ctx->state[2] = 0x3070DD17;
- ctx->state[3] = 0xF70E5939;
- ctx->state[4] = 0xFFC00B31;
- ctx->state[5] = 0x68581511;
- ctx->state[6] = 0x64F98FA7;
- ctx->state[7] = 0xBEFA4FA4;
- }
-
- ctx->is224 = is224;
-}
-
-static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
-{
- unsigned long temp1, temp2, W[64];
- unsigned long A, B, C, D, E, F, G, H;
-
- GET_ULONG_BE( W[ 0], data, 0 );
- GET_ULONG_BE( W[ 1], data, 4 );
- GET_ULONG_BE( W[ 2], data, 8 );
- GET_ULONG_BE( W[ 3], data, 12 );
- GET_ULONG_BE( W[ 4], data, 16 );
- GET_ULONG_BE( W[ 5], data, 20 );
- GET_ULONG_BE( W[ 6], data, 24 );
- GET_ULONG_BE( W[ 7], data, 28 );
- GET_ULONG_BE( W[ 8], data, 32 );
- GET_ULONG_BE( W[ 9], data, 36 );
- GET_ULONG_BE( W[10], data, 40 );
- GET_ULONG_BE( W[11], data, 44 );
- GET_ULONG_BE( W[12], data, 48 );
- GET_ULONG_BE( W[13], data, 52 );
- GET_ULONG_BE( W[14], data, 56 );
- GET_ULONG_BE( W[15], data, 60 );
-
-#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
-#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
-
-#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
-#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
-
-#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
-#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
-
-#define F0(x,y,z) ((x & y) | (z & (x | y)))
-#define F1(x,y,z) (z ^ (x & (y ^ z)))
-
-#define R(t) \
-( \
- W[t] = S1(W[t - 2]) + W[t - 7] + \
- S0(W[t - 15]) + W[t - 16] \
-)
-
-#define P(a,b,c,d,e,f,g,h,x,K) \
-{ \
- temp1 = h + S3(e) + F1(e,f,g) + K + x; \
- temp2 = S2(a) + F0(a,b,c); \
- d += temp1; h = temp1 + temp2; \
-}
-
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
- E = ctx->state[4];
- F = ctx->state[5];
- G = ctx->state[6];
- H = ctx->state[7];
-
- P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
- P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
- P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
- P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
- P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
- P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
- P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
- P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
- P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
- P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
- P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
- P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
- P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
- P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
- P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
- P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
- P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
- P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
- P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
- P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
- P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
- P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
- P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
- P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
- P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
- P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
- P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
- P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
- P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
- P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
- P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
- P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
- P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
- P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
- P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
- P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
- P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
- P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
- P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
- P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
- P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
- P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
- P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
- P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
- P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
- P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
- P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
- P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
- P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
- P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
- P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
- P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
- P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
- P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
- P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
- P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
- P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
- P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
- P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
- P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
- P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
- P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
- P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
- P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
-
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
- ctx->state[4] += E;
- ctx->state[5] += F;
- ctx->state[6] += G;
- ctx->state[7] += H;
-}
-
-/*
- * SHA-256 process buffer
- */
-void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
-{
- size_t fill;
- unsigned long left;
-
- if( ilen <= 0 )
- return;
-
- left = ctx->total[0] & 0x3F;
- fill = 64 - left;
-
- ctx->total[0] += (unsigned long) ilen;
- ctx->total[0] &= 0xFFFFFFFF;
-
- if( ctx->total[0] < (unsigned long) ilen )
- ctx->total[1]++;
-
- if( left && ilen >= fill )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, fill );
- sha2_process( ctx, ctx->buffer );
- input += fill;
- ilen -= fill;
- left = 0;
- }
-
- while( ilen >= 64 )
- {
- sha2_process( ctx, input );
- input += 64;
- ilen -= 64;
- }
-
- if( ilen > 0 )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, ilen );
- }
-}
-
-static const unsigned char sha2_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * SHA-256 final digest
- */
-void sha2_finish( sha2_context *ctx, unsigned char output[32] )
-{
- unsigned long last, padn;
- unsigned long high, low;
- unsigned char msglen[8];
-
- high = ( ctx->total[0] >> 29 )
- | ( ctx->total[1] << 3 );
- low = ( ctx->total[0] << 3 );
-
- PUT_ULONG_BE( high, msglen, 0 );
- PUT_ULONG_BE( low, msglen, 4 );
-
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
- sha2_update( ctx, (unsigned char *) sha2_padding, padn );
- sha2_update( ctx, msglen, 8 );
-
- PUT_ULONG_BE( ctx->state[0], output, 0 );
- PUT_ULONG_BE( ctx->state[1], output, 4 );
- PUT_ULONG_BE( ctx->state[2], output, 8 );
- PUT_ULONG_BE( ctx->state[3], output, 12 );
- PUT_ULONG_BE( ctx->state[4], output, 16 );
- PUT_ULONG_BE( ctx->state[5], output, 20 );
- PUT_ULONG_BE( ctx->state[6], output, 24 );
-
- if( ctx->is224 == 0 )
- PUT_ULONG_BE( ctx->state[7], output, 28 );
-}
-
-/*
- * output = SHA-256( input buffer )
- */
-void sha2( const unsigned char *input, size_t ilen,
- unsigned char output[32], int is224 )
-{
- sha2_context ctx;
-
- sha2_starts( &ctx, is224 );
- sha2_update( &ctx, input, ilen );
- sha2_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha2_context ) );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * output = SHA-256( file contents )
- */
-int sha2_file( const char *path, unsigned char output[32], int is224 )
-{
- FILE *f;
- size_t n;
- sha2_context ctx;
- unsigned char buf[1024];
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
-
- sha2_starts( &ctx, is224 );
-
- while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
- sha2_update( &ctx, buf, n );
-
- sha2_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha2_context ) );
-
- if( ferror( f ) != 0 )
- {
- fclose( f );
- return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
- }
-
- fclose( f );
- return( 0 );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * SHA-256 HMAC context setup
- */
-void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
- int is224 )
-{
- size_t i;
- unsigned char sum[32];
-
- if( keylen > 64 )
- {
- sha2( key, keylen, sum, is224 );
- keylen = ( is224 ) ? 28 : 32;
- key = sum;
- }
-
- memset( ctx->ipad, 0x36, 64 );
- memset( ctx->opad, 0x5C, 64 );
-
- for( i = 0; i < keylen; i++ )
- {
- ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
- ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
- }
-
- sha2_starts( ctx, is224 );
- sha2_update( ctx, ctx->ipad, 64 );
-
- memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * SHA-256 HMAC process buffer
- */
-void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
-{
- sha2_update( ctx, input, ilen );
-}
-
-/*
- * SHA-256 HMAC final digest
- */
-void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
-{
- int is224, hlen;
- unsigned char tmpbuf[32];
-
- is224 = ctx->is224;
- hlen = ( is224 == 0 ) ? 32 : 28;
-
- sha2_finish( ctx, tmpbuf );
- sha2_starts( ctx, is224 );
- sha2_update( ctx, ctx->opad, 64 );
- sha2_update( ctx, tmpbuf, hlen );
- sha2_finish( ctx, output );
-
- memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * SHA-256 HMAC context reset
- */
-void sha2_hmac_reset( sha2_context *ctx )
-{
- sha2_starts( ctx, ctx->is224 );
- sha2_update( ctx, ctx->ipad, 64 );
-}
-
-/*
- * output = HMAC-SHA-256( hmac key, input buffer )
- */
-void sha2_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[32], int is224 )
-{
- sha2_context ctx;
-
- sha2_hmac_starts( &ctx, key, keylen, is224 );
- sha2_hmac_update( &ctx, input, ilen );
- sha2_hmac_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha2_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-/*
- * FIPS-180-2 test vectors
- */
-static unsigned char sha2_test_buf[3][57] =
-{
- { "abc" },
- { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
- { "" }
-};
-
-static const int sha2_test_buflen[3] =
-{
- 3, 56, 1000
-};
-
-static const unsigned char sha2_test_sum[6][32] =
-{
- /*
- * SHA-224 test vectors
- */
- { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
- 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
- 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
- 0xE3, 0x6C, 0x9D, 0xA7 },
- { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
- 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
- 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
- 0x52, 0x52, 0x25, 0x25 },
- { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
- 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
- 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
- 0x4E, 0xE7, 0xAD, 0x67 },
-
- /*
- * SHA-256 test vectors
- */
- { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
- 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
- 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
- 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
- { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
- 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
- 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
- 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
- { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
- 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
- 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
- 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
-};
-
-/*
- * RFC 4231 test vectors
- */
-static unsigned char sha2_hmac_test_key[7][26] =
-{
- { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
- "\x0B\x0B\x0B\x0B" },
- { "Jefe" },
- { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
- "\xAA\xAA\xAA\xAA" },
- { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
- "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
- { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
- "\x0C\x0C\x0C\x0C" },
- { "" }, /* 0xAA 131 times */
- { "" }
-};
-
-static const int sha2_hmac_test_keylen[7] =
-{
- 20, 4, 20, 25, 20, 131, 131
-};
-
-static unsigned char sha2_hmac_test_buf[7][153] =
-{
- { "Hi There" },
- { "what do ya want for nothing?" },
- { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
- { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
- { "Test With Truncation" },
- { "Test Using Larger Than Block-Size Key - Hash Key First" },
- { "This is a test using a larger than block-size key "
- "and a larger than block-size data. The key needs to "
- "be hashed before being used by the HMAC algorithm." }
-};
-
-static const int sha2_hmac_test_buflen[7] =
-{
- 8, 28, 50, 50, 20, 54, 152
-};
-
-static const unsigned char sha2_hmac_test_sum[14][32] =
-{
- /*
- * HMAC-SHA-224 test vectors
- */
- { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
- 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
- 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
- 0x53, 0x68, 0x4B, 0x22 },
- { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
- 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
- 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
- 0x8F, 0xD0, 0x5E, 0x44 },
- { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
- 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
- 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
- 0xEC, 0x83, 0x33, 0xEA },
- { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
- 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
- 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
- 0xE7, 0xAF, 0xEC, 0x5A },
- { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
- 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
- { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
- 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
- 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
- 0x3F, 0xA6, 0x87, 0x0E },
- { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
- 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
- 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
- 0xF6, 0xF5, 0x65, 0xD1 },
-
- /*
- * HMAC-SHA-256 test vectors
- */
- { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
- 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
- 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
- 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
- { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
- 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
- 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
- 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
- { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
- 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
- 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
- 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
- { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
- 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
- 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
- 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
- { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
- 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
- { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
- 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
- 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
- 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
- { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
- 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
- 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
- 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
-};
-
-/*
- * Checkup routine
- */
-int sha2_self_test( int verbose )
-{
- int i, j, k, buflen;
- unsigned char buf[1024];
- unsigned char sha2sum[32];
- sha2_context ctx;
-
- for( i = 0; i < 6; i++ )
- {
- j = i % 3;
- k = i < 3;
-
- if( verbose != 0 )
- printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
-
- sha2_starts( &ctx, k );
-
- if( j == 2 )
- {
- memset( buf, 'a', buflen = 1000 );
-
- for( j = 0; j < 1000; j++ )
- sha2_update( &ctx, buf, buflen );
- }
- else
- sha2_update( &ctx, sha2_test_buf[j],
- sha2_test_buflen[j] );
-
- sha2_finish( &ctx, sha2sum );
-
- if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- for( i = 0; i < 14; i++ )
- {
- j = i % 7;
- k = i < 7;
-
- if( verbose != 0 )
- printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
-
- if( j == 5 || j == 6 )
- {
- memset( buf, '\xAA', buflen = 131 );
- sha2_hmac_starts( &ctx, buf, buflen, k );
- }
- else
- sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
- sha2_hmac_test_keylen[j], k );
-
- sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
- sha2_hmac_test_buflen[j] );
-
- sha2_hmac_finish( &ctx, sha2sum );
-
- buflen = ( j == 4 ) ? 16 : 32 - k * 4;
-
- if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/sha4.c b/polarssl/src/library/sha4.c
deleted file mode 100644
index cf54d11..0000000
--- a/polarssl/src/library/sha4.c
+++ /dev/null
@@ -1,760 +0,0 @@
-/*
- * FIPS-180-2 compliant SHA-384/512 implementation
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The SHA-512 Secure Hash Standard was published by NIST in 2002.
- *
- * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SHA4_C)
-
-#include "polarssl/sha4.h"
-
-#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
-#include <stdio.h>
-#endif
-
-/*
- * 64-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT64_BE
-#define GET_UINT64_BE(n,b,i) \
-{ \
- (n) = ( (unsigned long64) (b)[(i) ] << 56 ) \
- | ( (unsigned long64) (b)[(i) + 1] << 48 ) \
- | ( (unsigned long64) (b)[(i) + 2] << 40 ) \
- | ( (unsigned long64) (b)[(i) + 3] << 32 ) \
- | ( (unsigned long64) (b)[(i) + 4] << 24 ) \
- | ( (unsigned long64) (b)[(i) + 5] << 16 ) \
- | ( (unsigned long64) (b)[(i) + 6] << 8 ) \
- | ( (unsigned long64) (b)[(i) + 7] ); \
-}
-#endif
-
-#ifndef PUT_UINT64_BE
-#define PUT_UINT64_BE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
- (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 7] = (unsigned char) ( (n) ); \
-}
-#endif
-
-/*
- * Round constants
- */
-static const unsigned long64 K[80] =
-{
- UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
- UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
- UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
- UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
- UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
- UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
- UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
- UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
- UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
- UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
- UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
- UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
- UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
- UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
- UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
- UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
- UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
- UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
- UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
- UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
- UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
- UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
- UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
- UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
- UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
- UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
- UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
- UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
- UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
- UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
- UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
- UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
- UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
- UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
- UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
- UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
- UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
- UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
- UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
- UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
-};
-
-/*
- * SHA-512 context setup
- */
-void sha4_starts( sha4_context *ctx, int is384 )
-{
- ctx->total[0] = 0;
- ctx->total[1] = 0;
-
- if( is384 == 0 )
- {
- /* SHA-512 */
- ctx->state[0] = UL64(0x6A09E667F3BCC908);
- ctx->state[1] = UL64(0xBB67AE8584CAA73B);
- ctx->state[2] = UL64(0x3C6EF372FE94F82B);
- ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
- ctx->state[4] = UL64(0x510E527FADE682D1);
- ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
- ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
- ctx->state[7] = UL64(0x5BE0CD19137E2179);
- }
- else
- {
- /* SHA-384 */
- ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
- ctx->state[1] = UL64(0x629A292A367CD507);
- ctx->state[2] = UL64(0x9159015A3070DD17);
- ctx->state[3] = UL64(0x152FECD8F70E5939);
- ctx->state[4] = UL64(0x67332667FFC00B31);
- ctx->state[5] = UL64(0x8EB44A8768581511);
- ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
- ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
- }
-
- ctx->is384 = is384;
-}
-
-static void sha4_process( sha4_context *ctx, const unsigned char data[128] )
-{
- int i;
- unsigned long64 temp1, temp2, W[80];
- unsigned long64 A, B, C, D, E, F, G, H;
-
-#define SHR(x,n) (x >> n)
-#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
-
-#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
-#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
-
-#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
-#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
-
-#define F0(x,y,z) ((x & y) | (z & (x | y)))
-#define F1(x,y,z) (z ^ (x & (y ^ z)))
-
-#define P(a,b,c,d,e,f,g,h,x,K) \
-{ \
- temp1 = h + S3(e) + F1(e,f,g) + K + x; \
- temp2 = S2(a) + F0(a,b,c); \
- d += temp1; h = temp1 + temp2; \
-}
-
- for( i = 0; i < 16; i++ )
- {
- GET_UINT64_BE( W[i], data, i << 3 );
- }
-
- for( ; i < 80; i++ )
- {
- W[i] = S1(W[i - 2]) + W[i - 7] +
- S0(W[i - 15]) + W[i - 16];
- }
-
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
- E = ctx->state[4];
- F = ctx->state[5];
- G = ctx->state[6];
- H = ctx->state[7];
- i = 0;
-
- do
- {
- P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
- P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
- P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
- P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
- P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
- P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
- P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
- P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
- }
- while( i < 80 );
-
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
- ctx->state[4] += E;
- ctx->state[5] += F;
- ctx->state[6] += G;
- ctx->state[7] += H;
-}
-
-/*
- * SHA-512 process buffer
- */
-void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen )
-{
- size_t fill;
- unsigned int left;
-
- if( ilen <= 0 )
- return;
-
- left = (unsigned int) (ctx->total[0] & 0x7F);
- fill = 128 - left;
-
- ctx->total[0] += (unsigned long64) ilen;
-
- if( ctx->total[0] < (unsigned long64) ilen )
- ctx->total[1]++;
-
- if( left && ilen >= fill )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, fill );
- sha4_process( ctx, ctx->buffer );
- input += fill;
- ilen -= fill;
- left = 0;
- }
-
- while( ilen >= 128 )
- {
- sha4_process( ctx, input );
- input += 128;
- ilen -= 128;
- }
-
- if( ilen > 0 )
- {
- memcpy( (void *) (ctx->buffer + left),
- (void *) input, ilen );
- }
-}
-
-static const unsigned char sha4_padding[128] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * SHA-512 final digest
- */
-void sha4_finish( sha4_context *ctx, unsigned char output[64] )
-{
- size_t last, padn;
- unsigned long64 high, low;
- unsigned char msglen[16];
-
- high = ( ctx->total[0] >> 61 )
- | ( ctx->total[1] << 3 );
- low = ( ctx->total[0] << 3 );
-
- PUT_UINT64_BE( high, msglen, 0 );
- PUT_UINT64_BE( low, msglen, 8 );
-
- last = (size_t)( ctx->total[0] & 0x7F );
- padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
-
- sha4_update( ctx, (unsigned char *) sha4_padding, padn );
- sha4_update( ctx, msglen, 16 );
-
- PUT_UINT64_BE( ctx->state[0], output, 0 );
- PUT_UINT64_BE( ctx->state[1], output, 8 );
- PUT_UINT64_BE( ctx->state[2], output, 16 );
- PUT_UINT64_BE( ctx->state[3], output, 24 );
- PUT_UINT64_BE( ctx->state[4], output, 32 );
- PUT_UINT64_BE( ctx->state[5], output, 40 );
-
- if( ctx->is384 == 0 )
- {
- PUT_UINT64_BE( ctx->state[6], output, 48 );
- PUT_UINT64_BE( ctx->state[7], output, 56 );
- }
-}
-
-/*
- * output = SHA-512( input buffer )
- */
-void sha4( const unsigned char *input, size_t ilen,
- unsigned char output[64], int is384 )
-{
- sha4_context ctx;
-
- sha4_starts( &ctx, is384 );
- sha4_update( &ctx, input, ilen );
- sha4_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha4_context ) );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * output = SHA-512( file contents )
- */
-int sha4_file( const char *path, unsigned char output[64], int is384 )
-{
- FILE *f;
- size_t n;
- sha4_context ctx;
- unsigned char buf[1024];
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
-
- sha4_starts( &ctx, is384 );
-
- while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
- sha4_update( &ctx, buf, n );
-
- sha4_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha4_context ) );
-
- if( ferror( f ) != 0 )
- {
- fclose( f );
- return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
- }
-
- fclose( f );
- return( 0 );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * SHA-512 HMAC context setup
- */
-void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
- int is384 )
-{
- size_t i;
- unsigned char sum[64];
-
- if( keylen > 128 )
- {
- sha4( key, keylen, sum, is384 );
- keylen = ( is384 ) ? 48 : 64;
- key = sum;
- }
-
- memset( ctx->ipad, 0x36, 128 );
- memset( ctx->opad, 0x5C, 128 );
-
- for( i = 0; i < keylen; i++ )
- {
- ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
- ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
- }
-
- sha4_starts( ctx, is384 );
- sha4_update( ctx, ctx->ipad, 128 );
-
- memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * SHA-512 HMAC process buffer
- */
-void sha4_hmac_update( sha4_context *ctx,
- const unsigned char *input, size_t ilen )
-{
- sha4_update( ctx, input, ilen );
-}
-
-/*
- * SHA-512 HMAC final digest
- */
-void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] )
-{
- int is384, hlen;
- unsigned char tmpbuf[64];
-
- is384 = ctx->is384;
- hlen = ( is384 == 0 ) ? 64 : 48;
-
- sha4_finish( ctx, tmpbuf );
- sha4_starts( ctx, is384 );
- sha4_update( ctx, ctx->opad, 128 );
- sha4_update( ctx, tmpbuf, hlen );
- sha4_finish( ctx, output );
-
- memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * SHA-512 HMAC context reset
- */
-void sha4_hmac_reset( sha4_context *ctx )
-{
- sha4_starts( ctx, ctx->is384 );
- sha4_update( ctx, ctx->ipad, 128 );
-}
-
-/*
- * output = HMAC-SHA-512( hmac key, input buffer )
- */
-void sha4_hmac( const unsigned char *key, size_t keylen,
- const unsigned char *input, size_t ilen,
- unsigned char output[64], int is384 )
-{
- sha4_context ctx;
-
- sha4_hmac_starts( &ctx, key, keylen, is384 );
- sha4_hmac_update( &ctx, input, ilen );
- sha4_hmac_finish( &ctx, output );
-
- memset( &ctx, 0, sizeof( sha4_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-/*
- * FIPS-180-2 test vectors
- */
-static unsigned char sha4_test_buf[3][113] =
-{
- { "abc" },
- { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
- "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
- { "" }
-};
-
-static const int sha4_test_buflen[3] =
-{
- 3, 112, 1000
-};
-
-static const unsigned char sha4_test_sum[6][64] =
-{
- /*
- * SHA-384 test vectors
- */
- { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
- 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
- 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
- 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
- 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
- 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
- { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
- 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
- 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
- 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
- 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
- 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
- { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
- 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
- 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
- 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
- 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
- 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
-
- /*
- * SHA-512 test vectors
- */
- { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
- 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
- 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
- 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
- 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
- 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
- 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
- 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
- { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
- 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
- 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
- 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
- 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
- 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
- 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
- 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
- { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
- 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
- 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
- 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
- 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
- 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
- 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
- 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
-};
-
-/*
- * RFC 4231 test vectors
- */
-static unsigned char sha4_hmac_test_key[7][26] =
-{
- { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
- "\x0B\x0B\x0B\x0B" },
- { "Jefe" },
- { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
- "\xAA\xAA\xAA\xAA" },
- { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
- "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
- { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
- "\x0C\x0C\x0C\x0C" },
- { "" }, /* 0xAA 131 times */
- { "" }
-};
-
-static const int sha4_hmac_test_keylen[7] =
-{
- 20, 4, 20, 25, 20, 131, 131
-};
-
-static unsigned char sha4_hmac_test_buf[7][153] =
-{
- { "Hi There" },
- { "what do ya want for nothing?" },
- { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
- "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
- { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
- "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
- { "Test With Truncation" },
- { "Test Using Larger Than Block-Size Key - Hash Key First" },
- { "This is a test using a larger than block-size key "
- "and a larger than block-size data. The key needs to "
- "be hashed before being used by the HMAC algorithm." }
-};
-
-static const int sha4_hmac_test_buflen[7] =
-{
- 8, 28, 50, 50, 20, 54, 152
-};
-
-static const unsigned char sha4_hmac_test_sum[14][64] =
-{
- /*
- * HMAC-SHA-384 test vectors
- */
- { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62,
- 0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F,
- 0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6,
- 0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C,
- 0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F,
- 0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 },
- { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31,
- 0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B,
- 0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47,
- 0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E,
- 0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7,
- 0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 },
- { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A,
- 0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F,
- 0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB,
- 0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B,
- 0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9,
- 0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 },
- { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85,
- 0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7,
- 0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C,
- 0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E,
- 0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79,
- 0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB },
- { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23,
- 0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 },
- { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90,
- 0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4,
- 0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F,
- 0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6,
- 0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82,
- 0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 },
- { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D,
- 0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C,
- 0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A,
- 0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5,
- 0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D,
- 0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E },
-
- /*
- * HMAC-SHA-512 test vectors
- */
- { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D,
- 0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0,
- 0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78,
- 0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE,
- 0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02,
- 0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4,
- 0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70,
- 0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 },
- { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2,
- 0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3,
- 0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6,
- 0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54,
- 0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A,
- 0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD,
- 0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B,
- 0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 },
- { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84,
- 0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9,
- 0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36,
- 0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39,
- 0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8,
- 0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07,
- 0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26,
- 0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB },
- { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69,
- 0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7,
- 0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D,
- 0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB,
- 0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4,
- 0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63,
- 0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D,
- 0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD },
- { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53,
- 0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 },
- { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB,
- 0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4,
- 0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1,
- 0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52,
- 0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98,
- 0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52,
- 0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC,
- 0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 },
- { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA,
- 0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD,
- 0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86,
- 0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44,
- 0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1,
- 0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15,
- 0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60,
- 0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 }
-};
-
-/*
- * Checkup routine
- */
-int sha4_self_test( int verbose )
-{
- int i, j, k, buflen;
- unsigned char buf[1024];
- unsigned char sha4sum[64];
- sha4_context ctx;
-
- for( i = 0; i < 6; i++ )
- {
- j = i % 3;
- k = i < 3;
-
- if( verbose != 0 )
- printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
-
- sha4_starts( &ctx, k );
-
- if( j == 2 )
- {
- memset( buf, 'a', buflen = 1000 );
-
- for( j = 0; j < 1000; j++ )
- sha4_update( &ctx, buf, buflen );
- }
- else
- sha4_update( &ctx, sha4_test_buf[j],
- sha4_test_buflen[j] );
-
- sha4_finish( &ctx, sha4sum );
-
- if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- for( i = 0; i < 14; i++ )
- {
- j = i % 7;
- k = i < 7;
-
- if( verbose != 0 )
- printf( " HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
-
- if( j == 5 || j == 6 )
- {
- memset( buf, '\xAA', buflen = 131 );
- sha4_hmac_starts( &ctx, buf, buflen, k );
- }
- else
- sha4_hmac_starts( &ctx, sha4_hmac_test_key[j],
- sha4_hmac_test_keylen[j], k );
-
- sha4_hmac_update( &ctx, sha4_hmac_test_buf[j],
- sha4_hmac_test_buflen[j] );
-
- sha4_hmac_finish( &ctx, sha4sum );
-
- buflen = ( j == 4 ) ? 16 : 64 - k * 16;
-
- if( memcmp( sha4sum, sha4_hmac_test_sum[i], buflen ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/ssl_cli.c b/polarssl/src/library/ssl_cli.c
deleted file mode 100644
index 99120d5..0000000
--- a/polarssl/src/library/ssl_cli.c
+++ /dev/null
@@ -1,1130 +0,0 @@
-/*
- * SSLv3/TLSv1 client-side functions
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SSL_CLI_C)
-
-#include "polarssl/debug.h"
-#include "polarssl/ssl.h"
-
-#if defined(POLARSSL_PKCS11_C)
-#include "polarssl/pkcs11.h"
-#endif /* defined(POLARSSL_PKCS11_C) */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-#if defined(POLARSSL_SHA4_C)
-#include "polarssl/sha4.h"
-#endif
-
-static int ssl_write_client_hello( ssl_context *ssl )
-{
- int ret;
- size_t i, n, ext_len = 0;
- unsigned char *buf;
- unsigned char *p;
- time_t t;
- unsigned char sig_alg_list[20];
- size_t sig_alg_len = 0;
-
- SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
-
- ssl->major_ver = SSL_MAJOR_VERSION_3;
- ssl->minor_ver = SSL_MINOR_VERSION_0;
-
- if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 )
- {
- ssl->max_major_ver = SSL_MAJOR_VERSION_3;
- ssl->max_minor_ver = SSL_MINOR_VERSION_3;
- }
-
- /*
- * 0 . 0 handshake type
- * 1 . 3 handshake length
- * 4 . 5 highest version supported
- * 6 . 9 current UNIX time
- * 10 . 37 random bytes
- */
- buf = ssl->out_msg;
- p = buf + 4;
-
- *p++ = (unsigned char) ssl->max_major_ver;
- *p++ = (unsigned char) ssl->max_minor_ver;
-
- SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
- buf[4], buf[5] ) );
-
- t = time( NULL );
- *p++ = (unsigned char)( t >> 24 );
- *p++ = (unsigned char)( t >> 16 );
- *p++ = (unsigned char)( t >> 8 );
- *p++ = (unsigned char)( t );
-
- SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
-
- if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
- return( ret );
-
- p += 28;
-
- memcpy( ssl->randbytes, buf + 6, 32 );
-
- SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 );
-
- /*
- * 38 . 38 session id length
- * 39 . 39+n session id
- * 40+n . 41+n ciphersuitelist length
- * 42+n . .. ciphersuitelist
- * .. . .. compression methods length
- * .. . .. compression methods
- * .. . .. extensions length
- * .. . .. extensions
- */
- n = ssl->session->length;
-
- if( n < 16 || n > 32 || ssl->resume == 0 ||
- ( ssl->timeout != 0 && t - ssl->session->start > ssl->timeout ) )
- n = 0;
-
- *p++ = (unsigned char) n;
-
- for( i = 0; i < n; i++ )
- *p++ = ssl->session->id[i];
-
- SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
- SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n );
-
- for( n = 0; ssl->ciphersuites[n] != 0; n++ );
- *p++ = (unsigned char)( n >> 7 );
- *p++ = (unsigned char)( n << 1 );
-
- SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
-
- for( i = 0; i < n; i++ )
- {
- SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d",
- ssl->ciphersuites[i] ) );
-
- *p++ = (unsigned char)( ssl->ciphersuites[i] >> 8 );
- *p++ = (unsigned char)( ssl->ciphersuites[i] );
- }
-
- SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
- SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", 0 ) );
-
- *p++ = 1;
- *p++ = SSL_COMPRESS_NULL;
-
- if ( ssl->hostname != NULL )
- {
- SSL_DEBUG_MSG( 3, ( "client hello, prepping for server name extension: %s",
- ssl->hostname ) );
-
- ext_len += ssl->hostname_len + 9;
- }
-
- /*
- * Prepare signature_algorithms extension (TLS 1.2)
- */
- if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 )
- {
-#if defined(POLARSSL_SHA4_C)
- sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512;
- sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
- sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384;
- sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
-#endif
-#if defined(POLARSSL_SHA2_C)
- sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256;
- sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
- sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224;
- sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
-#endif
-#if defined(POLARSSL_SHA1_C)
- sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1;
- sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
-#endif
-#if defined(POLARSSL_MD5_C)
- sig_alg_list[sig_alg_len++] = SSL_HASH_MD5;
- sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
-#endif
- ext_len = 6 + sig_alg_len;
- }
-
- SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
- ext_len ) );
-
- *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( ext_len ) & 0xFF );
-
- if ( ssl->hostname != NULL )
- {
- /*
- * struct {
- * NameType name_type;
- * select (name_type) {
- * case host_name: HostName;
- * } name;
- * } ServerName;
- *
- * enum {
- * host_name(0), (255)
- * } NameType;
- *
- * opaque HostName<1..2^16-1>;
- *
- * struct {
- * ServerName server_name_list<1..2^16-1>
- * } ServerNameList;
- */
- SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
- ssl->hostname ) );
-
- *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME ) & 0xFF );
-
- *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( (ssl->hostname_len + 5) ) & 0xFF );
-
- *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( (ssl->hostname_len + 3) ) & 0xFF );
-
- *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
- *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF );
-
- memcpy( p, ssl->hostname, ssl->hostname_len );
-
- p += ssl->hostname_len;
- }
-
- if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 )
- {
- /*
- * enum {
- * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- * sha512(6), (255)
- * } HashAlgorithm;
- *
- * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- * SignatureAlgorithm;
- *
- * struct {
- * HashAlgorithm hash;
- * SignatureAlgorithm signature;
- * } SignatureAndHashAlgorithm;
- *
- * SignatureAndHashAlgorithm
- * supported_signature_algorithms<2..2^16-2>;
- */
- SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
-
- *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG ) & 0xFF );
-
- *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF );
-
- *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF );
-
- memcpy( p, sig_alg_list, sig_alg_len );
-
- p += sig_alg_len;
- }
-
- ssl->out_msglen = p - buf;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_CLIENT_HELLO;
-
- ssl->state++;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
-
- return( 0 );
-}
-
-static int ssl_parse_server_hello( ssl_context *ssl )
-{
-#if defined(POLARSSL_DEBUG_C)
- time_t t;
-#endif
- int ret, i;
- size_t n;
- int ext_len;
- unsigned char *buf;
-
- SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
-
- /*
- * 0 . 0 handshake type
- * 1 . 3 handshake length
- * 4 . 5 protocol version
- * 6 . 9 UNIX time()
- * 10 . 37 random bytes
- */
- buf = ssl->in_msg;
-
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
- buf[4], buf[5] ) );
-
- if( ssl->in_hslen < 42 ||
- buf[0] != SSL_HS_SERVER_HELLO ||
- buf[4] != SSL_MAJOR_VERSION_3 )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
- }
-
- if( buf[5] > ssl->max_minor_ver )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
- }
-
- ssl->minor_ver = buf[5];
-
-#if defined(POLARSSL_DEBUG_C)
- t = ( (time_t) buf[6] << 24 )
- | ( (time_t) buf[7] << 16 )
- | ( (time_t) buf[8] << 8 )
- | ( (time_t) buf[9] );
-#endif
-
- memcpy( ssl->randbytes + 32, buf + 6, 32 );
-
- n = buf[38];
-
- SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
- SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
-
- /*
- * 38 . 38 session id length
- * 39 . 38+n session id
- * 39+n . 40+n chosen ciphersuite
- * 41+n . 41+n chosen compression alg.
- * 42+n . 43+n extensions length
- * 44+n . 44+n+m extensions
- */
- if( n > 32 || ssl->in_hslen > 42 + n )
- {
- ext_len = ( ( buf[42 + n] << 8 )
- | ( buf[43 + n] ) ) + 2;
- }
- else
- {
- ext_len = 0;
- }
-
- if( n > 32 || ssl->in_hslen != 42 + n + ext_len )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
- }
-
- i = ( buf[39 + n] << 8 ) | buf[40 + n];
-
- /*
- * Initialize update checksum functions
- */
- ssl_kickstart_checksum( ssl, i, buf, ssl->in_hslen );
-
- SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
- SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
-
- /*
- * Check if the session can be resumed
- */
- if( ssl->resume == 0 || n == 0 ||
- ssl->session->ciphersuite != i ||
- ssl->session->length != n ||
- memcmp( ssl->session->id, buf + 39, n ) != 0 )
- {
- ssl->state++;
- ssl->resume = 0;
- ssl->session->start = time( NULL );
- ssl->session->ciphersuite = i;
- ssl->session->length = n;
- memcpy( ssl->session->id, buf + 39, n );
- }
- else
- {
- ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
-
- if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
- return( ret );
- }
- }
-
- SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
- ssl->resume ? "a" : "no" ) );
-
- SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) );
- SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) );
-
- i = 0;
- while( 1 )
- {
- if( ssl->ciphersuites[i] == 0 )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
- }
-
- if( ssl->ciphersuites[i++] == ssl->session->ciphersuite )
- break;
- }
-
- if( buf[41 + n] != SSL_COMPRESS_NULL )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
- }
-
- /* TODO: Process extensions */
-
- SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
-
- return( 0 );
-}
-
-static int ssl_parse_server_key_exchange( ssl_context *ssl )
-{
-#if defined(POLARSSL_DHM_C)
- int ret;
- size_t n;
- unsigned char *p, *end;
- unsigned char hash[64];
- md5_context md5;
- sha1_context sha1;
- int hash_id = SIG_RSA_RAW;
- unsigned int hashlen = 0;
-#endif
-
- SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
-
- if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
- ssl->state++;
- return( 0 );
- }
-
-#if !defined(POLARSSL_DHM_C)
- SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-#else
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE )
- {
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- }
-
- SSL_DEBUG_BUF( 3, "server key exchange", ssl->in_msg + 4, ssl->in_hslen - 4 );
-
- /*
- * Ephemeral DH parameters:
- *
- * struct {
- * opaque dh_p<1..2^16-1>;
- * opaque dh_g<1..2^16-1>;
- * opaque dh_Ys<1..2^16-1>;
- * } ServerDHParams;
- */
- p = ssl->in_msg + 4;
- end = ssl->in_msg + ssl->in_hslen;
-
- if( ( ret = dhm_read_params( &ssl->dhm_ctx, &p, end ) ) != 0 )
- {
- SSL_DEBUG_MSG( 2, ( "DHM Read Params returned -0x%x", -ret ) );
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- }
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
- {
- if( p[1] != SSL_SIG_RSA )
- {
- SSL_DEBUG_MSG( 2, ( "Server used unsupported SignatureAlgorithm %d", p[1] ) );
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- }
-
- switch( p[0] )
- {
-#if defined(POLARSSL_MD5_C)
- case SSL_HASH_MD5:
- hash_id = SIG_RSA_MD5;
- break;
-#endif
-#if defined(POLARSSL_SHA1_C)
- case SSL_HASH_SHA1:
- hash_id = SIG_RSA_SHA1;
- break;
-#endif
-#if defined(POLARSSL_SHA2_C)
- case SSL_HASH_SHA224:
- hash_id = SIG_RSA_SHA224;
- break;
- case SSL_HASH_SHA256:
- hash_id = SIG_RSA_SHA256;
- break;
-#endif
-#if defined(POLARSSL_SHA4_C)
- case SSL_HASH_SHA384:
- hash_id = SIG_RSA_SHA384;
- break;
- case SSL_HASH_SHA512:
- hash_id = SIG_RSA_SHA512;
- break;
-#endif
- default:
- SSL_DEBUG_MSG( 2, ( "Server used unsupported HashAlgorithm %d", p[0] ) );
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- }
-
- SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", p[1] ) );
- SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", p[0] ) );
- p += 2;
- }
-
- n = ( p[0] << 8 ) | p[1];
- p += 2;
-
- if( end != p + n )
- {
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- }
-
- if( (unsigned int)( end - p ) != ssl->peer_cert->rsa.len )
- {
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- }
-
- if( ssl->dhm_ctx.len < 64 || ssl->dhm_ctx.len > 512 )
- {
- SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- }
-
- SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P );
- SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
- SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
-
- if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
- {
- /*
- * digitally-signed struct {
- * opaque md5_hash[16];
- * opaque sha_hash[20];
- * };
- *
- * md5_hash
- * MD5(ClientHello.random + ServerHello.random
- * + ServerParams);
- * sha_hash
- * SHA(ClientHello.random + ServerHello.random
- * + ServerParams);
- */
- n = ssl->in_hslen - ( end - p ) - 6;
-
- md5_starts( &md5 );
- md5_update( &md5, ssl->randbytes, 64 );
- md5_update( &md5, ssl->in_msg + 4, n );
- md5_finish( &md5, hash );
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, ssl->randbytes, 64 );
- sha1_update( &sha1, ssl->in_msg + 4, n );
- sha1_finish( &sha1, hash + 16 );
-
- hash_id = SIG_RSA_RAW;
- hashlen = 36;
- }
- else
- {
- sha2_context sha2;
- sha4_context sha4;
-
- n = ssl->in_hslen - ( end - p ) - 8;
-
- /*
- * digitally-signed struct {
- * opaque client_random[32];
- * opaque server_random[32];
- * ServerDHParams params;
- * };
- */
- switch( hash_id )
- {
-#if defined(POLARSSL_MD5_C)
- case SIG_RSA_MD5:
- md5_starts( &md5 );
- md5_update( &md5, ssl->randbytes, 64 );
- md5_update( &md5, ssl->in_msg + 4, n );
- md5_finish( &md5, hash );
- hashlen = 16;
- break;
-#endif
-#if defined(POLARSSL_SHA1_C)
- case SIG_RSA_SHA1:
- sha1_starts( &sha1 );
- sha1_update( &sha1, ssl->randbytes, 64 );
- sha1_update( &sha1, ssl->in_msg + 4, n );
- sha1_finish( &sha1, hash );
- hashlen = 20;
- break;
-#endif
-#if defined(POLARSSL_SHA2_C)
- case SIG_RSA_SHA224:
- sha2_starts( &sha2, 1 );
- sha2_update( &sha2, ssl->randbytes, 64 );
- sha2_update( &sha2, ssl->in_msg + 4, n );
- sha2_finish( &sha2, hash );
- hashlen = 28;
- break;
- case SIG_RSA_SHA256:
- sha2_starts( &sha2, 0 );
- sha2_update( &sha2, ssl->randbytes, 64 );
- sha2_update( &sha2, ssl->in_msg + 4, n );
- sha2_finish( &sha2, hash );
- hashlen = 32;
- break;
-#endif
-#if defined(POLARSSL_SHA4_C)
- case SIG_RSA_SHA384:
- sha4_starts( &sha4, 1 );
- sha4_update( &sha4, ssl->randbytes, 64 );
- sha4_update( &sha4, ssl->in_msg + 4, n );
- sha4_finish( &sha4, hash );
- hashlen = 48;
- break;
- case SIG_RSA_SHA512:
- sha4_starts( &sha4, 0 );
- sha4_update( &sha4, ssl->randbytes, 64 );
- sha4_update( &sha4, ssl->in_msg + 4, n );
- sha4_finish( &sha4, hash );
- hashlen = 64;
- break;
-#endif
- }
- }
-
- SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
-
- if( ( ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
- hash_id, hashlen, hash, p ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
- return( ret );
- }
-
- ssl->state++;
-
- SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
-
- return( 0 );
-#endif
-}
-
-static int ssl_parse_certificate_request( ssl_context *ssl )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
-
- /*
- * 0 . 0 handshake type
- * 1 . 3 handshake length
- * 4 . 5 SSL version
- * 6 . 6 cert type count
- * 7 .. n-1 cert types
- * n .. n+1 length of all DNs
- * n+2 .. n+3 length of DN 1
- * n+4 .. ... Distinguished Name #1
- * ... .. ... length of DN 2, etc.
- */
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- ssl->client_auth = 0;
- ssl->state++;
-
- if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST )
- ssl->client_auth++;
-
- SSL_DEBUG_MSG( 3, ( "got %s certificate request",
- ssl->client_auth ? "a" : "no" ) );
-
- SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
-
- return( 0 );
-}
-
-static int ssl_parse_server_hello_done( ssl_context *ssl )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
-
- if( ssl->client_auth != 0 )
- {
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
- }
-
- if( ssl->in_hslen != 4 ||
- ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE )
- {
- SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
- }
-
- ssl->state++;
-
- SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
-
- return( 0 );
-}
-
-static int ssl_write_client_key_exchange( ssl_context *ssl )
-{
- int ret;
- size_t i, n;
-
- SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
-
- if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
-#if !defined(POLARSSL_DHM_C)
- SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-#else
- /*
- * DHM key exchange -- send G^X mod P
- */
- n = ssl->dhm_ctx.len;
-
- ssl->out_msg[4] = (unsigned char)( n >> 8 );
- ssl->out_msg[5] = (unsigned char)( n );
- i = 6;
-
- ret = dhm_make_public( &ssl->dhm_ctx, 256,
- &ssl->out_msg[i], n,
- ssl->f_rng, ssl->p_rng );
- if( ret != 0 )
- {
- SSL_DEBUG_RET( 1, "dhm_make_public", ret );
- return( ret );
- }
-
- SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X );
- SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
-
- ssl->pmslen = ssl->dhm_ctx.len;
-
- if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
- ssl->premaster,
- &ssl->pmslen ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
- return( ret );
- }
-
- SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K );
-#endif
- }
- else
- {
- /*
- * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster))
- */
- ssl->premaster[0] = (unsigned char) ssl->max_major_ver;
- ssl->premaster[1] = (unsigned char) ssl->max_minor_ver;
- ssl->pmslen = 48;
-
- ret = ssl->f_rng( ssl->p_rng, ssl->premaster + 2, ssl->pmslen - 2 );
- if( ret != 0 )
- return( ret );
-
- i = 4;
- n = ssl->peer_cert->rsa.len;
-
- if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
- {
- i += 2;
- ssl->out_msg[4] = (unsigned char)( n >> 8 );
- ssl->out_msg[5] = (unsigned char)( n );
- }
-
- ret = rsa_pkcs1_encrypt( &ssl->peer_cert->rsa,
- ssl->f_rng, ssl->p_rng,
- RSA_PUBLIC,
- ssl->pmslen, ssl->premaster,
- ssl->out_msg + i );
- if( ret != 0 )
- {
- SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
- return( ret );
- }
- }
-
- if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
- return( ret );
- }
-
- ssl->out_msglen = i + n;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE;
-
- ssl->state++;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
-
- return( 0 );
-}
-
-static int ssl_write_certificate_verify( ssl_context *ssl )
-{
- int ret = 0;
- size_t n = 0, offset = 0;
- unsigned char hash[48];
- int hash_id = SIG_RSA_RAW;
- unsigned int hashlen = 36;
-
- SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
-
- if( ssl->client_auth == 0 || ssl->own_cert == NULL )
- {
- SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
- ssl->state++;
- return( 0 );
- }
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
- {
- // TODO TLS1.2 Should be based on allowed signature algorithm received in
- // Certificate Request according to RFC 5246. But OpenSSL only allows
- // SHA256 and SHA384. Find out why OpenSSL does this.
- //
- if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- hash_id = SIG_RSA_SHA384;
- hashlen = 48;
- }
- else
- {
- hash_id = SIG_RSA_SHA256;
- hashlen = 32;
- }
- }
-
- if( ssl->rsa_key == NULL )
- {
-#if defined(POLARSSL_PKCS11_C)
- if( ssl->pkcs11_key == NULL )
- {
-#endif /* defined(POLARSSL_PKCS11_C) */
- SSL_DEBUG_MSG( 1, ( "got no private key" ) );
- return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
-#if defined(POLARSSL_PKCS11_C)
- }
-#endif /* defined(POLARSSL_PKCS11_C) */
- }
-
- /*
- * Make an RSA signature of the handshake digests
- */
- ssl->calc_verify( ssl, hash );
-
- if ( ssl->rsa_key )
- n = ssl->rsa_key->len;
-#if defined(POLARSSL_PKCS11_C)
- else
- n = ssl->pkcs11_key->len;
-#endif /* defined(POLARSSL_PKCS11_C) */
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
- {
- // TODO TLS1.2 Should be based on allowed signature algorithm received in
- // Certificate Request according to RFC 5246. But OpenSSL only allows
- // SHA256 and SHA384. Find out why OpenSSL does this.
- //
- if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- ssl->out_msg[4] = SSL_HASH_SHA384;
- ssl->out_msg[5] = SSL_SIG_RSA;
- }
- else
- {
- ssl->out_msg[4] = SSL_HASH_SHA256;
- ssl->out_msg[5] = SSL_SIG_RSA;
- }
-
- offset = 2;
- }
-
- ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
- ssl->out_msg[5 + offset] = (unsigned char)( n );
-
- if( ssl->rsa_key )
- {
- ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
- RSA_PRIVATE, hash_id,
- hashlen, hash, ssl->out_msg + 6 + offset );
- } else {
-#if defined(POLARSSL_PKCS11_C)
- ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, hash_id,
- hashlen, hash, ssl->out_msg + 6 + offset );
-#endif /* defined(POLARSSL_PKCS11_C) */
- }
-
- if (ret != 0)
- {
- SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
- return( ret );
- }
-
- ssl->out_msglen = 6 + n + offset;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY;
-
- ssl->state++;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
-
- return( 0 );
-}
-
-/*
- * SSL handshake -- client side
- */
-int ssl_handshake_client( ssl_context *ssl )
-{
- int ret = 0;
-
- SSL_DEBUG_MSG( 2, ( "=> handshake client" ) );
-
- while( ssl->state != SSL_HANDSHAKE_OVER )
- {
- SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
-
- if( ( ret = ssl_flush_output( ssl ) ) != 0 )
- break;
-
- switch( ssl->state )
- {
- case SSL_HELLO_REQUEST:
- ssl->state = SSL_CLIENT_HELLO;
- break;
-
- /*
- * ==> ClientHello
- */
- case SSL_CLIENT_HELLO:
- ret = ssl_write_client_hello( ssl );
- break;
-
- /*
- * <== ServerHello
- * Certificate
- * ( ServerKeyExchange )
- * ( CertificateRequest )
- * ServerHelloDone
- */
- case SSL_SERVER_HELLO:
- ret = ssl_parse_server_hello( ssl );
- break;
-
- case SSL_SERVER_CERTIFICATE:
- ret = ssl_parse_certificate( ssl );
- break;
-
- case SSL_SERVER_KEY_EXCHANGE:
- ret = ssl_parse_server_key_exchange( ssl );
- break;
-
- case SSL_CERTIFICATE_REQUEST:
- ret = ssl_parse_certificate_request( ssl );
- break;
-
- case SSL_SERVER_HELLO_DONE:
- ret = ssl_parse_server_hello_done( ssl );
- break;
-
- /*
- * ==> ( Certificate/Alert )
- * ClientKeyExchange
- * ( CertificateVerify )
- * ChangeCipherSpec
- * Finished
- */
- case SSL_CLIENT_CERTIFICATE:
- ret = ssl_write_certificate( ssl );
- break;
-
- case SSL_CLIENT_KEY_EXCHANGE:
- ret = ssl_write_client_key_exchange( ssl );
- break;
-
- case SSL_CERTIFICATE_VERIFY:
- ret = ssl_write_certificate_verify( ssl );
- break;
-
- case SSL_CLIENT_CHANGE_CIPHER_SPEC:
- ret = ssl_write_change_cipher_spec( ssl );
- break;
-
- case SSL_CLIENT_FINISHED:
- ret = ssl_write_finished( ssl );
- break;
-
- /*
- * <== ChangeCipherSpec
- * Finished
- */
- case SSL_SERVER_CHANGE_CIPHER_SPEC:
- ret = ssl_parse_change_cipher_spec( ssl );
- break;
-
- case SSL_SERVER_FINISHED:
- ret = ssl_parse_finished( ssl );
- break;
-
- case SSL_FLUSH_BUFFERS:
- SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
- ssl->state = SSL_HANDSHAKE_OVER;
- break;
-
- default:
- SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
- }
-
- if( ret != 0 )
- break;
- }
-
- SSL_DEBUG_MSG( 2, ( "<= handshake client" ) );
-
- return( ret );
-}
-
-#endif
diff --git a/polarssl/src/library/ssl_srv.c b/polarssl/src/library/ssl_srv.c
deleted file mode 100644
index ecf1536..0000000
--- a/polarssl/src/library/ssl_srv.c
+++ /dev/null
@@ -1,1080 +0,0 @@
-/*
- * SSLv3/TLSv1 server-side functions
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SSL_SRV_C)
-
-#include "polarssl/debug.h"
-#include "polarssl/ssl.h"
-
-#if defined(POLARSSL_PKCS11_C)
-#include "polarssl/pkcs11.h"
-#endif /* defined(POLARSSL_PKCS11_C) */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-static int ssl_parse_client_hello( ssl_context *ssl )
-{
- int ret;
- unsigned int i, j;
- size_t n;
- unsigned int ciph_len, sess_len;
- unsigned int chal_len, comp_len;
- unsigned char *buf, *p;
-
- SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
-
- if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
- return( ret );
- }
-
- buf = ssl->in_hdr;
-
- if( ( buf[0] & 0x80 ) != 0 )
- {
- SSL_DEBUG_BUF( 4, "record header", buf, 5 );
-
- SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
- buf[2] ) );
- SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
- ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
- SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
- buf[3], buf[4] ) );
-
- /*
- * SSLv2 Client Hello
- *
- * Record layer:
- * 0 . 1 message length
- *
- * SSL layer:
- * 2 . 2 message type
- * 3 . 4 protocol version
- */
- if( buf[2] != SSL_HS_CLIENT_HELLO ||
- buf[3] != SSL_MAJOR_VERSION_3 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
-
- if( n < 17 || n > 512 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- ssl->max_major_ver = buf[3];
- ssl->max_minor_ver = buf[4];
-
- ssl->major_ver = SSL_MAJOR_VERSION_3;
- ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_3 )
- ? buf[4] : SSL_MINOR_VERSION_3;
-
- if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
- return( ret );
- }
-
- ssl->update_checksum( ssl, buf + 2, n );
-
- buf = ssl->in_msg;
- n = ssl->in_left - 5;
-
- /*
- * 0 . 1 ciphersuitelist length
- * 2 . 3 session id length
- * 4 . 5 challenge length
- * 6 . .. ciphersuitelist
- * .. . .. session id
- * .. . .. challenge
- */
- SSL_DEBUG_BUF( 4, "record contents", buf, n );
-
- ciph_len = ( buf[0] << 8 ) | buf[1];
- sess_len = ( buf[2] << 8 ) | buf[3];
- chal_len = ( buf[4] << 8 ) | buf[5];
-
- SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
- ciph_len, sess_len, chal_len ) );
-
- /*
- * Make sure each parameter length is valid
- */
- if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- if( sess_len > 32 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- if( chal_len < 8 || chal_len > 32 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- if( n != 6 + ciph_len + sess_len + chal_len )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
- buf + 6, ciph_len );
- SSL_DEBUG_BUF( 3, "client hello, session id",
- buf + 6 + ciph_len, sess_len );
- SSL_DEBUG_BUF( 3, "client hello, challenge",
- buf + 6 + ciph_len + sess_len, chal_len );
-
- p = buf + 6 + ciph_len;
- ssl->session->length = sess_len;
- memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
- memcpy( ssl->session->id, p, ssl->session->length );
-
- p += sess_len;
- memset( ssl->randbytes, 0, 64 );
- memcpy( ssl->randbytes + 32 - chal_len, p, chal_len );
-
- for( i = 0; ssl->ciphersuites[i] != 0; i++ )
- {
- for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
- {
- if( p[0] == 0 &&
- p[1] == 0 &&
- p[2] == ssl->ciphersuites[i] )
- goto have_ciphersuite;
- }
- }
- }
- else
- {
- SSL_DEBUG_BUF( 4, "record header", buf, 5 );
-
- SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
- buf[0] ) );
- SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
- ( buf[3] << 8 ) | buf[4] ) );
- SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]",
- buf[1], buf[2] ) );
-
- /*
- * SSLv3 Client Hello
- *
- * Record layer:
- * 0 . 0 message type
- * 1 . 2 protocol version
- * 3 . 4 message length
- */
- if( buf[0] != SSL_MSG_HANDSHAKE ||
- buf[1] != SSL_MAJOR_VERSION_3 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- n = ( buf[3] << 8 ) | buf[4];
-
- if( n < 45 || n > 512 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
- return( ret );
- }
-
- buf = ssl->in_msg;
- n = ssl->in_left - 5;
-
- ssl->update_checksum( ssl, buf, n );
-
- /*
- * SSL layer:
- * 0 . 0 handshake type
- * 1 . 3 handshake length
- * 4 . 5 protocol version
- * 6 . 9 UNIX time()
- * 10 . 37 random bytes
- * 38 . 38 session id length
- * 39 . 38+x session id
- * 39+x . 40+x ciphersuitelist length
- * 41+x . .. ciphersuitelist
- * .. . .. compression alg.
- * .. . .. extensions
- */
- SSL_DEBUG_BUF( 4, "record contents", buf, n );
-
- SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d",
- buf[0] ) );
- SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
- ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
- SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]",
- buf[4], buf[5] ) );
-
- /*
- * Check the handshake type and protocol version
- */
- if( buf[0] != SSL_HS_CLIENT_HELLO ||
- buf[4] != SSL_MAJOR_VERSION_3 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- ssl->major_ver = SSL_MAJOR_VERSION_3;
- ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_3 )
- ? buf[5] : SSL_MINOR_VERSION_3;
-
- ssl->max_major_ver = buf[4];
- ssl->max_minor_ver = buf[5];
-
- memcpy( ssl->randbytes, buf + 6, 32 );
-
- /*
- * Check the handshake message length
- */
- if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- /*
- * Check the session length
- */
- sess_len = buf[38];
-
- if( sess_len > 32 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- ssl->session->length = sess_len;
- memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
- memcpy( ssl->session->id, buf + 39 , ssl->session->length );
-
- /*
- * Check the ciphersuitelist length
- */
- ciph_len = ( buf[39 + sess_len] << 8 )
- | ( buf[40 + sess_len] );
-
- if( ciph_len < 2 || ciph_len > 256 || ( ciph_len % 2 ) != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- /*
- * Check the compression algorithms length
- */
- comp_len = buf[41 + sess_len + ciph_len];
-
- if( comp_len < 1 || comp_len > 16 )
- {
- SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- SSL_DEBUG_BUF( 3, "client hello, random bytes",
- buf + 6, 32 );
- SSL_DEBUG_BUF( 3, "client hello, session id",
- buf + 38, sess_len );
- SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
- buf + 41 + sess_len, ciph_len );
- SSL_DEBUG_BUF( 3, "client hello, compression",
- buf + 42 + sess_len + ciph_len, comp_len );
-
- /*
- * Search for a matching ciphersuite
- */
- for( i = 0; ssl->ciphersuites[i] != 0; i++ )
- {
- for( j = 0, p = buf + 41 + sess_len; j < ciph_len;
- j += 2, p += 2 )
- {
- if( p[0] == 0 && p[1] == ssl->ciphersuites[i] )
- goto have_ciphersuite;
- }
- }
- }
-
- SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
-
- return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
-
-have_ciphersuite:
-
- ssl->session->ciphersuite = ssl->ciphersuites[i];
- ssl_kickstart_checksum( ssl, ssl->session->ciphersuite, buf, n );
-
- ssl->in_left = 0;
- ssl->state++;
-
- SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
-
- return( 0 );
-}
-
-static int ssl_write_server_hello( ssl_context *ssl )
-{
- time_t t;
- int ret, n;
- unsigned char *buf, *p;
-
- SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
-
- /*
- * 0 . 0 handshake type
- * 1 . 3 handshake length
- * 4 . 5 protocol version
- * 6 . 9 UNIX time()
- * 10 . 37 random bytes
- */
- buf = ssl->out_msg;
- p = buf + 4;
-
- *p++ = (unsigned char) ssl->major_ver;
- *p++ = (unsigned char) ssl->minor_ver;
-
- SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
- buf[4], buf[5] ) );
-
- t = time( NULL );
- *p++ = (unsigned char)( t >> 24 );
- *p++ = (unsigned char)( t >> 16 );
- *p++ = (unsigned char)( t >> 8 );
- *p++ = (unsigned char)( t );
-
- SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
-
- if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
- return( ret );
-
- p += 28;
-
- memcpy( ssl->randbytes + 32, buf + 6, 32 );
-
- SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
-
- /*
- * 38 . 38 session id length
- * 39 . 38+n session id
- * 39+n . 40+n chosen ciphersuite
- * 41+n . 41+n chosen compression alg.
- */
- ssl->session->length = n = 32;
- *p++ = (unsigned char) ssl->session->length;
-
- if( ssl->s_get == NULL ||
- ssl->s_get( ssl ) != 0 )
- {
- /*
- * Not found, create a new session id
- */
- ssl->resume = 0;
- ssl->state++;
-
- if( ssl->session == NULL )
- {
- SSL_DEBUG_MSG( 1, ( "No session struct set" ) );
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
- }
-
- if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session->id, n ) ) != 0 )
- return( ret );
- }
- else
- {
- /*
- * Found a matching session, resume it
- */
- ssl->resume = 1;
- ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
-
- if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
- return( ret );
- }
- }
-
- memcpy( p, ssl->session->id, ssl->session->length );
- p += ssl->session->length;
-
- SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
- SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
- SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
- ssl->resume ? "a" : "no" ) );
-
- *p++ = (unsigned char)( ssl->session->ciphersuite >> 8 );
- *p++ = (unsigned char)( ssl->session->ciphersuite );
- *p++ = SSL_COMPRESS_NULL;
-
- SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d",
- ssl->session->ciphersuite ) );
- SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", 0 ) );
-
- ssl->out_msglen = p - buf;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_SERVER_HELLO;
-
- ret = ssl_write_record( ssl );
-
- SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
-
- return( ret );
-}
-
-static int ssl_write_certificate_request( ssl_context *ssl )
-{
- int ret;
- size_t n;
- unsigned char *buf, *p;
- const x509_cert *crt;
-
- SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
-
- ssl->state++;
-
- if( ssl->authmode == SSL_VERIFY_NONE )
- {
- SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
- return( 0 );
- }
-
- /*
- * 0 . 0 handshake type
- * 1 . 3 handshake length
- * 4 . 4 cert type count
- * 5 .. n-1 cert types
- * n .. n+1 length of all DNs
- * n+2 .. n+3 length of DN 1
- * n+4 .. ... Distinguished Name #1
- * ... .. ... length of DN 2, etc.
- */
- buf = ssl->out_msg;
- p = buf + 4;
-
- /*
- * At the moment, only RSA certificates are supported
- */
- *p++ = 1;
- *p++ = 1;
-
- p += 2;
- crt = ssl->ca_chain;
-
- while( crt != NULL )
- {
- if( p - buf > 4096 )
- break;
-
- n = crt->subject_raw.len;
- *p++ = (unsigned char)( n >> 8 );
- *p++ = (unsigned char)( n );
- memcpy( p, crt->subject_raw.p, n );
-
- SSL_DEBUG_BUF( 3, "requested DN", p, n );
- p += n; crt = crt->next;
- }
-
- ssl->out_msglen = n = p - buf;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_CERTIFICATE_REQUEST;
- ssl->out_msg[6] = (unsigned char)( ( n - 8 ) >> 8 );
- ssl->out_msg[7] = (unsigned char)( ( n - 8 ) );
-
- ret = ssl_write_record( ssl );
-
- SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
-
- return( ret );
-}
-
-static int ssl_write_server_key_exchange( ssl_context *ssl )
-{
-#if defined(POLARSSL_DHM_C)
- int ret;
- size_t n, rsa_key_len = 0;
- unsigned char hash[48];
- md5_context md5;
- sha1_context sha1;
- int hash_id;
- unsigned int hashlen;
-#endif
-
- SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
-
- if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 &&
- ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
- ssl->state++;
- return( 0 );
- }
-
-#if !defined(POLARSSL_DHM_C)
- SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-#else
-
- if( ssl->rsa_key == NULL )
- {
-#if defined(POLARSSL_PKCS11_C)
- if( ssl->pkcs11_key == NULL )
- {
-#endif /* defined(POLARSSL_PKCS11_C) */
- SSL_DEBUG_MSG( 1, ( "got no private key" ) );
- return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
-#if defined(POLARSSL_PKCS11_C)
- }
-#endif /* defined(POLARSSL_PKCS11_C) */
- }
-
- /*
- * Ephemeral DH parameters:
- *
- * struct {
- * opaque dh_p<1..2^16-1>;
- * opaque dh_g<1..2^16-1>;
- * opaque dh_Ys<1..2^16-1>;
- * } ServerDHParams;
- */
- if( ( ret = dhm_make_params( &ssl->dhm_ctx, 256, ssl->out_msg + 4,
- &n, ssl->f_rng, ssl->p_rng ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "dhm_make_params", ret );
- return( ret );
- }
-
- SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X );
- SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P );
- SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
- SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
-
- if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
- {
- /*
- * digitally-signed struct {
- * opaque md5_hash[16];
- * opaque sha_hash[20];
- * };
- *
- * md5_hash
- * MD5(ClientHello.random + ServerHello.random
- * + ServerParams);
- * sha_hash
- * SHA(ClientHello.random + ServerHello.random
- * + ServerParams);
- */
- md5_starts( &md5 );
- md5_update( &md5, ssl->randbytes, 64 );
- md5_update( &md5, ssl->out_msg + 4, n );
- md5_finish( &md5, hash );
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, ssl->randbytes, 64 );
- sha1_update( &sha1, ssl->out_msg + 4, n );
- sha1_finish( &sha1, hash + 16 );
-
- hashlen = 36;
- hash_id = SIG_RSA_RAW;
- }
- else
- {
- /*
- * digitally-signed struct {
- * opaque client_random[32];
- * opaque server_random[32];
- * ServerDHParams params;
- * };
- */
- /* TODO TLS1.2 Get a supported hash algorithm from the
- * signature_algorithms extension, Otherwise SHA1 + RSA!
- */
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, ssl->randbytes, 64 );
- sha1_update( &sha1, ssl->out_msg + 4, n );
- sha1_finish( &sha1, hash );
-
- hashlen = 20;
- hash_id = SIG_RSA_SHA1;
- }
-
- SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
-
- if ( ssl->rsa_key )
- rsa_key_len = ssl->rsa_key->len;
-#if defined(POLARSSL_PKCS11_C)
- else
- rsa_key_len = ssl->pkcs11_key->len;
-#endif /* defined(POLARSSL_PKCS11_C) */
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
- {
- // TODO TLS1.2 Base on selection above (SHA1 + RSA is default choice)
- ssl->out_msg[4 + n] = SSL_HASH_SHA1;
- ssl->out_msg[5 + n] = SSL_SIG_RSA;
-
- n += 2;
- }
-
- ssl->out_msg[4 + n] = (unsigned char)( rsa_key_len >> 8 );
- ssl->out_msg[5 + n] = (unsigned char)( rsa_key_len );
-
- if ( ssl->rsa_key )
- {
- ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
- RSA_PRIVATE,
- hash_id, hashlen, hash, ssl->out_msg + 6 + n );
- }
-#if defined(POLARSSL_PKCS11_C)
- else {
- ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE,
- hash_id, hashlen, hash, ssl->out_msg + 6 + n );
- }
-#endif /* defined(POLARSSL_PKCS11_C) */
-
- if( ret != 0 )
- {
- SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
- return( ret );
- }
-
- SSL_DEBUG_BUF( 3, "my RSA sig", ssl->out_msg + 6 + n, rsa_key_len );
-
- ssl->out_msglen = 6 + n + rsa_key_len;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_SERVER_KEY_EXCHANGE;
-
- ssl->state++;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
-
- return( 0 );
-#endif
-}
-
-static int ssl_write_server_hello_done( ssl_context *ssl )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
-
- ssl->out_msglen = 4;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_SERVER_HELLO_DONE;
-
- ssl->state++;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
-
- return( 0 );
-}
-
-static int ssl_parse_client_key_exchange( ssl_context *ssl )
-{
- int ret;
- size_t i, n = 0;
-
- SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
-
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
- }
-
- if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE )
- {
- SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
- }
-
- if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
-#if !defined(POLARSSL_DHM_C)
- SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-#else
- /*
- * Receive G^Y mod P, premaster = (G^Y)^X mod P
- */
- n = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
-
- if( n < 1 || n > ssl->dhm_ctx.len ||
- n + 6 != ssl->in_hslen )
- {
- SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
- }
-
- if( ( ret = dhm_read_public( &ssl->dhm_ctx,
- ssl->in_msg + 6, n ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "dhm_read_public", ret );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP );
- }
-
- SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
-
- ssl->pmslen = ssl->dhm_ctx.len;
-
- if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
- ssl->premaster, &ssl->pmslen ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS );
- }
-
- SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K );
-#endif
- }
- else
- {
- if( ssl->rsa_key == NULL )
- {
-#if defined(POLARSSL_PKCS11_C)
- if( ssl->pkcs11_key == NULL )
- {
-#endif
- SSL_DEBUG_MSG( 1, ( "got no private key" ) );
- return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
-#if defined(POLARSSL_PKCS11_C)
- }
-#endif
- }
-
- /*
- * Decrypt the premaster using own private RSA key
- */
- i = 4;
- if( ssl->rsa_key )
- n = ssl->rsa_key->len;
-#if defined(POLARSSL_PKCS11_C)
- else
- n = ssl->pkcs11_key->len;
-#endif
- ssl->pmslen = 48;
-
- if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
- {
- i += 2;
- if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) ||
- ssl->in_msg[5] != ( ( n ) & 0xFF ) )
- {
- SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
- }
- }
-
- if( ssl->in_hslen != i + n )
- {
- SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
- }
-
- if( ssl->rsa_key ) {
- ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, &ssl->pmslen,
- ssl->in_msg + i, ssl->premaster,
- sizeof(ssl->premaster) );
- }
-#if defined(POLARSSL_PKCS11_C)
- else {
- ret = pkcs11_decrypt( ssl->pkcs11_key, RSA_PRIVATE, &ssl->pmslen,
- ssl->in_msg + i, ssl->premaster,
- sizeof(ssl->premaster) );
- }
-#endif /* defined(POLARSSL_PKCS11_C) */
-
- if( ret != 0 || ssl->pmslen != 48 ||
- ssl->premaster[0] != ssl->max_major_ver ||
- ssl->premaster[1] != ssl->max_minor_ver )
- {
- SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-
- /*
- * Protection against Bleichenbacher's attack:
- * invalid PKCS#1 v1.5 padding must not cause
- * the connection to end immediately; instead,
- * send a bad_record_mac later in the handshake.
- */
- ssl->pmslen = 48;
-
- ret = ssl->f_rng( ssl->p_rng, ssl->premaster, ssl->pmslen );
- if( ret != 0 )
- return( ret );
- }
- }
-
- if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
- return( ret );
- }
-
- if( ssl->s_set != NULL )
- ssl->s_set( ssl );
-
- ssl->state++;
-
- SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
-
- return( 0 );
-}
-
-static int ssl_parse_certificate_verify( ssl_context *ssl )
-{
- int ret;
- size_t n1, n2;
- unsigned char hash[48];
-
- SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
-
- if( ssl->peer_cert == NULL )
- {
- SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
- ssl->state++;
- return( 0 );
- }
-
- ssl->calc_verify( ssl, hash );
-
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- ssl->state++;
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
- }
-
- if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
- }
-
- n1 = ssl->peer_cert->rsa.len;
- n2 = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
-
- if( n1 + 6 != ssl->in_hslen || n1 != n2 )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
- }
-
- ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
- SIG_RSA_RAW, 36, hash, ssl->in_msg + 6 );
- if( ret != 0 )
- {
- SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
-
- return( 0 );
-}
-
-/*
- * SSL handshake -- server side
- */
-int ssl_handshake_server( ssl_context *ssl )
-{
- int ret = 0;
-
- SSL_DEBUG_MSG( 2, ( "=> handshake server" ) );
-
- while( ssl->state != SSL_HANDSHAKE_OVER )
- {
- SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
-
- if( ( ret = ssl_flush_output( ssl ) ) != 0 )
- break;
-
- switch( ssl->state )
- {
- case SSL_HELLO_REQUEST:
- ssl->state = SSL_CLIENT_HELLO;
- break;
-
- /*
- * <== ClientHello
- */
- case SSL_CLIENT_HELLO:
- ret = ssl_parse_client_hello( ssl );
- break;
-
- /*
- * ==> ServerHello
- * Certificate
- * ( ServerKeyExchange )
- * ( CertificateRequest )
- * ServerHelloDone
- */
- case SSL_SERVER_HELLO:
- ret = ssl_write_server_hello( ssl );
- break;
-
- case SSL_SERVER_CERTIFICATE:
- ret = ssl_write_certificate( ssl );
- break;
-
- case SSL_SERVER_KEY_EXCHANGE:
- ret = ssl_write_server_key_exchange( ssl );
- break;
-
- case SSL_CERTIFICATE_REQUEST:
- ret = ssl_write_certificate_request( ssl );
- break;
-
- case SSL_SERVER_HELLO_DONE:
- ret = ssl_write_server_hello_done( ssl );
- break;
-
- /*
- * <== ( Certificate/Alert )
- * ClientKeyExchange
- * ( CertificateVerify )
- * ChangeCipherSpec
- * Finished
- */
- case SSL_CLIENT_CERTIFICATE:
- ret = ssl_parse_certificate( ssl );
- break;
-
- case SSL_CLIENT_KEY_EXCHANGE:
- ret = ssl_parse_client_key_exchange( ssl );
- break;
-
- case SSL_CERTIFICATE_VERIFY:
- ret = ssl_parse_certificate_verify( ssl );
- break;
-
- case SSL_CLIENT_CHANGE_CIPHER_SPEC:
- ret = ssl_parse_change_cipher_spec( ssl );
- break;
-
- case SSL_CLIENT_FINISHED:
- ret = ssl_parse_finished( ssl );
- break;
-
- /*
- * ==> ChangeCipherSpec
- * Finished
- */
- case SSL_SERVER_CHANGE_CIPHER_SPEC:
- ret = ssl_write_change_cipher_spec( ssl );
- break;
-
- case SSL_SERVER_FINISHED:
- ret = ssl_write_finished( ssl );
- break;
-
- case SSL_FLUSH_BUFFERS:
- SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
- ssl->state = SSL_HANDSHAKE_OVER;
- break;
-
- default:
- SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
- }
-
- if( ret != 0 )
- break;
- }
-
- SSL_DEBUG_MSG( 2, ( "<= handshake server" ) );
-
- return( ret );
-}
-
-#endif
diff --git a/polarssl/src/library/ssl_tls.c b/polarssl/src/library/ssl_tls.c
deleted file mode 100644
index 88c6e55..0000000
--- a/polarssl/src/library/ssl_tls.c
+++ /dev/null
@@ -1,3166 +0,0 @@
-/*
- * SSLv3/TLSv1 shared functions
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The SSL 3.0 specification was drafted by Netscape in 1996,
- * and became an IETF standard in 1999.
- *
- * http://wp.netscape.com/eng/ssl3/
- * http://www.ietf.org/rfc/rfc2246.txt
- * http://www.ietf.org/rfc/rfc4346.txt
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SSL_TLS_C)
-
-#include "polarssl/aes.h"
-#include "polarssl/arc4.h"
-#include "polarssl/camellia.h"
-#include "polarssl/des.h"
-#include "polarssl/debug.h"
-#include "polarssl/ssl.h"
-#include "polarssl/sha2.h"
-
-#if defined(POLARSSL_GCM_C)
-#include "polarssl/gcm.h"
-#endif
-
-#include <stdlib.h>
-#include <time.h>
-
-#if defined _MSC_VER && !defined strcasecmp
-#define strcasecmp _stricmp
-#endif
-
-/*
- * Key material generation
- */
-static int tls1_prf( unsigned char *secret, size_t slen, char *label,
- unsigned char *random, size_t rlen,
- unsigned char *dstbuf, size_t dlen )
-{
- size_t nb, hs;
- size_t i, j, k;
- unsigned char *S1, *S2;
- unsigned char tmp[128];
- unsigned char h_i[20];
-
- if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-
- hs = ( slen + 1 ) / 2;
- S1 = secret;
- S2 = secret + slen - hs;
-
- nb = strlen( label );
- memcpy( tmp + 20, label, nb );
- memcpy( tmp + 20 + nb, random, rlen );
- nb += rlen;
-
- /*
- * First compute P_md5(secret,label+random)[0..dlen]
- */
- md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp );
-
- for( i = 0; i < dlen; i += 16 )
- {
- md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i );
- md5_hmac( S1, hs, 4 + tmp, 16, 4 + tmp );
-
- k = ( i + 16 > dlen ) ? dlen % 16 : 16;
-
- for( j = 0; j < k; j++ )
- dstbuf[i + j] = h_i[j];
- }
-
- /*
- * XOR out with P_sha1(secret,label+random)[0..dlen]
- */
- sha1_hmac( S2, hs, tmp + 20, nb, tmp );
-
- for( i = 0; i < dlen; i += 20 )
- {
- sha1_hmac( S2, hs, tmp, 20 + nb, h_i );
- sha1_hmac( S2, hs, tmp, 20, tmp );
-
- k = ( i + 20 > dlen ) ? dlen % 20 : 20;
-
- for( j = 0; j < k; j++ )
- dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
- }
-
- memset( tmp, 0, sizeof( tmp ) );
- memset( h_i, 0, sizeof( h_i ) );
-
- return( 0 );
-}
-
-static int tls_prf_sha256( unsigned char *secret, size_t slen, char *label,
- unsigned char *random, size_t rlen,
- unsigned char *dstbuf, size_t dlen )
-{
- size_t nb;
- size_t i, j, k;
- unsigned char tmp[128];
- unsigned char h_i[32];
-
- if( sizeof( tmp ) < 32 + strlen( label ) + rlen )
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-
- nb = strlen( label );
- memcpy( tmp + 32, label, nb );
- memcpy( tmp + 32 + nb, random, rlen );
- nb += rlen;
-
- /*
- * Compute P_<hash>(secret, label + random)[0..dlen]
- */
- sha2_hmac( secret, slen, tmp + 32, nb, tmp, 0 );
-
- for( i = 0; i < dlen; i += 32 )
- {
- sha2_hmac( secret, slen, tmp, 32 + nb, h_i, 0 );
- sha2_hmac( secret, slen, tmp, 32, tmp, 0 );
-
- k = ( i + 32 > dlen ) ? dlen % 32 : 32;
-
- for( j = 0; j < k; j++ )
- dstbuf[i + j] = h_i[j];
- }
-
- memset( tmp, 0, sizeof( tmp ) );
- memset( h_i, 0, sizeof( h_i ) );
-
- return( 0 );
-}
-
-static int tls_prf_sha384( unsigned char *secret, size_t slen, char *label,
- unsigned char *random, size_t rlen,
- unsigned char *dstbuf, size_t dlen )
-{
- size_t nb;
- size_t i, j, k;
- unsigned char tmp[128];
- unsigned char h_i[48];
-
- if( sizeof( tmp ) < 48 + strlen( label ) + rlen )
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-
- nb = strlen( label );
- memcpy( tmp + 48, label, nb );
- memcpy( tmp + 48 + nb, random, rlen );
- nb += rlen;
-
- /*
- * Compute P_<hash>(secret, label + random)[0..dlen]
- */
- sha4_hmac( secret, slen, tmp + 48, nb, tmp, 1 );
-
- for( i = 0; i < dlen; i += 48 )
- {
- sha4_hmac( secret, slen, tmp, 48 + nb, h_i, 1 );
- sha4_hmac( secret, slen, tmp, 48, tmp, 1 );
-
- k = ( i + 48 > dlen ) ? dlen % 48 : 48;
-
- for( j = 0; j < k; j++ )
- dstbuf[i + j] = h_i[j];
- }
-
- memset( tmp, 0, sizeof( tmp ) );
- memset( h_i, 0, sizeof( h_i ) );
-
- return( 0 );
-}
-
-static void ssl_update_checksum_start(ssl_context *, unsigned char *, size_t);
-static void ssl_update_checksum_md5sha1(ssl_context *, unsigned char *, size_t);
-static void ssl_update_checksum_sha256(ssl_context *, unsigned char *, size_t);
-static void ssl_update_checksum_sha384(ssl_context *, unsigned char *, size_t);
-
-static void ssl_calc_verify_ssl(ssl_context *,unsigned char *);
-static void ssl_calc_verify_tls(ssl_context *,unsigned char *);
-static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *);
-static void ssl_calc_verify_tls_sha384(ssl_context *,unsigned char *);
-
-static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int);
-static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int);
-static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int);
-static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int);
-
-int ssl_derive_keys( ssl_context *ssl )
-{
- int i;
- md5_context md5;
- sha1_context sha1;
- unsigned char tmp[64];
- unsigned char padding[16];
- unsigned char sha1sum[20];
- unsigned char keyblk[256];
- unsigned char *key1;
- unsigned char *key2;
- unsigned int iv_copy_len;
-
- SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
-
- /*
- * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions
- */
- if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- ssl->tls_prf = tls1_prf;
- ssl->calc_verify = ssl_calc_verify_ssl;
- ssl->calc_finished = ssl_calc_finished_ssl;
- }
- else if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
- {
- ssl->tls_prf = tls1_prf;
- ssl->calc_verify = ssl_calc_verify_tls;
- ssl->calc_finished = ssl_calc_finished_tls;
- }
- else if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- ssl->tls_prf = tls_prf_sha384;
- ssl->calc_verify = ssl_calc_verify_tls_sha384;
- ssl->calc_finished = ssl_calc_finished_tls_sha384;
- }
- else
- {
- ssl->tls_prf = tls_prf_sha256;
- ssl->calc_verify = ssl_calc_verify_tls_sha256;
- ssl->calc_finished = ssl_calc_finished_tls_sha256;
- }
-
- /*
- * SSLv3:
- * master =
- * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) +
- * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) +
- * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
- *
- * TLSv1:
- * master = PRF( premaster, "master secret", randbytes )[0..47]
- */
- if( ssl->resume == 0 )
- {
- size_t len = ssl->pmslen;
-
- SSL_DEBUG_BUF( 3, "premaster secret", ssl->premaster, len );
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- for( i = 0; i < 3; i++ )
- {
- memset( padding, 'A' + i, 1 + i );
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, padding, 1 + i );
- sha1_update( &sha1, ssl->premaster, len );
- sha1_update( &sha1, ssl->randbytes, 64 );
- sha1_finish( &sha1, sha1sum );
-
- md5_starts( &md5 );
- md5_update( &md5, ssl->premaster, len );
- md5_update( &md5, sha1sum, 20 );
- md5_finish( &md5, ssl->session->master + i * 16 );
- }
- }
- else
- ssl->tls_prf( ssl->premaster, len, "master secret",
- ssl->randbytes, 64, ssl->session->master, 48 );
-
- memset( ssl->premaster, 0, sizeof( ssl->premaster ) );
- }
- else
- SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
-
- /*
- * Swap the client and server random values.
- */
- memcpy( tmp, ssl->randbytes, 64 );
- memcpy( ssl->randbytes, tmp + 32, 32 );
- memcpy( ssl->randbytes + 32, tmp, 32 );
- memset( tmp, 0, sizeof( tmp ) );
-
- /*
- * SSLv3:
- * key block =
- * MD5( master + SHA1( 'A' + master + randbytes ) ) +
- * MD5( master + SHA1( 'BB' + master + randbytes ) ) +
- * MD5( master + SHA1( 'CCC' + master + randbytes ) ) +
- * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) +
- * ...
- *
- * TLSv1:
- * key block = PRF( master, "key expansion", randbytes )
- */
- if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- for( i = 0; i < 16; i++ )
- {
- memset( padding, 'A' + i, 1 + i );
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, padding, 1 + i );
- sha1_update( &sha1, ssl->session->master, 48 );
- sha1_update( &sha1, ssl->randbytes, 64 );
- sha1_finish( &sha1, sha1sum );
-
- md5_starts( &md5 );
- md5_update( &md5, ssl->session->master, 48 );
- md5_update( &md5, sha1sum, 20 );
- md5_finish( &md5, keyblk + i * 16 );
- }
-
- memset( &md5, 0, sizeof( md5 ) );
- memset( &sha1, 0, sizeof( sha1 ) );
-
- memset( padding, 0, sizeof( padding ) );
- memset( sha1sum, 0, sizeof( sha1sum ) );
- }
- else
- ssl->tls_prf( ssl->session->master, 48, "key expansion",
- ssl->randbytes, 64, keyblk, 256 );
-
- SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) );
- SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 );
- SSL_DEBUG_BUF( 4, "random bytes", ssl->randbytes, 64 );
- SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
-
- memset( ssl->randbytes, 0, sizeof( ssl->randbytes ) );
-
- /*
- * Determine the appropriate key, IV and MAC length.
- */
- switch( ssl->session->ciphersuite )
- {
-#if defined(POLARSSL_ARC4_C)
- case SSL_RSA_RC4_128_MD5:
- ssl->keylen = 16; ssl->minlen = 16;
- ssl->ivlen = 0; ssl->maclen = 16;
- break;
-
- case SSL_RSA_RC4_128_SHA:
- ssl->keylen = 16; ssl->minlen = 20;
- ssl->ivlen = 0; ssl->maclen = 20;
- break;
-#endif
-
-#if defined(POLARSSL_DES_C)
- case SSL_RSA_DES_168_SHA:
- case SSL_EDH_RSA_DES_168_SHA:
- ssl->keylen = 24; ssl->minlen = 24;
- ssl->ivlen = 8; ssl->maclen = 20;
- break;
-#endif
-
-#if defined(POLARSSL_AES_C)
- case SSL_RSA_AES_128_SHA:
- case SSL_EDH_RSA_AES_128_SHA:
- ssl->keylen = 16; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 20;
- break;
-
- case SSL_RSA_AES_256_SHA:
- case SSL_EDH_RSA_AES_256_SHA:
- ssl->keylen = 32; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 20;
- break;
-
-#if defined(POLARSSL_SHA2_C)
- case SSL_RSA_AES_128_SHA256:
- case SSL_EDH_RSA_AES_128_SHA256:
- ssl->keylen = 16; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 32;
- break;
-
- case SSL_RSA_AES_256_SHA256:
- case SSL_EDH_RSA_AES_256_SHA256:
- ssl->keylen = 32; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 32;
- break;
-#endif
-#if defined(POLARSSL_GCM_C)
- case SSL_RSA_AES_128_GCM_SHA256:
- case SSL_EDH_RSA_AES_128_GCM_SHA256:
- ssl->keylen = 16; ssl->minlen = 1;
- ssl->ivlen = 12; ssl->maclen = 0;
- ssl->fixed_ivlen = 4;
- break;
-
- case SSL_RSA_AES_256_GCM_SHA384:
- case SSL_EDH_RSA_AES_256_GCM_SHA384:
- ssl->keylen = 32; ssl->minlen = 1;
- ssl->ivlen = 12; ssl->maclen = 0;
- ssl->fixed_ivlen = 4;
- break;
-#endif
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
- case SSL_RSA_CAMELLIA_128_SHA:
- case SSL_EDH_RSA_CAMELLIA_128_SHA:
- ssl->keylen = 16; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 20;
- break;
-
- case SSL_RSA_CAMELLIA_256_SHA:
- case SSL_EDH_RSA_CAMELLIA_256_SHA:
- ssl->keylen = 32; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 20;
- break;
-
-#if defined(POLARSSL_SHA2_C)
- case SSL_RSA_CAMELLIA_128_SHA256:
- case SSL_EDH_RSA_CAMELLIA_128_SHA256:
- ssl->keylen = 16; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 32;
- break;
-
- case SSL_RSA_CAMELLIA_256_SHA256:
- case SSL_EDH_RSA_CAMELLIA_256_SHA256:
- ssl->keylen = 32; ssl->minlen = 32;
- ssl->ivlen = 16; ssl->maclen = 32;
- break;
-#endif
-#endif
-
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- case SSL_RSA_NULL_MD5:
- ssl->keylen = 0; ssl->minlen = 0;
- ssl->ivlen = 0; ssl->maclen = 16;
- break;
-
- case SSL_RSA_NULL_SHA:
- ssl->keylen = 0; ssl->minlen = 0;
- ssl->ivlen = 0; ssl->maclen = 20;
- break;
-
- case SSL_RSA_NULL_SHA256:
- ssl->keylen = 0; ssl->minlen = 0;
- ssl->ivlen = 0; ssl->maclen = 32;
- break;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#if defined(POLARSSL_DES_C)
- case SSL_RSA_DES_SHA:
- case SSL_EDH_RSA_DES_SHA:
- ssl->keylen = 8; ssl->minlen = 8;
- ssl->ivlen = 8; ssl->maclen = 20;
- break;
-#endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
-
- default:
- SSL_DEBUG_MSG( 1, ( "ciphersuite %s is not available",
- ssl_get_ciphersuite( ssl ) ) );
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d",
- ssl->keylen, ssl->minlen, ssl->ivlen, ssl->maclen ) );
-
- /*
- * Finally setup the cipher contexts, IVs and MAC secrets.
- */
- if( ssl->endpoint == SSL_IS_CLIENT )
- {
- key1 = keyblk + ssl->maclen * 2;
- key2 = keyblk + ssl->maclen * 2 + ssl->keylen;
-
- memcpy( ssl->mac_enc, keyblk, ssl->maclen );
- memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen );
-
- /*
- * This is not used in TLS v1.1.
- */
- iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen;
- memcpy( ssl->iv_enc, key2 + ssl->keylen, iv_copy_len );
- memcpy( ssl->iv_dec, key2 + ssl->keylen + iv_copy_len,
- iv_copy_len );
- }
- else
- {
- key1 = keyblk + ssl->maclen * 2 + ssl->keylen;
- key2 = keyblk + ssl->maclen * 2;
-
- memcpy( ssl->mac_dec, keyblk, ssl->maclen );
- memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen );
-
- /*
- * This is not used in TLS v1.1.
- */
- iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen;
- memcpy( ssl->iv_dec, key1 + ssl->keylen, iv_copy_len );
- memcpy( ssl->iv_enc, key1 + ssl->keylen + iv_copy_len,
- iv_copy_len );
- }
-
- switch( ssl->session->ciphersuite )
- {
-#if defined(POLARSSL_ARC4_C)
- case SSL_RSA_RC4_128_MD5:
- case SSL_RSA_RC4_128_SHA:
- arc4_setup( (arc4_context *) ssl->ctx_enc, key1, ssl->keylen );
- arc4_setup( (arc4_context *) ssl->ctx_dec, key2, ssl->keylen );
- break;
-#endif
-
-#if defined(POLARSSL_DES_C)
- case SSL_RSA_DES_168_SHA:
- case SSL_EDH_RSA_DES_168_SHA:
- des3_set3key_enc( (des3_context *) ssl->ctx_enc, key1 );
- des3_set3key_dec( (des3_context *) ssl->ctx_dec, key2 );
- break;
-#endif
-
-#if defined(POLARSSL_AES_C)
- case SSL_RSA_AES_128_SHA:
- case SSL_EDH_RSA_AES_128_SHA:
- case SSL_RSA_AES_128_SHA256:
- case SSL_EDH_RSA_AES_128_SHA256:
- aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 128 );
- aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 128 );
- break;
-
- case SSL_RSA_AES_256_SHA:
- case SSL_EDH_RSA_AES_256_SHA:
- case SSL_RSA_AES_256_SHA256:
- case SSL_EDH_RSA_AES_256_SHA256:
- aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 256 );
- aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 256 );
- break;
-
-#if defined(POLARSSL_GCM_C)
- case SSL_RSA_AES_128_GCM_SHA256:
- case SSL_EDH_RSA_AES_128_GCM_SHA256:
- gcm_init( (gcm_context *) ssl->ctx_enc, key1, 128 );
- gcm_init( (gcm_context *) ssl->ctx_dec, key2, 128 );
- break;
-
- case SSL_RSA_AES_256_GCM_SHA384:
- case SSL_EDH_RSA_AES_256_GCM_SHA384:
- gcm_init( (gcm_context *) ssl->ctx_enc, key1, 256 );
- gcm_init( (gcm_context *) ssl->ctx_dec, key2, 256 );
- break;
-#endif
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
- case SSL_RSA_CAMELLIA_128_SHA:
- case SSL_EDH_RSA_CAMELLIA_128_SHA:
- case SSL_RSA_CAMELLIA_128_SHA256:
- case SSL_EDH_RSA_CAMELLIA_128_SHA256:
- camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 128 );
- camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 128 );
- break;
-
- case SSL_RSA_CAMELLIA_256_SHA:
- case SSL_EDH_RSA_CAMELLIA_256_SHA:
- case SSL_RSA_CAMELLIA_256_SHA256:
- case SSL_EDH_RSA_CAMELLIA_256_SHA256:
- camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 256 );
- camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 256 );
- break;
-#endif
-
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- case SSL_RSA_NULL_MD5:
- case SSL_RSA_NULL_SHA:
- case SSL_RSA_NULL_SHA256:
- break;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#if defined(POLARSSL_DES_C)
- case SSL_RSA_DES_SHA:
- case SSL_EDH_RSA_DES_SHA:
- des_setkey_enc( (des_context *) ssl->ctx_enc, key1 );
- des_setkey_dec( (des_context *) ssl->ctx_dec, key2 );
- break;
-#endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
-
- default:
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- memset( keyblk, 0, sizeof( keyblk ) );
-
- SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
-
- return( 0 );
-}
-
-void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] )
-{
- md5_context md5;
- sha1_context sha1;
- unsigned char pad_1[48];
- unsigned char pad_2[48];
-
- SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) );
-
- memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
- memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
- sizeof( sha1_context ) );
-
- memset( pad_1, 0x36, 48 );
- memset( pad_2, 0x5C, 48 );
-
- md5_update( &md5, ssl->session->master, 48 );
- md5_update( &md5, pad_1, 48 );
- md5_finish( &md5, hash );
-
- md5_starts( &md5 );
- md5_update( &md5, ssl->session->master, 48 );
- md5_update( &md5, pad_2, 48 );
- md5_update( &md5, hash, 16 );
- md5_finish( &md5, hash );
-
- sha1_update( &sha1, ssl->session->master, 48 );
- sha1_update( &sha1, pad_1, 40 );
- sha1_finish( &sha1, hash + 16 );
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, ssl->session->master, 48 );
- sha1_update( &sha1, pad_2, 40 );
- sha1_update( &sha1, hash + 16, 20 );
- sha1_finish( &sha1, hash + 16 );
-
- SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
- SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
- return;
-}
-
-void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] )
-{
- md5_context md5;
- sha1_context sha1;
-
- SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) );
-
- memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
- memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
- sizeof( sha1_context ) );
-
- md5_finish( &md5, hash );
- sha1_finish( &sha1, hash + 16 );
-
- SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
- SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
- return;
-}
-
-void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] )
-{
- sha2_context sha2;
-
- SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) );
-
- memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) );
- sha2_finish( &sha2, hash );
-
- SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 );
- SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
- return;
-}
-
-void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] )
-{
- sha4_context sha4;
-
- SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) );
-
- memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) );
- sha4_finish( &sha4, hash );
-
- SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 );
- SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
- return;
-}
-
-/*
- * SSLv3.0 MAC functions
- */
-static void ssl_mac_md5( unsigned char *secret,
- unsigned char *buf, size_t len,
- unsigned char *ctr, int type )
-{
- unsigned char header[11];
- unsigned char padding[48];
- md5_context md5;
-
- memcpy( header, ctr, 8 );
- header[ 8] = (unsigned char) type;
- header[ 9] = (unsigned char)( len >> 8 );
- header[10] = (unsigned char)( len );
-
- memset( padding, 0x36, 48 );
- md5_starts( &md5 );
- md5_update( &md5, secret, 16 );
- md5_update( &md5, padding, 48 );
- md5_update( &md5, header, 11 );
- md5_update( &md5, buf, len );
- md5_finish( &md5, buf + len );
-
- memset( padding, 0x5C, 48 );
- md5_starts( &md5 );
- md5_update( &md5, secret, 16 );
- md5_update( &md5, padding, 48 );
- md5_update( &md5, buf + len, 16 );
- md5_finish( &md5, buf + len );
-}
-
-static void ssl_mac_sha1( unsigned char *secret,
- unsigned char *buf, size_t len,
- unsigned char *ctr, int type )
-{
- unsigned char header[11];
- unsigned char padding[40];
- sha1_context sha1;
-
- memcpy( header, ctr, 8 );
- header[ 8] = (unsigned char) type;
- header[ 9] = (unsigned char)( len >> 8 );
- header[10] = (unsigned char)( len );
-
- memset( padding, 0x36, 40 );
- sha1_starts( &sha1 );
- sha1_update( &sha1, secret, 20 );
- sha1_update( &sha1, padding, 40 );
- sha1_update( &sha1, header, 11 );
- sha1_update( &sha1, buf, len );
- sha1_finish( &sha1, buf + len );
-
- memset( padding, 0x5C, 40 );
- sha1_starts( &sha1 );
- sha1_update( &sha1, secret, 20 );
- sha1_update( &sha1, padding, 40 );
- sha1_update( &sha1, buf + len, 20 );
- sha1_finish( &sha1, buf + len );
-}
-
-/*
- * Encryption/decryption functions
- */
-static int ssl_encrypt_buf( ssl_context *ssl )
-{
- size_t i, padlen;
-
- SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
-
- /*
- * Add MAC then encrypt
- */
- if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- if( ssl->maclen == 16 )
- ssl_mac_md5( ssl->mac_enc,
- ssl->out_msg, ssl->out_msglen,
- ssl->out_ctr, ssl->out_msgtype );
-
- if( ssl->maclen == 20 )
- ssl_mac_sha1( ssl->mac_enc,
- ssl->out_msg, ssl->out_msglen,
- ssl->out_ctr, ssl->out_msgtype );
- }
- else
- {
- if( ssl->maclen == 16 )
- md5_hmac( ssl->mac_enc, 16,
- ssl->out_ctr, ssl->out_msglen + 13,
- ssl->out_msg + ssl->out_msglen );
-
- if( ssl->maclen == 20 )
- sha1_hmac( ssl->mac_enc, 20,
- ssl->out_ctr, ssl->out_msglen + 13,
- ssl->out_msg + ssl->out_msglen );
-
- if( ssl->maclen == 32 )
- sha2_hmac( ssl->mac_enc, 32,
- ssl->out_ctr, ssl->out_msglen + 13,
- ssl->out_msg + ssl->out_msglen, 0);
- }
-
- SSL_DEBUG_BUF( 4, "computed mac",
- ssl->out_msg + ssl->out_msglen, ssl->maclen );
-
- ssl->out_msglen += ssl->maclen;
-
- if( ssl->ivlen == 0 )
- {
- padlen = 0;
-
- SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of padding",
- ssl->out_msglen, 0 ) );
-
- SSL_DEBUG_BUF( 4, "before encrypt: output payload",
- ssl->out_msg, ssl->out_msglen );
-
-#if defined(POLARSSL_ARC4_C)
- if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 ||
- ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA )
- {
- arc4_crypt( (arc4_context *) ssl->ctx_enc,
- ssl->out_msglen, ssl->out_msg,
- ssl->out_msg );
- } else
-#endif
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 ||
- ssl->session->ciphersuite == SSL_RSA_NULL_SHA ||
- ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 )
- {
- } else
-#endif
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
- }
- else if( ssl->ivlen == 12 )
- {
- size_t enc_msglen;
- unsigned char *enc_msg;
- unsigned char add_data[13];
- int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
-
- padlen = 0;
- enc_msglen = ssl->out_msglen;
-
- memcpy( add_data, ssl->out_ctr, 8 );
- add_data[8] = ssl->out_msgtype;
- add_data[9] = ssl->major_ver;
- add_data[10] = ssl->minor_ver;
- add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
- add_data[12] = ssl->out_msglen & 0xFF;
-
- SSL_DEBUG_BUF( 4, "additional data used for AEAD",
- add_data, 13 );
-
-#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
-
- if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
- ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- /*
- * Generate IV
- */
- ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc + ssl->fixed_ivlen,
- ssl->ivlen - ssl->fixed_ivlen );
- if( ret != 0 )
- return( ret );
-
- /*
- * Shift message for ivlen bytes and prepend IV
- */
- memmove( ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen,
- ssl->out_msg, ssl->out_msglen );
- memcpy( ssl->out_msg, ssl->iv_enc + ssl->fixed_ivlen,
- ssl->ivlen - ssl->fixed_ivlen );
-
- /*
- * Fix pointer positions and message length with added IV
- */
- enc_msg = ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen;
- enc_msglen = ssl->out_msglen;
- ssl->out_msglen += ssl->ivlen - ssl->fixed_ivlen;
-
- SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of padding",
- ssl->out_msglen, 0 ) );
-
- SSL_DEBUG_BUF( 4, "before encrypt: output payload",
- ssl->out_msg, ssl->out_msglen );
-
- /*
- * Adjust for tag
- */
- ssl->out_msglen += 16;
-
- gcm_crypt_and_tag( (gcm_context *) ssl->ctx_enc,
- GCM_ENCRYPT, enc_msglen,
- ssl->iv_enc, ssl->ivlen,
- add_data, 13,
- enc_msg, enc_msg,
- 16, enc_msg + enc_msglen );
-
- SSL_DEBUG_BUF( 4, "after encrypt: tag",
- enc_msg + enc_msglen, 16 );
-
- } else
-#endif
- return( ret );
- }
- else
- {
- unsigned char *enc_msg;
- size_t enc_msglen;
-
- padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen;
- if( padlen == ssl->ivlen )
- padlen = 0;
-
- for( i = 0; i <= padlen; i++ )
- ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen;
-
- ssl->out_msglen += padlen + 1;
-
- enc_msglen = ssl->out_msglen;
- enc_msg = ssl->out_msg;
-
- /*
- * Prepend per-record IV for block cipher in TLS v1.1 and up as per
- * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
- */
- if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
- {
- /*
- * Generate IV
- */
- int ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc, ssl->ivlen );
- if( ret != 0 )
- return( ret );
-
- /*
- * Shift message for ivlen bytes and prepend IV
- */
- memmove( ssl->out_msg + ssl->ivlen, ssl->out_msg, ssl->out_msglen );
- memcpy( ssl->out_msg, ssl->iv_enc, ssl->ivlen );
-
- /*
- * Fix pointer positions and message length with added IV
- */
- enc_msg = ssl->out_msg + ssl->ivlen;
- enc_msglen = ssl->out_msglen;
- ssl->out_msglen += ssl->ivlen;
- }
-
- SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of IV and %d bytes of padding",
- ssl->out_msglen, ssl->ivlen, padlen + 1 ) );
-
- SSL_DEBUG_BUF( 4, "before encrypt: output payload",
- ssl->out_msg, ssl->out_msglen );
-
- switch( ssl->ivlen )
- {
-#if defined(POLARSSL_DES_C)
- case 8:
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
- if( ssl->session->ciphersuite == SSL_RSA_DES_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA )
- {
- des_crypt_cbc( (des_context *) ssl->ctx_enc,
- DES_ENCRYPT, enc_msglen,
- ssl->iv_enc, enc_msg, enc_msg );
- }
- else
-#endif
- des3_crypt_cbc( (des3_context *) ssl->ctx_enc,
- DES_ENCRYPT, enc_msglen,
- ssl->iv_enc, enc_msg, enc_msg );
- break;
-#endif
-
- case 16:
-#if defined(POLARSSL_AES_C)
- if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
- ssl->session->ciphersuite == SSL_RSA_AES_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
- ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
- ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 )
- {
- aes_crypt_cbc( (aes_context *) ssl->ctx_enc,
- AES_ENCRYPT, enc_msglen,
- ssl->iv_enc, enc_msg, enc_msg);
- break;
- }
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
- if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
- ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
- ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
- ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 )
- {
- camellia_crypt_cbc( (camellia_context *) ssl->ctx_enc,
- CAMELLIA_ENCRYPT, enc_msglen,
- ssl->iv_enc, enc_msg, enc_msg );
- break;
- }
-#endif
-
- default:
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
- }
- }
-
- for( i = 8; i > 0; i-- )
- if( ++ssl->out_ctr[i - 1] != 0 )
- break;
-
- SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
-
- return( 0 );
-}
-
-/*
- * TODO: Use digest version when integrated!
- */
-#define POLARSSL_SSL_MAX_MAC_SIZE 32
-
-static int ssl_decrypt_buf( ssl_context *ssl )
-{
- size_t i, padlen;
- unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
-
- SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
-
- if( ssl->in_msglen < ssl->minlen )
- {
- SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)",
- ssl->in_msglen, ssl->minlen ) );
- return( POLARSSL_ERR_SSL_INVALID_MAC );
- }
-
- if( ssl->ivlen == 0 )
- {
-#if defined(POLARSSL_ARC4_C)
- padlen = 0;
- if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 ||
- ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA )
- {
- arc4_crypt( (arc4_context *) ssl->ctx_dec,
- ssl->in_msglen, ssl->in_msg,
- ssl->in_msg );
- } else
-#endif
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 ||
- ssl->session->ciphersuite == SSL_RSA_NULL_SHA ||
- ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 )
- {
- } else
-#endif
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
- }
- else if( ssl->ivlen == 12 )
- {
- unsigned char *dec_msg;
- unsigned char *dec_msg_result;
- size_t dec_msglen;
- unsigned char add_data[13];
- int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
-
- padlen = 0;
-
-#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
- if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
- ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- dec_msglen = ssl->in_msglen - ( ssl->ivlen - ssl->fixed_ivlen );
- dec_msglen -= 16;
- dec_msg = ssl->in_msg + ( ssl->ivlen - ssl->fixed_ivlen );
- dec_msg_result = ssl->in_msg;
- ssl->in_msglen = dec_msglen;
-
- memcpy( add_data, ssl->in_ctr, 8 );
- add_data[8] = ssl->in_msgtype;
- add_data[9] = ssl->major_ver;
- add_data[10] = ssl->minor_ver;
- add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
- add_data[12] = ssl->in_msglen & 0xFF;
-
- SSL_DEBUG_BUF( 4, "additional data used for AEAD",
- add_data, 13 );
-
- memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg,
- ssl->ivlen - ssl->fixed_ivlen );
-
- SSL_DEBUG_BUF( 4, "IV used", ssl->iv_dec, ssl->ivlen );
- SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
-
- memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg,
- ssl->ivlen - ssl->fixed_ivlen );
-
- ret = gcm_auth_decrypt( (gcm_context *) ssl->ctx_dec,
- dec_msglen,
- ssl->iv_dec, ssl->ivlen,
- add_data, 13,
- dec_msg + dec_msglen, 16,
- dec_msg, dec_msg_result );
-
- if( ret != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)",
- -ret ) );
-
- return( POLARSSL_ERR_SSL_INVALID_MAC );
- }
- } else
-#endif
- return( ret );
- }
- else
- {
- unsigned char *dec_msg;
- unsigned char *dec_msg_result;
- size_t dec_msglen;
-
- /*
- * Decrypt and check the padding
- */
- if( ssl->in_msglen % ssl->ivlen != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
- ssl->in_msglen, ssl->ivlen ) );
- return( POLARSSL_ERR_SSL_INVALID_MAC );
- }
-
- dec_msglen = ssl->in_msglen;
- dec_msg = ssl->in_msg;
- dec_msg_result = ssl->in_msg;
-
- /*
- * Initialize for prepended IV for block cipher in TLS v1.1 and up
- */
- if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
- {
- dec_msg += ssl->ivlen;
- dec_msglen -= ssl->ivlen;
- ssl->in_msglen -= ssl->ivlen;
-
- for( i = 0; i < ssl->ivlen; i++ )
- ssl->iv_dec[i] = ssl->in_msg[i];
- }
-
- switch( ssl->ivlen )
- {
-#if defined(POLARSSL_DES_C)
- case 8:
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
- if( ssl->session->ciphersuite == SSL_RSA_DES_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA )
- {
- des_crypt_cbc( (des_context *) ssl->ctx_dec,
- DES_DECRYPT, dec_msglen,
- ssl->iv_dec, dec_msg, dec_msg_result );
- }
- else
-#endif
- des3_crypt_cbc( (des3_context *) ssl->ctx_dec,
- DES_DECRYPT, dec_msglen,
- ssl->iv_dec, dec_msg, dec_msg_result );
- break;
-#endif
-
- case 16:
-#if defined(POLARSSL_AES_C)
- if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
- ssl->session->ciphersuite == SSL_RSA_AES_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
- ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
- ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 )
- {
- aes_crypt_cbc( (aes_context *) ssl->ctx_dec,
- AES_DECRYPT, dec_msglen,
- ssl->iv_dec, dec_msg, dec_msg_result );
- break;
- }
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
- if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
- ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
- ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
- ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 ||
- ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 )
- {
- camellia_crypt_cbc( (camellia_context *) ssl->ctx_dec,
- CAMELLIA_DECRYPT, dec_msglen,
- ssl->iv_dec, dec_msg, dec_msg_result );
- break;
- }
-#endif
-
- default:
- return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- if( padlen > ssl->ivlen )
- {
- SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
- "should be no more than %d",
- padlen, ssl->ivlen ) );
- padlen = 0;
- }
- }
- else
- {
- /*
- * TLSv1: always check the padding
- */
- for( i = 1; i <= padlen; i++ )
- {
- if( ssl->in_msg[ssl->in_msglen - i] != padlen - 1 )
- {
- SSL_DEBUG_MSG( 1, ( "bad padding byte: should be "
- "%02x, but is %02x", padlen - 1,
- ssl->in_msg[ssl->in_msglen - i] ) );
- padlen = 0;
- }
- }
- }
- }
-
- SSL_DEBUG_BUF( 4, "raw buffer after decryption",
- ssl->in_msg, ssl->in_msglen );
-
- /*
- * Always compute the MAC (RFC4346, CBCTIME).
- */
- if( ssl->in_msglen < ssl->maclen + padlen )
- {
- SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
- ssl->in_msglen, ssl->maclen, padlen ) );
- return( POLARSSL_ERR_SSL_INVALID_MAC );
- }
-
- ssl->in_msglen -= ( ssl->maclen + padlen );
-
- ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
- ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen );
-
- memcpy( tmp, ssl->in_msg + ssl->in_msglen, POLARSSL_SSL_MAX_MAC_SIZE );
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- if( ssl->maclen == 16 )
- ssl_mac_md5( ssl->mac_dec,
- ssl->in_msg, ssl->in_msglen,
- ssl->in_ctr, ssl->in_msgtype );
- else if( ssl->maclen == 20 )
- ssl_mac_sha1( ssl->mac_dec,
- ssl->in_msg, ssl->in_msglen,
- ssl->in_ctr, ssl->in_msgtype );
- }
- else
- {
- if( ssl->maclen == 16 )
- md5_hmac( ssl->mac_dec, 16,
- ssl->in_ctr, ssl->in_msglen + 13,
- ssl->in_msg + ssl->in_msglen );
- else if( ssl->maclen == 20 )
- sha1_hmac( ssl->mac_dec, 20,
- ssl->in_ctr, ssl->in_msglen + 13,
- ssl->in_msg + ssl->in_msglen );
- else if( ssl->maclen == 32 )
- sha2_hmac( ssl->mac_dec, 32,
- ssl->in_ctr, ssl->in_msglen + 13,
- ssl->in_msg + ssl->in_msglen, 0 );
- }
-
- SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->maclen );
- SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
- ssl->maclen );
-
- if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
- ssl->maclen ) != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
- return( POLARSSL_ERR_SSL_INVALID_MAC );
- }
-
- /*
- * Finally check the padding length; bad padding
- * will produce the same error as an invalid MAC.
- */
- if( ssl->ivlen != 0 && ssl->ivlen != 12 && padlen == 0 )
- return( POLARSSL_ERR_SSL_INVALID_MAC );
-
- if( ssl->in_msglen == 0 )
- {
- ssl->nb_zero++;
-
- /*
- * Three or more empty messages may be a DoS attack
- * (excessive CPU consumption).
- */
- if( ssl->nb_zero > 3 )
- {
- SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
- "messages, possible DoS attack" ) );
- return( POLARSSL_ERR_SSL_INVALID_MAC );
- }
- }
- else
- ssl->nb_zero = 0;
-
- for( i = 8; i > 0; i-- )
- if( ++ssl->in_ctr[i - 1] != 0 )
- break;
-
- SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
-
- return( 0 );
-}
-
-/*
- * Fill the input message buffer
- */
-int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
-{
- int ret;
- size_t len;
-
- SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
-
- while( ssl->in_left < nb_want )
- {
- len = nb_want - ssl->in_left;
- ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len );
-
- SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
- ssl->in_left, nb_want ) );
- SSL_DEBUG_RET( 2, "ssl->f_recv", ret );
-
- if( ret == 0 )
- return( POLARSSL_ERR_SSL_CONN_EOF );
-
- if( ret < 0 )
- return( ret );
-
- ssl->in_left += ret;
- }
-
- SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
-
- return( 0 );
-}
-
-/*
- * Flush any data not yet written
- */
-int ssl_flush_output( ssl_context *ssl )
-{
- int ret;
- unsigned char *buf;
-
- SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
-
- while( ssl->out_left > 0 )
- {
- SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
- 5 + ssl->out_msglen, ssl->out_left ) );
-
- buf = ssl->out_hdr + 5 + ssl->out_msglen - ssl->out_left;
- ret = ssl->f_send( ssl->p_send, buf, ssl->out_left );
- SSL_DEBUG_RET( 2, "ssl->f_send", ret );
-
- if( ret <= 0 )
- return( ret );
-
- ssl->out_left -= ret;
- }
-
- SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
-
- return( 0 );
-}
-
-/*
- * Record layer functions
- */
-int ssl_write_record( ssl_context *ssl )
-{
- int ret;
- size_t len = ssl->out_msglen;
-
- SSL_DEBUG_MSG( 2, ( "=> write record" ) );
-
- ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
- ssl->out_hdr[1] = (unsigned char) ssl->major_ver;
- ssl->out_hdr[2] = (unsigned char) ssl->minor_ver;
- ssl->out_hdr[3] = (unsigned char)( len >> 8 );
- ssl->out_hdr[4] = (unsigned char)( len );
-
- if( ssl->out_msgtype == SSL_MSG_HANDSHAKE )
- {
- ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
- ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 );
- ssl->out_msg[3] = (unsigned char)( ( len - 4 ) );
-
- ssl->update_checksum( ssl, ssl->out_msg, len );
- }
-
- if( ssl->do_crypt != 0 )
- {
- if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
- return( ret );
- }
-
- len = ssl->out_msglen;
- ssl->out_hdr[3] = (unsigned char)( len >> 8 );
- ssl->out_hdr[4] = (unsigned char)( len );
- }
-
- ssl->out_left = 5 + ssl->out_msglen;
-
- SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
- "version = [%d:%d], msglen = %d",
- ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
- ( ssl->out_hdr[3] << 8 ) | ssl->out_hdr[4] ) );
-
- SSL_DEBUG_BUF( 4, "output record sent to network",
- ssl->out_hdr, 5 + ssl->out_msglen );
-
- if( ( ret = ssl_flush_output( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write record" ) );
-
- return( 0 );
-}
-
-int ssl_read_record( ssl_context *ssl )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> read record" ) );
-
- if( ssl->in_hslen != 0 &&
- ssl->in_hslen < ssl->in_msglen )
- {
- /*
- * Get next Handshake message in the current record
- */
- ssl->in_msglen -= ssl->in_hslen;
-
- memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
- ssl->in_msglen );
-
- ssl->in_hslen = 4;
- ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
-
- SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
- " %d, type = %d, hslen = %d",
- ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
-
- if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- if( ssl->in_msglen < ssl->in_hslen )
- {
- SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
-
- return( 0 );
- }
-
- ssl->in_hslen = 0;
-
- /*
- * Read the record header and validate it
- */
- if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
- return( ret );
- }
-
- ssl->in_msgtype = ssl->in_hdr[0];
- ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4];
-
- SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
- "version = [%d:%d], msglen = %d",
- ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2],
- ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) );
-
- if( ssl->in_hdr[1] != ssl->major_ver )
- {
- SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- if( ssl->in_hdr[2] > ssl->max_minor_ver )
- {
- SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- /*
- * Make sure the message length is acceptable
- */
- if( ssl->do_crypt == 0 )
- {
- if( ssl->in_msglen < 1 ||
- ssl->in_msglen > SSL_MAX_CONTENT_LEN )
- {
- SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
- }
- else
- {
- if( ssl->in_msglen < ssl->minlen )
- {
- SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- if( ssl->minor_ver == SSL_MINOR_VERSION_0 &&
- ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN )
- {
- SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- /*
- * TLS encrypted messages can have up to 256 bytes of padding
- */
- if( ssl->minor_ver >= SSL_MINOR_VERSION_1 &&
- ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 )
- {
- SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
- }
-
- /*
- * Read and optionally decrypt the message contents
- */
- if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
- return( ret );
- }
-
- SSL_DEBUG_BUF( 4, "input record from network",
- ssl->in_hdr, 5 + ssl->in_msglen );
-
- if( ssl->do_crypt != 0 )
- {
- if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
- return( ret );
- }
-
- SSL_DEBUG_BUF( 4, "input payload after decrypt",
- ssl->in_msg, ssl->in_msglen );
-
- if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
- {
- SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE &&
- ssl->in_msgtype != SSL_MSG_ALERT &&
- ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC &&
- ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
- {
- SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
-
- if( ( ret = ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
- SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 )
- {
- return( ret );
- }
-
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
- {
- ssl->in_hslen = 4;
- ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
-
- SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
- " %d, type = %d, hslen = %d",
- ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
-
- /*
- * Additional checks to validate the handshake header
- */
- if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- if( ssl->in_msglen < ssl->in_hslen )
- {
- SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
- return( POLARSSL_ERR_SSL_INVALID_RECORD );
- }
-
- ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
- }
-
- if( ssl->in_msgtype == SSL_MSG_ALERT )
- {
- SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
- ssl->in_msg[0], ssl->in_msg[1] ) );
-
- /*
- * Ignore non-fatal alerts, except close_notify
- */
- if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL )
- {
- SSL_DEBUG_MSG( 1, ( "is a fatal alert message" ) );
- /**
- * Subtract from error code as ssl->in_msg[1] is 7-bit positive
- * error identifier.
- */
- return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE - ssl->in_msg[1] );
- }
-
- if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
- ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY )
- {
- SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
- return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY );
- }
- }
-
- ssl->in_left = 0;
-
- SSL_DEBUG_MSG( 2, ( "<= read record" ) );
-
- return( 0 );
-}
-
-int ssl_send_alert_message( ssl_context *ssl,
- unsigned char level,
- unsigned char message )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
-
- ssl->out_msgtype = SSL_MSG_ALERT;
- ssl->out_msglen = 2;
- ssl->out_msg[0] = level;
- ssl->out_msg[1] = message;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
-
- return( 0 );
-}
-
-/*
- * Handshake functions
- */
-int ssl_write_certificate( ssl_context *ssl )
-{
- int ret;
- size_t i, n;
- const x509_cert *crt;
-
- SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
-
- if( ssl->endpoint == SSL_IS_CLIENT )
- {
- if( ssl->client_auth == 0 )
- {
- SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
- /*
- * If using SSLv3 and got no cert, send an Alert message
- * (otherwise an empty Certificate message will be sent).
- */
- if( ssl->own_cert == NULL &&
- ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- ssl->out_msglen = 2;
- ssl->out_msgtype = SSL_MSG_ALERT;
- ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING;
- ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT;
-
- SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
- goto write_msg;
- }
- }
- else /* SSL_IS_SERVER */
- {
- if( ssl->own_cert == NULL )
- {
- SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
- return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED );
- }
- }
-
- SSL_DEBUG_CRT( 3, "own certificate", ssl->own_cert );
-
- /*
- * 0 . 0 handshake type
- * 1 . 3 handshake length
- * 4 . 6 length of all certs
- * 7 . 9 length of cert. 1
- * 10 . n-1 peer certificate
- * n . n+2 length of cert. 2
- * n+3 . ... upper level cert, etc.
- */
- i = 7;
- crt = ssl->own_cert;
-
- while( crt != NULL )
- {
- n = crt->raw.len;
- if( i + 3 + n > SSL_MAX_CONTENT_LEN )
- {
- SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
- i + 3 + n, SSL_MAX_CONTENT_LEN ) );
- return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
- }
-
- ssl->out_msg[i ] = (unsigned char)( n >> 16 );
- ssl->out_msg[i + 1] = (unsigned char)( n >> 8 );
- ssl->out_msg[i + 2] = (unsigned char)( n );
-
- i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
- i += n; crt = crt->next;
- }
-
- ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 );
- ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 );
- ssl->out_msg[6] = (unsigned char)( ( i - 7 ) );
-
- ssl->out_msglen = i;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_CERTIFICATE;
-
-write_msg:
-
- ssl->state++;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write certificate" ) );
-
- return( 0 );
-}
-
-int ssl_parse_certificate( ssl_context *ssl )
-{
- int ret;
- size_t i, n;
-
- SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
-
- if( ssl->endpoint == SSL_IS_SERVER &&
- ssl->authmode == SSL_VERIFY_NONE )
- {
- ssl->verify_result = BADCERT_SKIP_VERIFY;
- SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- ssl->state++;
-
- /*
- * Check if the client sent an empty certificate
- */
- if( ssl->endpoint == SSL_IS_SERVER &&
- ssl->minor_ver == SSL_MINOR_VERSION_0 )
- {
- if( ssl->in_msglen == 2 &&
- ssl->in_msgtype == SSL_MSG_ALERT &&
- ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
- ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT )
- {
- SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
-
- ssl->verify_result = BADCERT_MISSING;
- if( ssl->authmode == SSL_VERIFY_OPTIONAL )
- return( 0 );
- else
- return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
- }
- }
-
- if( ssl->endpoint == SSL_IS_SERVER &&
- ssl->minor_ver != SSL_MINOR_VERSION_0 )
- {
- if( ssl->in_hslen == 7 &&
- ssl->in_msgtype == SSL_MSG_HANDSHAKE &&
- ssl->in_msg[0] == SSL_HS_CERTIFICATE &&
- memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 )
- {
- SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
-
- ssl->verify_result = BADCERT_MISSING;
- if( ssl->authmode == SSL_VERIFY_REQUIRED )
- return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
- else
- return( 0 );
- }
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
- }
-
- /*
- * Same message structure as in ssl_write_certificate()
- */
- n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6];
-
- if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
- }
-
- if( ( ssl->peer_cert = (x509_cert *) malloc(
- sizeof( x509_cert ) ) ) == NULL )
- {
- SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed",
- sizeof( x509_cert ) ) );
- return( POLARSSL_ERR_SSL_MALLOC_FAILED );
- }
-
- memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
-
- i = 7;
-
- while( i < ssl->in_hslen )
- {
- if( ssl->in_msg[i] != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
- }
-
- n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
- | (unsigned int) ssl->in_msg[i + 2];
- i += 3;
-
- if( n < 128 || i + n > ssl->in_hslen )
- {
- SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
- }
-
- ret = x509parse_crt( ssl->peer_cert, ssl->in_msg + i, n );
- if( ret != 0 )
- {
- SSL_DEBUG_RET( 1, " x509parse_crt", ret );
- return( ret );
- }
-
- i += n;
- }
-
- SSL_DEBUG_CRT( 3, "peer certificate", ssl->peer_cert );
-
- if( ssl->authmode != SSL_VERIFY_NONE )
- {
- if( ssl->ca_chain == NULL )
- {
- SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
- return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
- }
-
- ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain, ssl->ca_crl,
- ssl->peer_cn, &ssl->verify_result,
- ssl->f_vrfy, ssl->p_vrfy );
-
- if( ret != 0 )
- SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
-
- if( ssl->authmode != SSL_VERIFY_REQUIRED )
- ret = 0;
- }
-
- SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
-
- return( ret );
-}
-
-int ssl_write_change_cipher_spec( ssl_context *ssl )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
-
- ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC;
- ssl->out_msglen = 1;
- ssl->out_msg[0] = 1;
-
- ssl->do_crypt = 0;
- ssl->state++;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
-
- return( 0 );
-}
-
-int ssl_parse_change_cipher_spec( ssl_context *ssl )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
-
- ssl->do_crypt = 0;
-
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC )
- {
- SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
- {
- SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
- }
-
- ssl->state++;
-
- SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
-
- return( 0 );
-}
-
-void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite,
- unsigned char *input_buf, size_t len )
-{
- if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
- {
- md5_starts( (md5_context *) ssl->ctx_checksum );
- sha1_starts( (sha1_context *) ( ssl->ctx_checksum +
- sizeof(md5_context) ) );
-
- ssl->update_checksum = ssl_update_checksum_md5sha1;
- }
- else if ( ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
- ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
- {
- sha4_starts( (sha4_context *) ssl->ctx_checksum, 1 );
- ssl->update_checksum = ssl_update_checksum_sha384;
- }
- else
- {
- sha2_starts( (sha2_context *) ssl->ctx_checksum, 0 );
- ssl->update_checksum = ssl_update_checksum_sha256;
- }
-
- if( ssl->endpoint == SSL_IS_CLIENT )
- ssl->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
- ssl->update_checksum( ssl, input_buf, len );
-}
-
-static void ssl_update_checksum_start( ssl_context *ssl, unsigned char *buf,
- size_t len )
-{
- ((void) ssl);
- ((void) buf);
- ((void) len);
-}
-
-static void ssl_update_checksum_md5sha1( ssl_context *ssl, unsigned char *buf,
- size_t len )
-{
- md5_update( (md5_context *) ssl->ctx_checksum, buf, len );
- sha1_update( (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
- buf, len );
-}
-
-static void ssl_update_checksum_sha256( ssl_context *ssl, unsigned char *buf,
- size_t len )
-{
- sha2_update( (sha2_context *) ssl->ctx_checksum, buf, len );
-}
-
-static void ssl_update_checksum_sha384( ssl_context *ssl, unsigned char *buf,
- size_t len )
-{
- sha4_update( (sha4_context *) ssl->ctx_checksum, buf, len );
-}
-
-static void ssl_calc_finished_ssl(
- ssl_context *ssl, unsigned char *buf, int from )
-{
- char *sender;
- md5_context md5;
- sha1_context sha1;
-
- unsigned char padbuf[48];
- unsigned char md5sum[16];
- unsigned char sha1sum[20];
-
- SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) );
-
- memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
- memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
- sizeof( sha1_context ) );
-
- /*
- * SSLv3:
- * hash =
- * MD5( master + pad2 +
- * MD5( handshake + sender + master + pad1 ) )
- * + SHA1( master + pad2 +
- * SHA1( handshake + sender + master + pad1 ) )
- */
-
- SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
- md5.state, sizeof( md5.state ) );
-
- SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
- sha1.state, sizeof( sha1.state ) );
-
- sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT"
- : (char *) "SRVR";
-
- memset( padbuf, 0x36, 48 );
-
- md5_update( &md5, (unsigned char *) sender, 4 );
- md5_update( &md5, ssl->session->master, 48 );
- md5_update( &md5, padbuf, 48 );
- md5_finish( &md5, md5sum );
-
- sha1_update( &sha1, (unsigned char *) sender, 4 );
- sha1_update( &sha1, ssl->session->master, 48 );
- sha1_update( &sha1, padbuf, 40 );
- sha1_finish( &sha1, sha1sum );
-
- memset( padbuf, 0x5C, 48 );
-
- md5_starts( &md5 );
- md5_update( &md5, ssl->session->master, 48 );
- md5_update( &md5, padbuf, 48 );
- md5_update( &md5, md5sum, 16 );
- md5_finish( &md5, buf );
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, ssl->session->master, 48 );
- sha1_update( &sha1, padbuf , 40 );
- sha1_update( &sha1, sha1sum, 20 );
- sha1_finish( &sha1, buf + 16 );
-
- SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 );
-
- memset( &md5, 0, sizeof( md5_context ) );
- memset( &sha1, 0, sizeof( sha1_context ) );
-
- memset( padbuf, 0, sizeof( padbuf ) );
- memset( md5sum, 0, sizeof( md5sum ) );
- memset( sha1sum, 0, sizeof( sha1sum ) );
-
- SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
-}
-
-static void ssl_calc_finished_tls(
- ssl_context *ssl, unsigned char *buf, int from )
-{
- int len = 12;
- char *sender;
- md5_context md5;
- sha1_context sha1;
- unsigned char padbuf[36];
-
- SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) );
-
- memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
- memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
- sizeof( sha1_context ) );
-
- /*
- * TLSv1:
- * hash = PRF( master, finished_label,
- * MD5( handshake ) + SHA1( handshake ) )[0..11]
- */
-
- SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
- md5.state, sizeof( md5.state ) );
-
- SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
- sha1.state, sizeof( sha1.state ) );
-
- sender = ( from == SSL_IS_CLIENT )
- ? (char *) "client finished"
- : (char *) "server finished";
-
- md5_finish( &md5, padbuf );
- sha1_finish( &sha1, padbuf + 16 );
-
- ssl->tls_prf( ssl->session->master, 48, sender,
- padbuf, 36, buf, len );
-
- SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
-
- memset( &md5, 0, sizeof( md5_context ) );
- memset( &sha1, 0, sizeof( sha1_context ) );
-
- memset( padbuf, 0, sizeof( padbuf ) );
-
- SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
-}
-
-static void ssl_calc_finished_tls_sha256(
- ssl_context *ssl, unsigned char *buf, int from )
-{
- int len = 12;
- char *sender;
- sha2_context sha2;
- unsigned char padbuf[32];
-
- SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) );
-
- memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) );
-
- /*
- * TLSv1.2:
- * hash = PRF( master, finished_label,
- * Hash( handshake ) )[0.11]
- */
-
- SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *)
- sha2.state, sizeof( sha2.state ) );
-
- sender = ( from == SSL_IS_CLIENT )
- ? (char *) "client finished"
- : (char *) "server finished";
-
- sha2_finish( &sha2, padbuf );
-
- ssl->tls_prf( ssl->session->master, 48, sender,
- padbuf, 32, buf, len );
-
- SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
-
- memset( &sha2, 0, sizeof( sha2_context ) );
-
- memset( padbuf, 0, sizeof( padbuf ) );
-
- SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
-}
-
-static void ssl_calc_finished_tls_sha384(
- ssl_context *ssl, unsigned char *buf, int from )
-{
- int len = 12;
- char *sender;
- sha4_context sha4;
- unsigned char padbuf[48];
-
- SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) );
-
- memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) );
-
- /*
- * TLSv1.2:
- * hash = PRF( master, finished_label,
- * Hash( handshake ) )[0.11]
- */
-
- SSL_DEBUG_BUF( 4, "finished sha4 state", (unsigned char *)
- sha4.state, sizeof( sha4.state ) );
-
- sender = ( from == SSL_IS_CLIENT )
- ? (char *) "client finished"
- : (char *) "server finished";
-
- sha4_finish( &sha4, padbuf );
-
- ssl->tls_prf( ssl->session->master, 48, sender,
- padbuf, 48, buf, len );
-
- SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
-
- memset( &sha4, 0, sizeof( sha4_context ) );
-
- memset( padbuf, 0, sizeof( padbuf ) );
-
- SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
-}
-
-int ssl_write_finished( ssl_context *ssl )
-{
- int ret, hash_len;
-
- SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
-
- ssl->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint );
-
- // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
- hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
-
- ssl->out_msglen = 4 + hash_len;
- ssl->out_msgtype = SSL_MSG_HANDSHAKE;
- ssl->out_msg[0] = SSL_HS_FINISHED;
-
- /*
- * In case of session resuming, invert the client and server
- * ChangeCipherSpec messages order.
- */
- if( ssl->resume != 0 )
- {
- if( ssl->endpoint == SSL_IS_CLIENT )
- ssl->state = SSL_HANDSHAKE_OVER;
- else
- ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
- }
- else
- ssl->state++;
-
- ssl->do_crypt = 1;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
-
- return( 0 );
-}
-
-int ssl_parse_finished( ssl_context *ssl )
-{
- int ret;
- unsigned int hash_len;
- unsigned char buf[36];
-
- SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
-
- ssl->calc_finished( ssl, buf, ssl->endpoint ^ 1 );
-
- ssl->do_crypt = 1;
-
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
- {
- SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
- hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
-
- if( ssl->in_msg[0] != SSL_HS_FINISHED ||
- ssl->in_hslen != 4 + hash_len )
- {
- SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
- }
-
- if( memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
- {
- SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
- return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
- }
-
- if( ssl->resume != 0 )
- {
- if( ssl->endpoint == SSL_IS_CLIENT )
- ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
-
- if( ssl->endpoint == SSL_IS_SERVER )
- ssl->state = SSL_HANDSHAKE_OVER;
- }
- else
- ssl->state++;
-
- SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
-
- return( 0 );
-}
-
-/*
- * Initialize an SSL context
- */
-int ssl_init( ssl_context *ssl )
-{
- int len = SSL_BUFFER_LEN;
-
- memset( ssl, 0, sizeof( ssl_context ) );
-
- ssl->in_ctr = (unsigned char *) malloc( len );
- ssl->in_hdr = ssl->in_ctr + 8;
- ssl->in_msg = ssl->in_ctr + 13;
-
- if( ssl->in_ctr == NULL )
- {
- SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
- return( POLARSSL_ERR_SSL_MALLOC_FAILED );
- }
-
- ssl->out_ctr = (unsigned char *) malloc( len );
- ssl->out_hdr = ssl->out_ctr + 8;
- ssl->out_msg = ssl->out_ctr + 13;
-
- if( ssl->out_ctr == NULL )
- {
- SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
- free( ssl-> in_ctr );
- return( POLARSSL_ERR_SSL_MALLOC_FAILED );
- }
-
- memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN );
- memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
-
- ssl->hostname = NULL;
- ssl->hostname_len = 0;
-
- ssl->update_checksum = ssl_update_checksum_start;
-
- return( 0 );
-}
-
-/*
- * Reset an initialized and used SSL context for re-use while retaining
- * all application-set variables, function pointers and data.
- */
-void ssl_session_reset( ssl_context *ssl )
-{
- ssl->state = SSL_HELLO_REQUEST;
-
- ssl->in_offt = NULL;
-
- ssl->in_msgtype = 0;
- ssl->in_msglen = 0;
- ssl->in_left = 0;
-
- ssl->in_hslen = 0;
- ssl->nb_zero = 0;
-
- ssl->out_msgtype = 0;
- ssl->out_msglen = 0;
- ssl->out_left = 0;
-
- ssl->do_crypt = 0;
- ssl->pmslen = 0;
- ssl->keylen = 0;
- ssl->minlen = 0;
- ssl->ivlen = 0;
- ssl->maclen = 0;
-
- memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
- memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
- memset( ssl->randbytes, 0, 64 );
- memset( ssl->premaster, 0, 256 );
- memset( ssl->iv_enc, 0, 16 );
- memset( ssl->iv_dec, 0, 16 );
- memset( ssl->mac_enc, 0, 32 );
- memset( ssl->mac_dec, 0, 32 );
- memset( ssl->ctx_enc, 0, 128 );
- memset( ssl->ctx_dec, 0, 128 );
-
- ssl->update_checksum = ssl_update_checksum_start;
-}
-
-/*
- * SSL set accessors
- */
-void ssl_set_endpoint( ssl_context *ssl, int endpoint )
-{
- ssl->endpoint = endpoint;
-}
-
-void ssl_set_authmode( ssl_context *ssl, int authmode )
-{
- ssl->authmode = authmode;
-}
-
-void ssl_set_verify( ssl_context *ssl,
- int (*f_vrfy)(void *, x509_cert *, int, int),
- void *p_vrfy )
-{
- ssl->f_vrfy = f_vrfy;
- ssl->p_vrfy = p_vrfy;
-}
-
-void ssl_set_rng( ssl_context *ssl,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
-{
- ssl->f_rng = f_rng;
- ssl->p_rng = p_rng;
-}
-
-void ssl_set_dbg( ssl_context *ssl,
- void (*f_dbg)(void *, int, const char *),
- void *p_dbg )
-{
- ssl->f_dbg = f_dbg;
- ssl->p_dbg = p_dbg;
-}
-
-void ssl_set_bio( ssl_context *ssl,
- int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
- int (*f_send)(void *, const unsigned char *, size_t), void *p_send )
-{
- ssl->f_recv = f_recv;
- ssl->f_send = f_send;
- ssl->p_recv = p_recv;
- ssl->p_send = p_send;
-}
-
-void ssl_set_scb( ssl_context *ssl,
- int (*s_get)(ssl_context *),
- int (*s_set)(ssl_context *) )
-{
- ssl->s_get = s_get;
- ssl->s_set = s_set;
-}
-
-void ssl_set_session( ssl_context *ssl, int resume, int timeout,
- ssl_session *session )
-{
- ssl->resume = resume;
- ssl->timeout = timeout;
- ssl->session = session;
-}
-
-void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites )
-{
- ssl->ciphersuites = ciphersuites;
-}
-
-void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
- x509_crl *ca_crl, const char *peer_cn )
-{
- ssl->ca_chain = ca_chain;
- ssl->ca_crl = ca_crl;
- ssl->peer_cn = peer_cn;
-}
-
-void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
- rsa_context *rsa_key )
-{
- ssl->own_cert = own_cert;
- ssl->rsa_key = rsa_key;
-}
-
-#if defined(POLARSSL_PKCS11_C)
-void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert,
- pkcs11_context *pkcs11_key )
-{
- ssl->own_cert = own_cert;
- ssl->pkcs11_key = pkcs11_key;
-}
-#endif
-
-int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G )
-{
- int ret;
-
- if( ( ret = mpi_read_string( &ssl->dhm_ctx.P, 16, dhm_P ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "mpi_read_string", ret );
- return( ret );
- }
-
- if( ( ret = mpi_read_string( &ssl->dhm_ctx.G, 16, dhm_G ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "mpi_read_string", ret );
- return( ret );
- }
-
- return( 0 );
-}
-
-int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
-{
- int ret;
-
- if( ( ret = mpi_copy(&ssl->dhm_ctx.P, &dhm_ctx->P) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "mpi_copy", ret );
- return( ret );
- }
-
- if( ( ret = mpi_copy(&ssl->dhm_ctx.G, &dhm_ctx->G) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "mpi_copy", ret );
- return( ret );
- }
-
- return( 0 );
-}
-
-int ssl_set_hostname( ssl_context *ssl, const char *hostname )
-{
- if( hostname == NULL )
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-
- ssl->hostname_len = strlen( hostname );
- ssl->hostname = (unsigned char *) malloc( ssl->hostname_len + 1 );
-
- if( ssl->hostname == NULL )
- return( POLARSSL_ERR_SSL_MALLOC_FAILED );
-
- memcpy( ssl->hostname, (unsigned char *) hostname,
- ssl->hostname_len );
-
- ssl->hostname[ssl->hostname_len] = '\0';
-
- return( 0 );
-}
-
-void ssl_set_max_version( ssl_context *ssl, int major, int minor )
-{
- ssl->max_major_ver = major;
- ssl->max_minor_ver = minor;
-}
-
-/*
- * SSL get accessors
- */
-size_t ssl_get_bytes_avail( const ssl_context *ssl )
-{
- return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
-}
-
-int ssl_get_verify_result( const ssl_context *ssl )
-{
- return( ssl->verify_result );
-}
-
-const char *ssl_get_ciphersuite_name( const int ciphersuite_id )
-{
- switch( ciphersuite_id )
- {
-#if defined(POLARSSL_ARC4_C)
- case SSL_RSA_RC4_128_MD5:
- return( "SSL-RSA-RC4-128-MD5" );
-
- case SSL_RSA_RC4_128_SHA:
- return( "SSL-RSA-RC4-128-SHA" );
-#endif
-
-#if defined(POLARSSL_DES_C)
- case SSL_RSA_DES_168_SHA:
- return( "SSL-RSA-DES-168-SHA" );
-
- case SSL_EDH_RSA_DES_168_SHA:
- return( "SSL-EDH-RSA-DES-168-SHA" );
-#endif
-
-#if defined(POLARSSL_AES_C)
- case SSL_RSA_AES_128_SHA:
- return( "SSL-RSA-AES-128-SHA" );
-
- case SSL_EDH_RSA_AES_128_SHA:
- return( "SSL-EDH-RSA-AES-128-SHA" );
-
- case SSL_RSA_AES_256_SHA:
- return( "SSL-RSA-AES-256-SHA" );
-
- case SSL_EDH_RSA_AES_256_SHA:
- return( "SSL-EDH-RSA-AES-256-SHA" );
-
-#if defined(POLARSSL_SHA2_C)
- case SSL_RSA_AES_128_SHA256:
- return( "SSL-RSA-AES-128-SHA256" );
-
- case SSL_EDH_RSA_AES_128_SHA256:
- return( "SSL-EDH-RSA-AES-128-SHA256" );
-
- case SSL_RSA_AES_256_SHA256:
- return( "SSL-RSA-AES-256-SHA256" );
-
- case SSL_EDH_RSA_AES_256_SHA256:
- return( "SSL-EDH-RSA-AES-256-SHA256" );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
- case SSL_RSA_AES_128_GCM_SHA256:
- return( "SSL-RSA-AES-128-GCM-SHA256" );
-
- case SSL_EDH_RSA_AES_128_GCM_SHA256:
- return( "SSL-EDH-RSA-AES-128-GCM-SHA256" );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
- case SSL_RSA_AES_256_GCM_SHA384:
- return( "SSL-RSA-AES-256-GCM-SHA384" );
-
- case SSL_EDH_RSA_AES_256_GCM_SHA384:
- return( "SSL-EDH-RSA-AES-256-GCM-SHA384" );
-#endif
-#endif /* POLARSSL_AES_C */
-
-#if defined(POLARSSL_CAMELLIA_C)
- case SSL_RSA_CAMELLIA_128_SHA:
- return( "SSL-RSA-CAMELLIA-128-SHA" );
-
- case SSL_EDH_RSA_CAMELLIA_128_SHA:
- return( "SSL-EDH-RSA-CAMELLIA-128-SHA" );
-
- case SSL_RSA_CAMELLIA_256_SHA:
- return( "SSL-RSA-CAMELLIA-256-SHA" );
-
- case SSL_EDH_RSA_CAMELLIA_256_SHA:
- return( "SSL-EDH-RSA-CAMELLIA-256-SHA" );
-
-#if defined(POLARSSL_SHA2_C)
- case SSL_RSA_CAMELLIA_128_SHA256:
- return( "SSL-RSA-CAMELLIA-128-SHA256" );
-
- case SSL_EDH_RSA_CAMELLIA_128_SHA256:
- return( "SSL-EDH-RSA-CAMELLIA-128-SHA256" );
-
- case SSL_RSA_CAMELLIA_256_SHA256:
- return( "SSL-RSA-CAMELLIA-256-SHA256" );
-
- case SSL_EDH_RSA_CAMELLIA_256_SHA256:
- return( "SSL-EDH-RSA-CAMELLIA-256-SHA256" );
-#endif
-#endif
-
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- case SSL_RSA_NULL_MD5:
- return( "SSL-RSA-NULL-MD5" );
- case SSL_RSA_NULL_SHA:
- return( "SSL-RSA-NULL-SHA" );
- case SSL_RSA_NULL_SHA256:
- return( "SSL-RSA-NULL-SHA256" );
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#if defined(POLARSSL_DES_C)
- case SSL_RSA_DES_SHA:
- return( "SSL-RSA-DES-SHA" );
- case SSL_EDH_RSA_DES_SHA:
- return( "SSL-EDH-RSA-DES-SHA" );
-#endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
-
- default:
- break;
- }
-
- return( "unknown" );
-}
-
-int ssl_get_ciphersuite_id( const char *ciphersuite_name )
-{
-#if defined(POLARSSL_ARC4_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-MD5"))
- return( SSL_RSA_RC4_128_MD5 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-SHA"))
- return( SSL_RSA_RC4_128_SHA );
-#endif
-
-#if defined(POLARSSL_DES_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-DES-168-SHA"))
- return( SSL_RSA_DES_168_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-DES-168-SHA"))
- return( SSL_EDH_RSA_DES_168_SHA );
-#endif
-
-#if defined(POLARSSL_AES_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-SHA"))
- return( SSL_RSA_AES_128_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-SHA"))
- return( SSL_EDH_RSA_AES_128_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-SHA"))
- return( SSL_RSA_AES_256_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA"))
- return( SSL_EDH_RSA_AES_256_SHA );
-
-#if defined(POLARSSL_SHA2_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-SHA256"))
- return( SSL_RSA_AES_128_SHA256 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-SHA256"))
- return( SSL_EDH_RSA_AES_128_SHA256 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-SHA256"))
- return( SSL_RSA_AES_256_SHA256 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA256"))
- return( SSL_EDH_RSA_AES_256_SHA256 );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-GCM-SHA256"))
- return( SSL_RSA_AES_128_GCM_SHA256 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-GCM-SHA256"))
- return( SSL_EDH_RSA_AES_128_GCM_SHA256 );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-GCM-SHA384"))
- return( SSL_RSA_AES_256_GCM_SHA384 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-GCM-SHA384"))
- return( SSL_EDH_RSA_AES_256_GCM_SHA384 );
-#endif
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-128-SHA"))
- return( SSL_RSA_CAMELLIA_128_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-128-SHA"))
- return( SSL_EDH_RSA_CAMELLIA_128_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-256-SHA"))
- return( SSL_RSA_CAMELLIA_256_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-256-SHA"))
- return( SSL_EDH_RSA_CAMELLIA_256_SHA );
-
-#if defined(POLARSSL_SHA2_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-128-SHA256"))
- return( SSL_RSA_CAMELLIA_128_SHA256 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-128-SHA256"))
- return( SSL_EDH_RSA_CAMELLIA_128_SHA256 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-256-SHA256"))
- return( SSL_RSA_CAMELLIA_256_SHA256 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-256-SHA256"))
- return( SSL_EDH_RSA_CAMELLIA_256_SHA256 );
-#endif
-#endif
-
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-MD5"))
- return( SSL_RSA_NULL_MD5 );
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-SHA"))
- return( SSL_RSA_NULL_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-SHA256"))
- return( SSL_RSA_NULL_SHA256 );
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#if defined(POLARSSL_DES_C)
- if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-DES-SHA"))
- return( SSL_RSA_DES_SHA );
- if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-DES-SHA"))
- return( SSL_EDH_RSA_DES_SHA );
-#endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
-
- return( 0 );
-}
-
-const char *ssl_get_ciphersuite( const ssl_context *ssl )
-{
- return ssl_get_ciphersuite_name( ssl->session->ciphersuite );
-}
-
-const char *ssl_get_version( const ssl_context *ssl )
-{
- switch( ssl->minor_ver )
- {
- case SSL_MINOR_VERSION_0:
- return( "SSLv3.0" );
-
- case SSL_MINOR_VERSION_1:
- return( "TLSv1.0" );
-
- case SSL_MINOR_VERSION_2:
- return( "TLSv1.1" );
-
- case SSL_MINOR_VERSION_3:
- return( "TLSv1.2" );
-
- default:
- break;
- }
- return( "unknown" );
-}
-
-int ssl_default_ciphersuites[] =
-{
-#if defined(POLARSSL_DHM_C)
-#if defined(POLARSSL_AES_C)
-#if defined(POLARSSL_SHA2_C)
- SSL_EDH_RSA_AES_256_SHA256,
-#endif /* POLARSSL_SHA2_C */
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
- SSL_EDH_RSA_AES_256_GCM_SHA384,
-#endif
- SSL_EDH_RSA_AES_256_SHA,
-#if defined(POLARSSL_SHA2_C)
- SSL_EDH_RSA_AES_128_SHA256,
-#endif
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
- SSL_EDH_RSA_AES_128_GCM_SHA256,
-#endif
- SSL_EDH_RSA_AES_128_SHA,
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#if defined(POLARSSL_SHA2_C)
- SSL_EDH_RSA_CAMELLIA_256_SHA256,
-#endif /* POLARSSL_SHA2_C */
- SSL_EDH_RSA_CAMELLIA_256_SHA,
-#if defined(POLARSSL_SHA2_C)
- SSL_EDH_RSA_CAMELLIA_128_SHA256,
-#endif /* POLARSSL_SHA2_C */
- SSL_EDH_RSA_CAMELLIA_128_SHA,
-#endif
-#if defined(POLARSSL_DES_C)
- SSL_EDH_RSA_DES_168_SHA,
-#endif
-#endif
-
-#if defined(POLARSSL_AES_C)
-#if defined(POLARSSL_SHA2_C)
- SSL_RSA_AES_256_SHA256,
-#endif /* POLARSSL_SHA2_C */
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
- SSL_RSA_AES_256_GCM_SHA384,
-#endif /* POLARSSL_SHA2_C */
- SSL_RSA_AES_256_SHA,
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#if defined(POLARSSL_SHA2_C)
- SSL_RSA_CAMELLIA_256_SHA256,
-#endif /* POLARSSL_SHA2_C */
- SSL_RSA_CAMELLIA_256_SHA,
-#endif
-#if defined(POLARSSL_AES_C)
-#if defined(POLARSSL_SHA2_C)
- SSL_RSA_AES_128_SHA256,
-#endif /* POLARSSL_SHA2_C */
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
- SSL_RSA_AES_128_GCM_SHA256,
-#endif /* POLARSSL_SHA2_C */
- SSL_RSA_AES_128_SHA,
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#if defined(POLARSSL_SHA2_C)
- SSL_RSA_CAMELLIA_128_SHA256,
-#endif /* POLARSSL_SHA2_C */
- SSL_RSA_CAMELLIA_128_SHA,
-#endif
-#if defined(POLARSSL_DES_C)
- SSL_RSA_DES_168_SHA,
-#endif
-#if defined(POLARSSL_ARC4_C)
- SSL_RSA_RC4_128_SHA,
- SSL_RSA_RC4_128_MD5,
-#endif
- 0
-};
-
-/*
- * Perform the SSL handshake
- */
-int ssl_handshake( ssl_context *ssl )
-{
- int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
-
- SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
-
-#if defined(POLARSSL_SSL_CLI_C)
- if( ssl->endpoint == SSL_IS_CLIENT )
- ret = ssl_handshake_client( ssl );
-#endif
-
-#if defined(POLARSSL_SSL_SRV_C)
- if( ssl->endpoint == SSL_IS_SERVER )
- ret = ssl_handshake_server( ssl );
-#endif
-
- SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
-
- return( ret );
-}
-
-/*
- * Receive application data decrypted from the SSL layer
- */
-int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
-{
- int ret;
- size_t n;
-
- SSL_DEBUG_MSG( 2, ( "=> read" ) );
-
- if( ssl->state != SSL_HANDSHAKE_OVER )
- {
- if( ( ret = ssl_handshake( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_handshake", ret );
- return( ret );
- }
- }
-
- if( ssl->in_offt == NULL )
- {
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_SSL_CONN_EOF )
- return( 0 );
-
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msglen == 0 &&
- ssl->in_msgtype == SSL_MSG_APPLICATION_DATA )
- {
- /*
- * OpenSSL sends empty messages to randomize the IV
- */
- if( ( ret = ssl_read_record( ssl ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_SSL_CONN_EOF )
- return( 0 );
-
- SSL_DEBUG_RET( 1, "ssl_read_record", ret );
- return( ret );
- }
- }
-
- if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
- {
- SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
- return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- ssl->in_offt = ssl->in_msg;
- }
-
- n = ( len < ssl->in_msglen )
- ? len : ssl->in_msglen;
-
- memcpy( buf, ssl->in_offt, n );
- ssl->in_msglen -= n;
-
- if( ssl->in_msglen == 0 )
- /* all bytes consumed */
- ssl->in_offt = NULL;
- else
- /* more data available */
- ssl->in_offt += n;
-
- SSL_DEBUG_MSG( 2, ( "<= read" ) );
-
- return( (int) n );
-}
-
-/*
- * Send application data to be encrypted by the SSL layer
- */
-int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
-{
- int ret;
- size_t n;
-
- SSL_DEBUG_MSG( 2, ( "=> write" ) );
-
- if( ssl->state != SSL_HANDSHAKE_OVER )
- {
- if( ( ret = ssl_handshake( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_handshake", ret );
- return( ret );
- }
- }
-
- n = ( len < SSL_MAX_CONTENT_LEN )
- ? len : SSL_MAX_CONTENT_LEN;
-
- if( ssl->out_left != 0 )
- {
- if( ( ret = ssl_flush_output( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
- return( ret );
- }
- }
- else
- {
- ssl->out_msglen = n;
- ssl->out_msgtype = SSL_MSG_APPLICATION_DATA;
- memcpy( ssl->out_msg, buf, n );
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write" ) );
-
- return( (int) n );
-}
-
-/*
- * Notify the peer that the connection is being closed
- */
-int ssl_close_notify( ssl_context *ssl )
-{
- int ret;
-
- SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
-
- if( ( ret = ssl_flush_output( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
- return( ret );
- }
-
- if( ssl->state == SSL_HANDSHAKE_OVER )
- {
- ssl->out_msgtype = SSL_MSG_ALERT;
- ssl->out_msglen = 2;
- ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING;
- ssl->out_msg[1] = SSL_ALERT_MSG_CLOSE_NOTIFY;
-
- if( ( ret = ssl_write_record( ssl ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
- }
-
- SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
-
- return( ret );
-}
-
-/*
- * Free an SSL context
- */
-void ssl_free( ssl_context *ssl )
-{
- SSL_DEBUG_MSG( 2, ( "=> free" ) );
-
- if( ssl->peer_cert != NULL )
- {
- x509_free( ssl->peer_cert );
- memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
- free( ssl->peer_cert );
- }
-
- if( ssl->out_ctr != NULL )
- {
- memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
- free( ssl->out_ctr );
- }
-
- if( ssl->in_ctr != NULL )
- {
- memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
- free( ssl->in_ctr );
- }
-
-#if defined(POLARSSL_DHM_C)
- dhm_free( &ssl->dhm_ctx );
-#endif
-
- if ( ssl->hostname != NULL)
- {
- memset( ssl->hostname, 0, ssl->hostname_len );
- free( ssl->hostname );
- ssl->hostname_len = 0;
- }
-
- SSL_DEBUG_MSG( 2, ( "<= free" ) );
-
- /* Actually free after last debug message */
- memset( ssl, 0, sizeof( ssl_context ) );
-}
-
-#endif
diff --git a/polarssl/src/library/timing.c b/polarssl/src/library/timing.c
deleted file mode 100644
index 523dbe1..0000000
--- a/polarssl/src/library/timing.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Portable interface to the CPU cycle counter
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_TIMING_C)
-
-#include "polarssl/timing.h"
-
-#if defined(_WIN32)
-
-#include <windows.h>
-#include <winbase.h>
-
-struct _hr_time
-{
- LARGE_INTEGER start;
-};
-
-#else
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <time.h>
-
-struct _hr_time
-{
- struct timeval start;
-};
-
-#endif
-
-#if defined(POLARSSL_HAVE_ASM) && \
- (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
-
-unsigned long hardclock( void )
-{
- unsigned long tsc;
- __asm rdtsc
- __asm mov [tsc], eax
- return( tsc );
-}
-
-#else
-#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
-
-unsigned long hardclock( void )
-{
- unsigned long lo, hi;
- asm( "rdtsc" : "=a" (lo), "=d" (hi) );
- return( lo );
-}
-
-#else
-#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \
- (defined(__amd64__) || defined(__x86_64__))
-
-unsigned long hardclock( void )
-{
- unsigned long lo, hi;
- asm( "rdtsc" : "=a" (lo), "=d" (hi) );
- return( lo | (hi << 32) );
-}
-
-#else
-#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \
- (defined(__powerpc__) || defined(__ppc__))
-
-unsigned long hardclock( void )
-{
- unsigned long tbl, tbu0, tbu1;
-
- do
- {
- asm( "mftbu %0" : "=r" (tbu0) );
- asm( "mftb %0" : "=r" (tbl ) );
- asm( "mftbu %0" : "=r" (tbu1) );
- }
- while( tbu0 != tbu1 );
-
- return( tbl );
-}
-
-#else
-#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__sparc__)
-
-unsigned long hardclock( void )
-{
- unsigned long tick;
- asm( ".byte 0x83, 0x41, 0x00, 0x00" );
- asm( "mov %%g1, %0" : "=r" (tick) );
- return( tick );
-}
-
-#else
-#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__alpha__)
-
-unsigned long hardclock( void )
-{
- unsigned long cc;
- asm( "rpcc %0" : "=r" (cc) );
- return( cc & 0xFFFFFFFF );
-}
-
-#else
-#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__ia64__)
-
-unsigned long hardclock( void )
-{
- unsigned long itc;
- asm( "mov %0 = ar.itc" : "=r" (itc) );
- return( itc );
-}
-
-#else
-#if defined(_MSC_VER)
-
-unsigned long hardclock( void )
-{
- LARGE_INTEGER offset;
-
- QueryPerformanceCounter( &offset );
-
- return (unsigned long)( offset.QuadPart );
-}
-
-#else
-
-static int hardclock_init = 0;
-static struct timeval tv_init;
-
-unsigned long hardclock( void )
-{
- struct timeval tv_cur;
-
- if( hardclock_init == 0 )
- {
- gettimeofday( &tv_init, NULL );
- hardclock_init = 1;
- }
-
- gettimeofday( &tv_cur, NULL );
- return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
- + ( tv_cur.tv_usec - tv_init.tv_usec ) );
-}
-
-#endif /* generic */
-#endif /* WIN32 */
-#endif /* IA-64 */
-#endif /* Alpha */
-#endif /* SPARC8 */
-#endif /* PowerPC */
-#endif /* AMD64 */
-#endif /* i586+ */
-
-volatile int alarmed = 0;
-
-#if defined(_WIN32)
-
-unsigned long get_timer( struct hr_time *val, int reset )
-{
- unsigned long delta;
- LARGE_INTEGER offset, hfreq;
- struct _hr_time *t = (struct _hr_time *) val;
-
- QueryPerformanceCounter( &offset );
- QueryPerformanceFrequency( &hfreq );
-
- delta = (unsigned long)( ( 1000 *
- ( offset.QuadPart - t->start.QuadPart ) ) /
- hfreq.QuadPart );
-
- if( reset )
- QueryPerformanceCounter( &t->start );
-
- return( delta );
-}
-
-DWORD WINAPI TimerProc( LPVOID uElapse )
-{
- Sleep( (DWORD) uElapse );
- alarmed = 1;
- return( TRUE );
-}
-
-void set_alarm( int seconds )
-{
- DWORD ThreadId;
-
- alarmed = 0;
- CloseHandle( CreateThread( NULL, 0, TimerProc,
- (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
-}
-
-void m_sleep( int milliseconds )
-{
- Sleep( milliseconds );
-}
-
-#else
-
-unsigned long get_timer( struct hr_time *val, int reset )
-{
- unsigned long delta;
- struct timeval offset;
- struct _hr_time *t = (struct _hr_time *) val;
-
- gettimeofday( &offset, NULL );
-
- delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
- + ( offset.tv_usec - t->start.tv_usec ) / 1000;
-
- if( reset )
- {
- t->start.tv_sec = offset.tv_sec;
- t->start.tv_usec = offset.tv_usec;
- }
-
- return( delta );
-}
-
-static void sighandler( int signum )
-{
- alarmed = 1;
- signal( signum, sighandler );
-}
-
-void set_alarm( int seconds )
-{
- alarmed = 0;
- signal( SIGALRM, sighandler );
- alarm( seconds );
-}
-
-void m_sleep( int milliseconds )
-{
- struct timeval tv;
-
- tv.tv_sec = milliseconds / 1000;
- tv.tv_usec = milliseconds * 1000;
-
- select( 0, NULL, NULL, NULL, &tv );
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/version.c b/polarssl/src/library/version.c
deleted file mode 100644
index c1080b7..0000000
--- a/polarssl/src/library/version.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Version information
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_VERSION_C)
-
-#include "polarssl/version.h"
-#include <string.h>
-
-const char version[] = POLARSSL_VERSION_STRING;
-
-unsigned int version_get_number()
-{
- return POLARSSL_VERSION_NUMBER;
-}
-
-void version_get_string( char *string )
-{
- memcpy( string, POLARSSL_VERSION_STRING, sizeof( POLARSSL_VERSION_STRING ) );
-}
-
-void version_get_string_full( char *string )
-{
- memcpy( string, POLARSSL_VERSION_STRING_FULL, sizeof( POLARSSL_VERSION_STRING_FULL ) );
-}
-
-#endif /* POLARSSL_VERSION_C */
diff --git a/polarssl/src/library/x509parse.c b/polarssl/src/library/x509parse.c
deleted file mode 100644
index 9d01a65..0000000
--- a/polarssl/src/library/x509parse.c
+++ /dev/null
@@ -1,3425 +0,0 @@
-/*
- * X.509 certificate and private key decoding
- *
- * Copyright (C) 2006-2011, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * The ITU-T X.509 standard defines a certificate format for PKI.
- *
- * http://www.ietf.org/rfc/rfc3279.txt
- * http://www.ietf.org/rfc/rfc3280.txt
- *
- * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
- *
- * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
- * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_X509_PARSE_C)
-
-#include "polarssl/x509.h"
-#include "polarssl/asn1.h"
-#include "polarssl/pem.h"
-#include "polarssl/des.h"
-#include "polarssl/md2.h"
-#include "polarssl/md4.h"
-#include "polarssl/md5.h"
-#include "polarssl/sha1.h"
-#include "polarssl/sha2.h"
-#include "polarssl/sha4.h"
-#include "polarssl/dhm.h"
-
-#include <string.h>
-#include <stdlib.h>
-#if defined(_WIN32)
-#include <windows.h>
-#else
-#include <time.h>
-#endif
-
-#if defined(POLARSSL_FS_IO)
-#include <stdio.h>
-#endif
-
-/*
- * Version ::= INTEGER { v1(0), v2(1), v3(2) }
- */
-static int x509_get_version( unsigned char **p,
- const unsigned char *end,
- int *ver )
-{
- int ret;
- size_t len;
-
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- {
- *ver = 0;
- return( 0 );
- }
-
- return( ret );
- }
-
- end = *p + len;
-
- if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_VERSION +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-/*
- * Version ::= INTEGER { v1(0), v2(1) }
- */
-static int x509_crl_get_version( unsigned char **p,
- const unsigned char *end,
- int *ver )
-{
- int ret;
-
- if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- {
- *ver = 0;
- return( 0 );
- }
-
- return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
- }
-
- return( 0 );
-}
-
-/*
- * CertificateSerialNumber ::= INTEGER
- */
-static int x509_get_serial( unsigned char **p,
- const unsigned char *end,
- x509_buf *serial )
-{
- int ret;
-
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
- **p != ASN1_INTEGER )
- return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
- POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
- serial->tag = *(*p)++;
-
- if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + ret );
-
- serial->p = *p;
- *p += serial->len;
-
- return( 0 );
-}
-
-/*
- * AlgorithmIdentifier ::= SEQUENCE {
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL }
- */
-static int x509_get_alg( unsigned char **p,
- const unsigned char *end,
- x509_buf *alg )
-{
- int ret;
- size_t len;
-
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
-
- end = *p + len;
- alg->tag = **p;
-
- if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
-
- alg->p = *p;
- *p += alg->len;
-
- if( *p == end )
- return( 0 );
-
- /*
- * assume the algorithm parameters must be NULL
- */
- if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_ALG +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-/*
- * AttributeTypeAndValue ::= SEQUENCE {
- * type AttributeType,
- * value AttributeValue }
- *
- * AttributeType ::= OBJECT IDENTIFIER
- *
- * AttributeValue ::= ANY DEFINED BY AttributeType
- */
-static int x509_get_attr_type_value( unsigned char **p,
- const unsigned char *end,
- x509_name *cur )
-{
- int ret;
- size_t len;
- x509_buf *oid;
- x509_buf *val;
-
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
- oid = &cur->oid;
- oid->tag = **p;
-
- if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
- oid->p = *p;
- *p += oid->len;
-
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
- **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
- **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
- return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
- POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
- val = &cur->val;
- val->tag = *(*p)++;
-
- if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
- val->p = *p;
- *p += val->len;
-
- cur->next = NULL;
-
- return( 0 );
-}
-
-/*
- * RelativeDistinguishedName ::=
- * SET OF AttributeTypeAndValue
- *
- * AttributeTypeAndValue ::= SEQUENCE {
- * type AttributeType,
- * value AttributeValue }
- *
- * AttributeType ::= OBJECT IDENTIFIER
- *
- * AttributeValue ::= ANY DEFINED BY AttributeType
- */
-static int x509_get_name( unsigned char **p,
- const unsigned char *end,
- x509_name *cur )
-{
- int ret;
- size_t len;
- const unsigned char *end2;
- x509_name *use;
-
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
-
- end2 = end;
- end = *p + len;
- use = cur;
-
- do
- {
- if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
- return( ret );
-
- if( *p != end )
- {
- use->next = (x509_name *) malloc(
- sizeof( x509_name ) );
-
- if( use->next == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- memset( use->next, 0, sizeof( x509_name ) );
-
- use = use->next;
- }
- }
- while( *p != end );
-
- /*
- * recurse until end of SEQUENCE is reached
- */
- if( *p == end2 )
- return( 0 );
-
- cur->next = (x509_name *) malloc(
- sizeof( x509_name ) );
-
- if( cur->next == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- return( x509_get_name( p, end2, cur->next ) );
-}
-
-/*
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- */
-static int x509_get_time( unsigned char **p,
- const unsigned char *end,
- x509_time *time )
-{
- int ret;
- size_t len;
- char date[64];
- unsigned char tag;
-
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- tag = **p;
-
- if ( tag == ASN1_UTC_TIME )
- {
- (*p)++;
- ret = asn1_get_len( p, end, &len );
-
- if( ret != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
-
- memset( date, 0, sizeof( date ) );
- memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
- len : sizeof( date ) - 1 );
-
- if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
- &time->year, &time->mon, &time->day,
- &time->hour, &time->min, &time->sec ) < 5 )
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
-
- time->year += 100 * ( time->year < 50 );
- time->year += 1900;
-
- *p += len;
-
- return( 0 );
- }
- else if ( tag == ASN1_GENERALIZED_TIME )
- {
- (*p)++;
- ret = asn1_get_len( p, end, &len );
-
- if( ret != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
-
- memset( date, 0, sizeof( date ) );
- memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
- len : sizeof( date ) - 1 );
-
- if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
- &time->year, &time->mon, &time->day,
- &time->hour, &time->min, &time->sec ) < 5 )
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
-
- *p += len;
-
- return( 0 );
- }
- else
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-}
-
-
-/*
- * Validity ::= SEQUENCE {
- * notBefore Time,
- * notAfter Time }
- */
-static int x509_get_dates( unsigned char **p,
- const unsigned char *end,
- x509_time *from,
- x509_time *to )
-{
- int ret;
- size_t len;
-
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
-
- end = *p + len;
-
- if( ( ret = x509_get_time( p, end, from ) ) != 0 )
- return( ret );
-
- if( ( ret = x509_get_time( p, end, to ) ) != 0 )
- return( ret );
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-/*
- * SubjectPublicKeyInfo ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * subjectPublicKey BIT STRING }
- */
-static int x509_get_pubkey( unsigned char **p,
- const unsigned char *end,
- x509_buf *pk_alg_oid,
- mpi *N, mpi *E )
-{
- int ret, can_handle;
- size_t len;
- unsigned char *end2;
-
- if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
- return( ret );
-
- /*
- * only RSA public keys handled at this time
- */
- can_handle = 0;
-
- if( pk_alg_oid->len == 9 &&
- memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) == 0 )
- can_handle = 1;
-
- if( pk_alg_oid->len == 9 &&
- memcmp( pk_alg_oid->p, OID_PKCS1, 8 ) == 0 )
- {
- if( pk_alg_oid->p[8] >= 2 && pk_alg_oid->p[8] <= 5 )
- can_handle = 1;
-
- if ( pk_alg_oid->p[8] >= 11 && pk_alg_oid->p[8] <= 14 )
- can_handle = 1;
- }
-
- if( pk_alg_oid->len == 5 &&
- memcmp( pk_alg_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
- can_handle = 1;
-
- if( can_handle == 0 )
- return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
- if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- end2 = *p + len;
-
- if( *(*p)++ != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
-
- /*
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER -- e
- * }
- */
- if( ( ret = asn1_get_tag( p, end2, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
- if( *p + len != end2 )
- return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
- ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-static int x509_get_sig( unsigned char **p,
- const unsigned char *end,
- x509_buf *sig )
-{
- int ret;
- size_t len;
-
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- sig->tag = **p;
-
- if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + ret );
-
-
- if( --len < 1 || *(*p)++ != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
-
- sig->len = len;
- sig->p = *p;
-
- *p += len;
-
- return( 0 );
-}
-
-/*
- * X.509 v2/v3 unique identifier (not parsed)
- */
-static int x509_get_uid( unsigned char **p,
- const unsigned char *end,
- x509_buf *uid, int n )
-{
- int ret;
-
- if( *p == end )
- return( 0 );
-
- uid->tag = **p;
-
- if( ( ret = asn1_get_tag( p, end, &uid->len,
- ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- return( 0 );
-
- return( ret );
- }
-
- uid->p = *p;
- *p += uid->len;
-
- return( 0 );
-}
-
-/*
- * X.509 Extensions (No parsing of extensions, pointer should
- * be either manually updated or extensions should be parsed!
- */
-static int x509_get_ext( unsigned char **p,
- const unsigned char *end,
- x509_buf *ext, int tag )
-{
- int ret;
- size_t len;
-
- if( *p == end )
- return( 0 );
-
- ext->tag = **p;
-
- if( ( ret = asn1_get_tag( p, end, &ext->len,
- ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
- return( ret );
-
- ext->p = *p;
- end = *p + ext->len;
-
- /*
- * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
- *
- * Extension ::= SEQUENCE {
- * extnID OBJECT IDENTIFIER,
- * critical BOOLEAN DEFAULT FALSE,
- * extnValue OCTET STRING }
- */
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( end != *p + len )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-/*
- * X.509 CRL v2 extensions (no extensions parsed yet.)
- */
-static int x509_get_crl_ext( unsigned char **p,
- const unsigned char *end,
- x509_buf *ext )
-{
- int ret;
- size_t len = 0;
-
- /* Get explicit tag */
- if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- return( 0 );
-
- return( ret );
- }
-
- while( *p < end )
- {
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- *p += len;
- }
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-/*
- * X.509 CRL v2 entry extensions (no extensions parsed yet.)
- */
-static int x509_get_crl_entry_ext( unsigned char **p,
- const unsigned char *end,
- x509_buf *ext )
-{
- int ret;
- size_t len = 0;
-
- /* OPTIONAL */
- if (end <= *p)
- return( 0 );
-
- ext->tag = **p;
- ext->p = *p;
-
- /*
- * Get CRL-entry extension sequence header
- * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2
- */
- if( ( ret = asn1_get_tag( p, end, &ext->len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- {
- ext->p = NULL;
- return( 0 );
- }
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
- }
-
- end = *p + ext->len;
-
- if( end != *p + ext->len )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- while( *p < end )
- {
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- *p += len;
- }
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-static int x509_get_basic_constraints( unsigned char **p,
- const unsigned char *end,
- int *ca_istrue,
- int *max_pathlen )
-{
- int ret;
- size_t len;
-
- /*
- * BasicConstraints ::= SEQUENCE {
- * cA BOOLEAN DEFAULT FALSE,
- * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
- */
- *ca_istrue = 0; /* DEFAULT FALSE */
- *max_pathlen = 0; /* endless */
-
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( *p == end )
- return 0;
-
- if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- ret = asn1_get_int( p, end, ca_istrue );
-
- if( ret != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( *ca_istrue != 0 )
- *ca_istrue = 1;
- }
-
- if( *p == end )
- return 0;
-
- if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- (*max_pathlen)++;
-
- return 0;
-}
-
-static int x509_get_ns_cert_type( unsigned char **p,
- const unsigned char *end,
- unsigned char *ns_cert_type)
-{
- int ret;
- x509_bitstring bs = { 0, 0, NULL };
-
- if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( bs.len != 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
- /* Get actual bitstring */
- *ns_cert_type = *bs.p;
- return 0;
-}
-
-static int x509_get_key_usage( unsigned char **p,
- const unsigned char *end,
- unsigned char *key_usage)
-{
- int ret;
- x509_bitstring bs = { 0, 0, NULL };
-
- if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( bs.len > 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
- /* Get actual bitstring */
- *key_usage = *bs.p;
- return 0;
-}
-
-/*
- * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
- *
- * KeyPurposeId ::= OBJECT IDENTIFIER
- */
-static int x509_get_ext_key_usage( unsigned char **p,
- const unsigned char *end,
- x509_sequence *ext_key_usage)
-{
- int ret;
-
- if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- /* Sequence length must be >= 1 */
- if( ext_key_usage->buf.p == NULL )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
- return 0;
-}
-
-/*
- * SubjectAltName ::= GeneralNames
- *
- * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- *
- * GeneralName ::= CHOICE {
- * otherName [0] OtherName,
- * rfc822Name [1] IA5String,
- * dNSName [2] IA5String,
- * x400Address [3] ORAddress,
- * directoryName [4] Name,
- * ediPartyName [5] EDIPartyName,
- * uniformResourceIdentifier [6] IA5String,
- * iPAddress [7] OCTET STRING,
- * registeredID [8] OBJECT IDENTIFIER }
- *
- * OtherName ::= SEQUENCE {
- * type-id OBJECT IDENTIFIER,
- * value [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * EDIPartyName ::= SEQUENCE {
- * nameAssigner [0] DirectoryString OPTIONAL,
- * partyName [1] DirectoryString }
- *
- * NOTE: PolarSSL only parses and uses dNSName at this point.
- */
-static int x509_get_subject_alt_name( unsigned char **p,
- const unsigned char *end,
- x509_sequence *subject_alt_name )
-{
- int ret;
- size_t len, tag_len;
- asn1_buf *buf;
- unsigned char tag;
- asn1_sequence *cur = subject_alt_name;
-
- /* Get main sequence tag */
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( *p + len != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- while( *p < end )
- {
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- tag = **p;
- (*p)++;
- if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
- if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
- {
- *p += tag_len;
- continue;
- }
-
- buf = &(cur->buf);
- buf->tag = tag;
- buf->p = *p;
- buf->len = tag_len;
- *p += buf->len;
-
- /* Allocate and assign next pointer */
- if (*p < end)
- {
- cur->next = (asn1_sequence *) malloc(
- sizeof( asn1_sequence ) );
-
- if( cur->next == NULL )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_MALLOC_FAILED );
-
- cur = cur->next;
- }
- }
-
- /* Set final sequence entry's next pointer to NULL */
- cur->next = NULL;
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-/*
- * X.509 v3 extensions
- *
- * TODO: Perform all of the basic constraints tests required by the RFC
- * TODO: Set values for undetected extensions to a sane default?
- *
- */
-static int x509_get_crt_ext( unsigned char **p,
- const unsigned char *end,
- x509_cert *crt )
-{
- int ret;
- size_t len;
- unsigned char *end_ext_data, *end_ext_octet;
-
- if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- return( 0 );
-
- return( ret );
- }
-
- while( *p < end )
- {
- /*
- * Extension ::= SEQUENCE {
- * extnID OBJECT IDENTIFIER,
- * critical BOOLEAN DEFAULT FALSE,
- * extnValue OCTET STRING }
- */
- x509_buf extn_oid = {0, 0, NULL};
- int is_critical = 0; /* DEFAULT FALSE */
-
- if( ( ret = asn1_get_tag( p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- end_ext_data = *p + len;
-
- /* Get extension ID */
- extn_oid.tag = **p;
-
- if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- extn_oid.p = *p;
- *p += extn_oid.len;
-
- if( ( end - *p ) < 1 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
- /* Get optional critical */
- if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
- ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- /* Data should be octet string type */
- if( ( ret = asn1_get_tag( p, end_ext_data, &len,
- ASN1_OCTET_STRING ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
-
- end_ext_octet = *p + len;
-
- if( end_ext_octet != end_ext_data )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- /*
- * Detect supported extensions
- */
- if( ( OID_SIZE( OID_BASIC_CONSTRAINTS ) == extn_oid.len ) &&
- memcmp( extn_oid.p, OID_BASIC_CONSTRAINTS, extn_oid.len ) == 0 )
- {
- /* Parse basic constraints */
- if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
- &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
- return ( ret );
- crt->ext_types |= EXT_BASIC_CONSTRAINTS;
- }
- else if( ( OID_SIZE( OID_NS_CERT_TYPE ) == extn_oid.len ) &&
- memcmp( extn_oid.p, OID_NS_CERT_TYPE, extn_oid.len ) == 0 )
- {
- /* Parse netscape certificate type */
- if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
- &crt->ns_cert_type ) ) != 0 )
- return ( ret );
- crt->ext_types |= EXT_NS_CERT_TYPE;
- }
- else if( ( OID_SIZE( OID_KEY_USAGE ) == extn_oid.len ) &&
- memcmp( extn_oid.p, OID_KEY_USAGE, extn_oid.len ) == 0 )
- {
- /* Parse key usage */
- if( ( ret = x509_get_key_usage( p, end_ext_octet,
- &crt->key_usage ) ) != 0 )
- return ( ret );
- crt->ext_types |= EXT_KEY_USAGE;
- }
- else if( ( OID_SIZE( OID_EXTENDED_KEY_USAGE ) == extn_oid.len ) &&
- memcmp( extn_oid.p, OID_EXTENDED_KEY_USAGE, extn_oid.len ) == 0 )
- {
- /* Parse extended key usage */
- if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
- &crt->ext_key_usage ) ) != 0 )
- return ( ret );
- crt->ext_types |= EXT_EXTENDED_KEY_USAGE;
- }
- else if( ( OID_SIZE( OID_SUBJECT_ALT_NAME ) == extn_oid.len ) &&
- memcmp( extn_oid.p, OID_SUBJECT_ALT_NAME, extn_oid.len ) == 0 )
- {
- /* Parse extended key usage */
- if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
- &crt->subject_alt_names ) ) != 0 )
- return ( ret );
- crt->ext_types |= EXT_SUBJECT_ALT_NAME;
- }
- else
- {
- /* No parser found, skip extension */
- *p = end_ext_octet;
-
-#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
- if( is_critical )
- {
- /* Data is marked as critical: fail */
- return ( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
- }
-#endif
- }
- }
-
- if( *p != end )
- return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
-}
-
-/*
- * X.509 CRL Entries
- */
-static int x509_get_entries( unsigned char **p,
- const unsigned char *end,
- x509_crl_entry *entry )
-{
- int ret;
- size_t entry_len;
- x509_crl_entry *cur_entry = entry;
-
- if( *p == end )
- return( 0 );
-
- if( ( ret = asn1_get_tag( p, end, &entry_len,
- ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
- {
- if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- return( 0 );
-
- return( ret );
- }
-
- end = *p + entry_len;
-
- while( *p < end )
- {
- size_t len2;
- const unsigned char *end2;
-
- if( ( ret = asn1_get_tag( p, end, &len2,
- ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
- {
- return( ret );
- }
-
- cur_entry->raw.tag = **p;
- cur_entry->raw.p = *p;
- cur_entry->raw.len = len2;
- end2 = *p + len2;
-
- if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
- return( ret );
-
- if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 )
- return( ret );
-
- if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 )
- return( ret );
-
- if ( *p < end )
- {
- cur_entry->next = malloc( sizeof( x509_crl_entry ) );
-
- if( cur_entry->next == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- cur_entry = cur_entry->next;
- memset( cur_entry, 0, sizeof( x509_crl_entry ) );
- }
- }
-
- return( 0 );
-}
-
-static int x509_get_sig_alg( const x509_buf *sig_oid, int *sig_alg )
-{
- if( sig_oid->len == 9 &&
- memcmp( sig_oid->p, OID_PKCS1, 8 ) == 0 )
- {
- if( sig_oid->p[8] >= 2 && sig_oid->p[8] <= 5 )
- {
- *sig_alg = sig_oid->p[8];
- return( 0 );
- }
-
- if ( sig_oid->p[8] >= 11 && sig_oid->p[8] <= 14 )
- {
- *sig_alg = sig_oid->p[8];
- return( 0 );
- }
-
- return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
- }
- if( sig_oid->len == 5 &&
- memcmp( sig_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
- {
- *sig_alg = SIG_RSA_SHA1;
- return( 0 );
- }
-
- return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
-}
-
-/*
- * Parse and fill a single X.509 certificate in DER format
- */
-int x509parse_crt_der( x509_cert *crt, const unsigned char *buf, size_t buflen )
-{
- int ret;
- size_t len;
- unsigned char *p, *end;
-
- /*
- * Check for valid input
- */
- if( crt == NULL || buf == NULL )
- return( POLARSSL_ERR_X509_INVALID_INPUT );
-
- p = (unsigned char *) malloc( len = buflen );
-
- if( p == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- memcpy( p, buf, buflen );
-
- buflen = 0;
-
- crt->raw.p = p;
- crt->raw.len = len;
- end = p + len;
-
- /*
- * Certificate ::= SEQUENCE {
- * tbsCertificate TBSCertificate,
- * signatureAlgorithm AlgorithmIdentifier,
- * signatureValue BIT STRING }
- */
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
- }
-
- if( len != (size_t) ( end - p ) )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- /*
- * TBSCertificate ::= SEQUENCE {
- */
- crt->tbs.p = p;
-
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
- }
-
- end = p + len;
- crt->tbs.len = end - crt->tbs.p;
-
- /*
- * Version ::= INTEGER { v1(0), v2(1), v3(2) }
- *
- * CertificateSerialNumber ::= INTEGER
- *
- * signature AlgorithmIdentifier
- */
- if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
- ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
- ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- crt->version++;
-
- if( crt->version > 3 )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
- }
-
- if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_alg ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- /*
- * issuer Name
- */
- crt->issuer_raw.p = p;
-
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
- }
-
- if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- crt->issuer_raw.len = p - crt->issuer_raw.p;
-
- /*
- * Validity ::= SEQUENCE {
- * notBefore Time,
- * notAfter Time }
- *
- */
- if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
- &crt->valid_to ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- /*
- * subject Name
- */
- crt->subject_raw.p = p;
-
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
- }
-
- if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- crt->subject_raw.len = p - crt->subject_raw.p;
-
- /*
- * SubjectPublicKeyInfo ::= SEQUENCE
- * algorithm AlgorithmIdentifier,
- * subjectPublicKey BIT STRING }
- */
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
- }
-
- if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
- &crt->rsa.N, &crt->rsa.E ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- crt->rsa.len = mpi_size( &crt->rsa.N );
-
- /*
- * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
- * -- If present, version shall be v2 or v3
- * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
- * -- If present, version shall be v2 or v3
- * extensions [3] EXPLICIT Extensions OPTIONAL
- * -- If present, version shall be v3
- */
- if( crt->version == 2 || crt->version == 3 )
- {
- ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
- if( ret != 0 )
- {
- x509_free( crt );
- return( ret );
- }
- }
-
- if( crt->version == 2 || crt->version == 3 )
- {
- ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
- if( ret != 0 )
- {
- x509_free( crt );
- return( ret );
- }
- }
-
- if( crt->version == 3 )
- {
- ret = x509_get_crt_ext( &p, end, crt);
- if( ret != 0 )
- {
- x509_free( crt );
- return( ret );
- }
- }
-
- if( p != end )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- end = crt->raw.p + crt->raw.len;
-
- /*
- * signatureAlgorithm AlgorithmIdentifier,
- * signatureValue BIT STRING
- */
- if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
- }
-
- if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
- {
- x509_free( crt );
- return( ret );
- }
-
- if( p != end )
- {
- x509_free( crt );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- return( 0 );
-}
-
-/*
- * Parse one or more PEM certificates from a buffer and add them to the chained list
- */
-int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen )
-{
- int ret, success = 0, first_error = 0, total_failed = 0;
- x509_cert *crt, *prev = NULL;
- int buf_format = X509_FORMAT_DER;
-
- crt = chain;
-
- /*
- * Check for valid input
- */
- if( crt == NULL || buf == NULL )
- return( POLARSSL_ERR_X509_INVALID_INPUT );
-
- while( crt->version != 0 && crt->next != NULL )
- {
- prev = crt;
- crt = crt->next;
- }
-
- /*
- * Add new certificate on the end of the chain if needed.
- */
- if ( crt->version != 0 && crt->next == NULL)
- {
- crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
-
- if( crt->next == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- prev = crt;
- crt = crt->next;
- memset( crt, 0, sizeof( x509_cert ) );
- }
-
- /*
- * Determine buffer content. Buffer contains either one DER certificate or
- * one or more PEM certificates.
- */
-#if defined(POLARSSL_PEM_C)
- if( strstr( (char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
- buf_format = X509_FORMAT_PEM;
-#endif
-
- if( buf_format == X509_FORMAT_DER )
- return x509parse_crt_der( crt, buf, buflen );
-
-#if defined(POLARSSL_PEM_C)
- if( buf_format == X509_FORMAT_PEM )
- {
- pem_context pem;
-
- while( buflen > 0 )
- {
- size_t use_len;
- pem_init( &pem );
-
- ret = pem_read_buffer( &pem,
- "-----BEGIN CERTIFICATE-----",
- "-----END CERTIFICATE-----",
- buf, NULL, 0, &use_len );
-
- if( ret == 0 )
- {
- /*
- * Was PEM encoded
- */
- buflen -= use_len;
- buf += use_len;
- }
- else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
- {
- pem_free( &pem );
-
- if( first_error == 0 )
- first_error = ret;
-
- continue;
- }
- else
- break;
-
- ret = x509parse_crt_der( crt, pem.buf, pem.buflen );
-
- pem_free( &pem );
-
- if( ret != 0 )
- {
- /*
- * quit parsing on a memory error
- */
- if( ret == POLARSSL_ERR_X509_MALLOC_FAILED )
- {
- if( prev )
- prev->next = NULL;
-
- if( crt != chain )
- free( crt );
-
- return( ret );
- }
-
- if( first_error == 0 )
- first_error = ret;
-
- total_failed++;
-
- memset( crt, 0, sizeof( x509_cert ) );
- continue;
- }
-
- success = 1;
-
- /*
- * Add new certificate to the list
- */
- crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
-
- if( crt->next == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- prev = crt;
- crt = crt->next;
- memset( crt, 0, sizeof( x509_cert ) );
- }
- }
-#endif
-
- if( crt->version == 0 )
- {
- if( prev )
- prev->next = NULL;
-
- if( crt != chain )
- free( crt );
- }
-
- if( success )
- return( total_failed );
- else if( first_error )
- return( first_error );
- else
- return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
-}
-
-/*
- * Parse one or more CRLs and add them to the chained list
- */
-int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen )
-{
- int ret;
- size_t len;
- unsigned char *p, *end;
- x509_crl *crl;
-#if defined(POLARSSL_PEM_C)
- size_t use_len;
- pem_context pem;
-#endif
-
- crl = chain;
-
- /*
- * Check for valid input
- */
- if( crl == NULL || buf == NULL )
- return( POLARSSL_ERR_X509_INVALID_INPUT );
-
- while( crl->version != 0 && crl->next != NULL )
- crl = crl->next;
-
- /*
- * Add new CRL on the end of the chain if needed.
- */
- if ( crl->version != 0 && crl->next == NULL)
- {
- crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
-
- if( crl->next == NULL )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
- }
-
- crl = crl->next;
- memset( crl, 0, sizeof( x509_crl ) );
- }
-
-#if defined(POLARSSL_PEM_C)
- pem_init( &pem );
- ret = pem_read_buffer( &pem,
- "-----BEGIN X509 CRL-----",
- "-----END X509 CRL-----",
- buf, NULL, 0, &use_len );
-
- if( ret == 0 )
- {
- /*
- * Was PEM encoded
- */
- buflen -= use_len;
- buf += use_len;
-
- /*
- * Steal PEM buffer
- */
- p = pem.buf;
- pem.buf = NULL;
- len = pem.buflen;
- pem_free( &pem );
- }
- else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
- {
- pem_free( &pem );
- return( ret );
- }
- else
- {
- /*
- * nope, copy the raw DER data
- */
- p = (unsigned char *) malloc( len = buflen );
-
- if( p == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- memcpy( p, buf, buflen );
-
- buflen = 0;
- }
-#else
- p = (unsigned char *) malloc( len = buflen );
-
- if( p == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- memcpy( p, buf, buflen );
-
- buflen = 0;
-#endif
-
- crl->raw.p = p;
- crl->raw.len = len;
- end = p + len;
-
- /*
- * CertificateList ::= SEQUENCE {
- * tbsCertList TBSCertList,
- * signatureAlgorithm AlgorithmIdentifier,
- * signatureValue BIT STRING }
- */
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
- }
-
- if( len != (size_t) ( end - p ) )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- /*
- * TBSCertList ::= SEQUENCE {
- */
- crl->tbs.p = p;
-
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
- }
-
- end = p + len;
- crl->tbs.len = end - crl->tbs.p;
-
- /*
- * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
- * -- if present, MUST be v2
- *
- * signature AlgorithmIdentifier
- */
- if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
- ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 )
- {
- x509_crl_free( crl );
- return( ret );
- }
-
- crl->version++;
-
- if( crl->version > 2 )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
- }
-
- if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_alg ) ) != 0 )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
- }
-
- /*
- * issuer Name
- */
- crl->issuer_raw.p = p;
-
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
- }
-
- if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
- {
- x509_crl_free( crl );
- return( ret );
- }
-
- crl->issuer_raw.len = p - crl->issuer_raw.p;
-
- /*
- * thisUpdate Time
- * nextUpdate Time OPTIONAL
- */
- if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
- {
- x509_crl_free( crl );
- return( ret );
- }
-
- if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
- {
- if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
- POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
- ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
- POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
- {
- x509_crl_free( crl );
- return( ret );
- }
- }
-
- /*
- * revokedCertificates SEQUENCE OF SEQUENCE {
- * userCertificate CertificateSerialNumber,
- * revocationDate Time,
- * crlEntryExtensions Extensions OPTIONAL
- * -- if present, MUST be v2
- * } OPTIONAL
- */
- if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
- {
- x509_crl_free( crl );
- return( ret );
- }
-
- /*
- * crlExtensions EXPLICIT Extensions OPTIONAL
- * -- if present, MUST be v2
- */
- if( crl->version == 2 )
- {
- ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
-
- if( ret != 0 )
- {
- x509_crl_free( crl );
- return( ret );
- }
- }
-
- if( p != end )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- end = crl->raw.p + crl->raw.len;
-
- /*
- * signatureAlgorithm AlgorithmIdentifier,
- * signatureValue BIT STRING
- */
- if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 )
- {
- x509_crl_free( crl );
- return( ret );
- }
-
- if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
- }
-
- if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
- {
- x509_crl_free( crl );
- return( ret );
- }
-
- if( p != end )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- if( buflen > 0 )
- {
- crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
-
- if( crl->next == NULL )
- {
- x509_crl_free( crl );
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
- }
-
- crl = crl->next;
- memset( crl, 0, sizeof( x509_crl ) );
-
- return( x509parse_crl( crl, buf, buflen ) );
- }
-
- return( 0 );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * Load all data from a file into a given buffer.
- */
-int load_file( const char *path, unsigned char **buf, size_t *n )
-{
- FILE *f;
-
- if( ( f = fopen( path, "rb" ) ) == NULL )
- return( POLARSSL_ERR_X509_FILE_IO_ERROR );
-
- fseek( f, 0, SEEK_END );
- *n = (size_t) ftell( f );
- fseek( f, 0, SEEK_SET );
-
- if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
- return( POLARSSL_ERR_X509_MALLOC_FAILED );
-
- if( fread( *buf, 1, *n, f ) != *n )
- {
- fclose( f );
- free( *buf );
- return( POLARSSL_ERR_X509_FILE_IO_ERROR );
- }
-
- fclose( f );
-
- (*buf)[*n] = '\0';
-
- return( 0 );
-}
-
-/*
- * Load one or more certificates and add them to the chained list
- */
-int x509parse_crtfile( x509_cert *chain, const char *path )
-{
- int ret;
- size_t n;
- unsigned char *buf;
-
- if ( (ret = load_file( path, &buf, &n ) ) != 0 )
- return( ret );
-
- ret = x509parse_crt( chain, buf, n );
-
- memset( buf, 0, n + 1 );
- free( buf );
-
- return( ret );
-}
-
-/*
- * Load one or more CRLs and add them to the chained list
- */
-int x509parse_crlfile( x509_crl *chain, const char *path )
-{
- int ret;
- size_t n;
- unsigned char *buf;
-
- if ( (ret = load_file( path, &buf, &n ) ) != 0 )
- return( ret );
-
- ret = x509parse_crl( chain, buf, n );
-
- memset( buf, 0, n + 1 );
- free( buf );
-
- return( ret );
-}
-
-/*
- * Load and parse a private RSA key
- */
-int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
-{
- int ret;
- size_t n;
- unsigned char *buf;
-
- if ( (ret = load_file( path, &buf, &n ) ) != 0 )
- return( ret );
-
- if( pwd == NULL )
- ret = x509parse_key( rsa, buf, n, NULL, 0 );
- else
- ret = x509parse_key( rsa, buf, n,
- (unsigned char *) pwd, strlen( pwd ) );
-
- memset( buf, 0, n + 1 );
- free( buf );
-
- return( ret );
-}
-
-/*
- * Load and parse a public RSA key
- */
-int x509parse_public_keyfile( rsa_context *rsa, const char *path )
-{
- int ret;
- size_t n;
- unsigned char *buf;
-
- if ( (ret = load_file( path, &buf, &n ) ) != 0 )
- return( ret );
-
- ret = x509parse_public_key( rsa, buf, n );
-
- memset( buf, 0, n + 1 );
- free( buf );
-
- return( ret );
-}
-#endif /* POLARSSL_FS_IO */
-
-/*
- * Parse a private RSA key
- */
-int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
- const unsigned char *pwd, size_t pwdlen )
-{
- int ret;
- size_t len;
- unsigned char *p, *end;
- unsigned char *p_alt;
- x509_buf pk_alg_oid;
-
-#if defined(POLARSSL_PEM_C)
- pem_context pem;
-
- pem_init( &pem );
- ret = pem_read_buffer( &pem,
- "-----BEGIN RSA PRIVATE KEY-----",
- "-----END RSA PRIVATE KEY-----",
- key, pwd, pwdlen, &len );
-
- if( ret == POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
- {
- ret = pem_read_buffer( &pem,
- "-----BEGIN PRIVATE KEY-----",
- "-----END PRIVATE KEY-----",
- key, pwd, pwdlen, &len );
- }
-
- if( ret == 0 )
- {
- /*
- * Was PEM encoded
- */
- keylen = pem.buflen;
- }
- else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
- {
- pem_free( &pem );
- return( ret );
- }
-
- p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
-#else
- ((void) pwd);
- ((void) pwdlen);
- p = (unsigned char *) key;
-#endif
- end = p + keylen;
-
- /*
- * Note: Depending on the type of private key file one can expect either a
- * PrivatKeyInfo object (PKCS#8) or a RSAPrivateKey (PKCS#1) directly.
- *
- * PrivateKeyInfo ::= SEQUENCE {
- * version Version,
- * algorithm AlgorithmIdentifier,
- * PrivateKey BIT STRING
- * }
- *
- * AlgorithmIdentifier ::= SEQUENCE {
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL
- * }
- *
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- */
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- end = p + len;
-
- if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- if( rsa->ver != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
- }
-
- p_alt = p;
-
- if( ( ret = x509_get_alg( &p_alt, end, &pk_alg_oid ) ) != 0 )
- {
- // Assume that we have the PKCS#1 format if wrong
- // tag was encountered
- //
- if( ret != POLARSSL_ERR_X509_CERT_INVALID_ALG +
- POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
- }
- }
- else
- {
- int can_handle;
-
- /*
- * only RSA keys handled at this time
- */
- can_handle = 0;
-
- if( pk_alg_oid.len == 9 &&
- memcmp( pk_alg_oid.p, OID_PKCS1_RSA, 9 ) == 0 )
- can_handle = 1;
-
- if( pk_alg_oid.len == 9 &&
- memcmp( pk_alg_oid.p, OID_PKCS1, 8 ) == 0 )
- {
- if( pk_alg_oid.p[8] >= 2 && pk_alg_oid.p[8] <= 5 )
- can_handle = 1;
-
- if ( pk_alg_oid.p[8] >= 11 && pk_alg_oid.p[8] <= 14 )
- can_handle = 1;
- }
-
- if( pk_alg_oid.len == 5 &&
- memcmp( pk_alg_oid.p, OID_RSA_SHA_OBS, 5 ) == 0 )
- can_handle = 1;
-
- if( can_handle == 0 )
- return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
- /*
- * Parse the PKCS#8 format
- */
-
- p = p_alt;
- if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- if( ( end - p ) < 1 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_OUT_OF_DATA );
- }
-
- end = p + len;
-
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- end = p + len;
-
- if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- if( rsa->ver != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
- }
- }
-
- if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- rsa->len = mpi_size( &rsa->N );
-
- if( p != end )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( ret );
- }
-
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
-
- return( 0 );
-}
-
-/*
- * Parse a public RSA key
- */
-int x509parse_public_key( rsa_context *rsa, const unsigned char *key, size_t keylen )
-{
- int ret;
- size_t len;
- unsigned char *p, *end;
- x509_buf alg_oid;
-#if defined(POLARSSL_PEM_C)
- pem_context pem;
-
- pem_init( &pem );
- ret = pem_read_buffer( &pem,
- "-----BEGIN PUBLIC KEY-----",
- "-----END PUBLIC KEY-----",
- key, NULL, 0, &len );
-
- if( ret == 0 )
- {
- /*
- * Was PEM encoded
- */
- keylen = pem.buflen;
- }
- else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
- {
- pem_free( &pem );
- return( ret );
- }
-
- p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
-#else
- p = (unsigned char *) key;
-#endif
- end = p + keylen;
-
- /*
- * PublicKeyInfo ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * PublicKey BIT STRING
- * }
- *
- * AlgorithmIdentifier ::= SEQUENCE {
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL
- * }
- *
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER -- e
- * }
- */
-
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
- }
-
- if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- rsa_free( rsa );
- return( ret );
- }
-
- rsa->len = mpi_size( &rsa->N );
-
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
-
- return( 0 );
-}
-
-#if defined(POLARSSL_DHM_C)
-/*
- * Parse DHM parameters
- */
-int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
-{
- int ret;
- size_t len;
- unsigned char *p, *end;
-#if defined(POLARSSL_PEM_C)
- pem_context pem;
-
- pem_init( &pem );
-
- ret = pem_read_buffer( &pem,
- "-----BEGIN DH PARAMETERS-----",
- "-----END DH PARAMETERS-----",
- dhmin, NULL, 0, &dhminlen );
-
- if( ret == 0 )
- {
- /*
- * Was PEM encoded
- */
- dhminlen = pem.buflen;
- }
- else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
- {
- pem_free( &pem );
- return( ret );
- }
-
- p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
-#else
- p = (unsigned char *) dhmin;
-#endif
- end = p + dhminlen;
-
- memset( dhm, 0, sizeof( dhm_context ) );
-
- /*
- * DHParams ::= SEQUENCE {
- * prime INTEGER, -- P
- * generator INTEGER, -- g
- * }
- */
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- end = p + len;
-
- if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- dhm_free( dhm );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
- }
-
- if( p != end )
- {
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
- dhm_free( dhm );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
-
- return( 0 );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * Load and parse a private RSA key
- */
-int x509parse_dhmfile( dhm_context *dhm, const char *path )
-{
- int ret;
- size_t n;
- unsigned char *buf;
-
- if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
- return( ret );
-
- ret = x509parse_dhm( dhm, buf, n );
-
- memset( buf, 0, n + 1 );
- free( buf );
-
- return( ret );
-}
-#endif /* POLARSSL_FS_IO */
-#endif /* POLARSSL_DHM_C */
-
-#if defined _MSC_VER && !defined snprintf
-#include <stdarg.h>
-
-#if !defined vsnprintf
-#define vsnprintf _vsnprintf
-#endif // vsnprintf
-
-/*
- * Windows _snprintf and _vsnprintf are not compatible to linux versions.
- * Result value is not size of buffer needed, but -1 if no fit is possible.
- *
- * This fuction tries to 'fix' this by at least suggesting enlarging the
- * size by 20.
- */
-int compat_snprintf(char *str, size_t size, const char *format, ...)
-{
- va_list ap;
- int res = -1;
-
- va_start( ap, format );
-
- res = vsnprintf( str, size, format, ap );
-
- va_end( ap );
-
- // No quick fix possible
- if ( res < 0 )
- return( (int) size + 20 );
-
- return res;
-}
-
-#define snprintf compat_snprintf
-#endif
-
-#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
-
-#define SAFE_SNPRINTF() \
-{ \
- if( ret == -1 ) \
- return( -1 ); \
- \
- if ( (unsigned int) ret > n ) { \
- p[n - 1] = '\0'; \
- return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
- } \
- \
- n -= (unsigned int) ret; \
- p += (unsigned int) ret; \
-}
-
-/*
- * Store the name in printable form into buf; no more
- * than size characters will be written
- */
-int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
-{
- int ret;
- size_t i, n;
- unsigned char c;
- const x509_name *name;
- char s[128], *p;
-
- memset( s, 0, sizeof( s ) );
-
- name = dn;
- p = buf;
- n = size;
-
- while( name != NULL )
- {
- if( name != dn )
- {
- ret = snprintf( p, n, ", " );
- SAFE_SNPRINTF();
- }
-
- if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
- {
- switch( name->oid.p[2] )
- {
- case X520_COMMON_NAME:
- ret = snprintf( p, n, "CN=" ); break;
-
- case X520_COUNTRY:
- ret = snprintf( p, n, "C=" ); break;
-
- case X520_LOCALITY:
- ret = snprintf( p, n, "L=" ); break;
-
- case X520_STATE:
- ret = snprintf( p, n, "ST=" ); break;
-
- case X520_ORGANIZATION:
- ret = snprintf( p, n, "O=" ); break;
-
- case X520_ORG_UNIT:
- ret = snprintf( p, n, "OU=" ); break;
-
- default:
- ret = snprintf( p, n, "0x%02X=",
- name->oid.p[2] );
- break;
- }
- SAFE_SNPRINTF();
- }
- else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
- {
- switch( name->oid.p[8] )
- {
- case PKCS9_EMAIL:
- ret = snprintf( p, n, "emailAddress=" ); break;
-
- default:
- ret = snprintf( p, n, "0x%02X=",
- name->oid.p[8] );
- break;
- }
- SAFE_SNPRINTF();
- }
- else
- {
- ret = snprintf( p, n, "\?\?=" );
- SAFE_SNPRINTF();
- }
-
- for( i = 0; i < name->val.len; i++ )
- {
- if( i >= sizeof( s ) - 1 )
- break;
-
- c = name->val.p[i];
- if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
- s[i] = '?';
- else s[i] = c;
- }
- s[i] = '\0';
- ret = snprintf( p, n, "%s", s );
- SAFE_SNPRINTF();
- name = name->next;
- }
-
- return( (int) ( size - n ) );
-}
-
-/*
- * Store the serial in printable form into buf; no more
- * than size characters will be written
- */
-int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial )
-{
- int ret;
- size_t i, n, nr;
- char *p;
-
- p = buf;
- n = size;
-
- nr = ( serial->len <= 32 )
- ? serial->len : 28;
-
- for( i = 0; i < nr; i++ )
- {
- if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
- continue;
-
- ret = snprintf( p, n, "%02X%s",
- serial->p[i], ( i < nr - 1 ) ? ":" : "" );
- SAFE_SNPRINTF();
- }
-
- if( nr != serial->len )
- {
- ret = snprintf( p, n, "...." );
- SAFE_SNPRINTF();
- }
-
- return( (int) ( size - n ) );
-}
-
-/*
- * Return an informational string about the certificate.
- */
-int x509parse_cert_info( char *buf, size_t size, const char *prefix,
- const x509_cert *crt )
-{
- int ret;
- size_t n;
- char *p;
-
- p = buf;
- n = size;
-
- ret = snprintf( p, n, "%scert. version : %d\n",
- prefix, crt->version );
- SAFE_SNPRINTF();
- ret = snprintf( p, n, "%sserial number : ",
- prefix );
- SAFE_SNPRINTF();
-
- ret = x509parse_serial_gets( p, n, &crt->serial);
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%sissuer name : ", prefix );
- SAFE_SNPRINTF();
- ret = x509parse_dn_gets( p, n, &crt->issuer );
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%ssubject name : ", prefix );
- SAFE_SNPRINTF();
- ret = x509parse_dn_gets( p, n, &crt->subject );
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%sissued on : " \
- "%04d-%02d-%02d %02d:%02d:%02d", prefix,
- crt->valid_from.year, crt->valid_from.mon,
- crt->valid_from.day, crt->valid_from.hour,
- crt->valid_from.min, crt->valid_from.sec );
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%sexpires on : " \
- "%04d-%02d-%02d %02d:%02d:%02d", prefix,
- crt->valid_to.year, crt->valid_to.mon,
- crt->valid_to.day, crt->valid_to.hour,
- crt->valid_to.min, crt->valid_to.sec );
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
- SAFE_SNPRINTF();
-
- switch( crt->sig_alg )
- {
- case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
- case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
- case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
- case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
- case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
- case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
- case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
- case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
- default: ret = snprintf( p, n, "???" ); break;
- }
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix,
- (int) crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
- SAFE_SNPRINTF();
-
- return( (int) ( size - n ) );
-}
-
-/* Compare a given OID string with an OID x509_buf * */
-#define OID_CMP(oid_str, oid_buf) \
- ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \
- memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0)
-
-/*
- * Return an informational string describing the given OID
- */
-const char *x509_oid_get_description( x509_buf *oid )
-{
- if ( oid == NULL )
- return ( NULL );
-
- else if( OID_CMP( OID_SERVER_AUTH, oid ) )
- return( STRING_SERVER_AUTH );
-
- else if( OID_CMP( OID_CLIENT_AUTH, oid ) )
- return( STRING_CLIENT_AUTH );
-
- else if( OID_CMP( OID_CODE_SIGNING, oid ) )
- return( STRING_CODE_SIGNING );
-
- else if( OID_CMP( OID_EMAIL_PROTECTION, oid ) )
- return( STRING_EMAIL_PROTECTION );
-
- else if( OID_CMP( OID_TIME_STAMPING, oid ) )
- return( STRING_TIME_STAMPING );
-
- else if( OID_CMP( OID_OCSP_SIGNING, oid ) )
- return( STRING_OCSP_SIGNING );
-
- return( NULL );
-}
-
-/* Return the x.y.z.... style numeric string for the given OID */
-int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
-{
- int ret;
- size_t i, n;
- unsigned int value;
- char *p;
-
- p = buf;
- n = size;
-
- /* First byte contains first two dots */
- if( oid->len > 0 )
- {
- ret = snprintf( p, n, "%d.%d", oid->p[0]/40, oid->p[0]%40 );
- SAFE_SNPRINTF();
- }
-
- /* TODO: value can overflow in value. */
- value = 0;
- for( i = 1; i < oid->len; i++ )
- {
- value <<= 7;
- value += oid->p[i] & 0x7F;
-
- if( !( oid->p[i] & 0x80 ) )
- {
- /* Last byte */
- ret = snprintf( p, n, ".%d", value );
- SAFE_SNPRINTF();
- value = 0;
- }
- }
-
- return( (int) ( size - n ) );
-}
-
-/*
- * Return an informational string about the CRL.
- */
-int x509parse_crl_info( char *buf, size_t size, const char *prefix,
- const x509_crl *crl )
-{
- int ret;
- size_t n;
- char *p;
- const x509_crl_entry *entry;
-
- p = buf;
- n = size;
-
- ret = snprintf( p, n, "%sCRL version : %d",
- prefix, crl->version );
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%sissuer name : ", prefix );
- SAFE_SNPRINTF();
- ret = x509parse_dn_gets( p, n, &crl->issuer );
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%sthis update : " \
- "%04d-%02d-%02d %02d:%02d:%02d", prefix,
- crl->this_update.year, crl->this_update.mon,
- crl->this_update.day, crl->this_update.hour,
- crl->this_update.min, crl->this_update.sec );
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n%snext update : " \
- "%04d-%02d-%02d %02d:%02d:%02d", prefix,
- crl->next_update.year, crl->next_update.mon,
- crl->next_update.day, crl->next_update.hour,
- crl->next_update.min, crl->next_update.sec );
- SAFE_SNPRINTF();
-
- entry = &crl->entry;
-
- ret = snprintf( p, n, "\n%sRevoked certificates:",
- prefix );
- SAFE_SNPRINTF();
-
- while( entry != NULL && entry->raw.len != 0 )
- {
- ret = snprintf( p, n, "\n%sserial number: ",
- prefix );
- SAFE_SNPRINTF();
-
- ret = x509parse_serial_gets( p, n, &entry->serial);
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, " revocation date: " \
- "%04d-%02d-%02d %02d:%02d:%02d",
- entry->revocation_date.year, entry->revocation_date.mon,
- entry->revocation_date.day, entry->revocation_date.hour,
- entry->revocation_date.min, entry->revocation_date.sec );
- SAFE_SNPRINTF();
-
- entry = entry->next;
- }
-
- ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
- SAFE_SNPRINTF();
-
- switch( crl->sig_alg )
- {
- case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
- case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
- case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
- case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
- case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
- case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
- case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
- case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
- default: ret = snprintf( p, n, "???" ); break;
- }
- SAFE_SNPRINTF();
-
- ret = snprintf( p, n, "\n" );
- SAFE_SNPRINTF();
-
- return( (int) ( size - n ) );
-}
-
-/*
- * Return 0 if the x509_time is still valid, or 1 otherwise.
- */
-int x509parse_time_expired( const x509_time *to )
-{
- int year, mon, day;
- int hour, min, sec;
-
-#if defined(_WIN32)
- SYSTEMTIME st;
-
- GetLocalTime(&st);
-
- year = st.wYear;
- mon = st.wMonth;
- day = st.wDay;
- hour = st.wHour;
- min = st.wMinute;
- sec = st.wSecond;
-#else
- struct tm *lt;
- time_t tt;
-
- tt = time( NULL );
- lt = localtime( &tt );
-
- year = lt->tm_year + 1900;
- mon = lt->tm_mon + 1;
- day = lt->tm_mday;
- hour = lt->tm_hour;
- min = lt->tm_min;
- sec = lt->tm_sec;
-#endif
-
- if( year > to->year )
- return( 1 );
-
- if( year == to->year &&
- mon > to->mon )
- return( 1 );
-
- if( year == to->year &&
- mon == to->mon &&
- day > to->day )
- return( 1 );
-
- if( year == to->year &&
- mon == to->mon &&
- day == to->day &&
- hour > to->hour )
- return( 1 );
-
- if( year == to->year &&
- mon == to->mon &&
- day == to->day &&
- hour == to->hour &&
- min > to->min )
- return( 1 );
-
- if( year == to->year &&
- mon == to->mon &&
- day == to->day &&
- hour == to->hour &&
- min == to->min &&
- sec > to->sec )
- return( 1 );
-
- return( 0 );
-}
-
-/*
- * Return 1 if the certificate is revoked, or 0 otherwise.
- */
-int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
-{
- const x509_crl_entry *cur = &crl->entry;
-
- while( cur != NULL && cur->serial.len != 0 )
- {
- if( crt->serial.len == cur->serial.len &&
- memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
- {
- if( x509parse_time_expired( &cur->revocation_date ) )
- return( 1 );
- }
-
- cur = cur->next;
- }
-
- return( 0 );
-}
-
-/*
- * Wrapper for x509 hashes.
- *
- * \param out Buffer to receive the hash (Should be at least 64 bytes)
- */
-static void x509_hash( const unsigned char *in, size_t len, int alg,
- unsigned char *out )
-{
- switch( alg )
- {
-#if defined(POLARSSL_MD2_C)
- case SIG_RSA_MD2 : md2( in, len, out ); break;
-#endif
-#if defined(POLARSSL_MD4_C)
- case SIG_RSA_MD4 : md4( in, len, out ); break;
-#endif
-#if defined(POLARSSL_MD5_C)
- case SIG_RSA_MD5 : md5( in, len, out ); break;
-#endif
-#if defined(POLARSSL_SHA1_C)
- case SIG_RSA_SHA1 : sha1( in, len, out ); break;
-#endif
-#if defined(POLARSSL_SHA2_C)
- case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
- case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
-#endif
-#if defined(POLARSSL_SHA4_C)
- case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
- case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
-#endif
- default:
- memset( out, '\xFF', 64 );
- break;
- }
-}
-
-/*
- * Check that the given certificate is valid accoring to the CRL.
- */
-static int x509parse_verifycrl(x509_cert *crt, x509_cert *ca,
- x509_crl *crl_list)
-{
- int flags = 0;
- int hash_id;
- unsigned char hash[64];
-
- /*
- * TODO: What happens if no CRL is present?
- * Suggestion: Revocation state should be unknown if no CRL is present.
- * For backwards compatibility this is not yet implemented.
- */
-
- while( ca != NULL && crl_list != NULL && crl_list->version != 0 )
- {
- if( crl_list->issuer_raw.len != ca->subject_raw.len ||
- memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
- crl_list->issuer_raw.len ) != 0 )
- {
- crl_list = crl_list->next;
- continue;
- }
-
- /*
- * Check if CRL is correctly signed by the trusted CA
- */
- hash_id = crl_list->sig_alg;
-
- x509_hash( crl_list->tbs.p, crl_list->tbs.len, hash_id, hash );
-
- if( !rsa_pkcs1_verify( &ca->rsa, RSA_PUBLIC, hash_id,
- 0, hash, crl_list->sig.p ) == 0 )
- {
- /*
- * CRL is not trusted
- */
- flags |= BADCRL_NOT_TRUSTED;
- break;
- }
-
- /*
- * Check for validity of CRL (Do not drop out)
- */
- if( x509parse_time_expired( &crl_list->next_update ) )
- flags |= BADCRL_EXPIRED;
-
- /*
- * Check if certificate is revoked
- */
- if( x509parse_revoked(crt, crl_list) )
- {
- flags |= BADCERT_REVOKED;
- break;
- }
-
- crl_list = crl_list->next;
- }
- return flags;
-}
-
-int x509_wildcard_verify( const char *cn, x509_buf *name )
-{
- size_t i;
- size_t cn_idx = 0;
-
- if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
- return( 0 );
-
- for( i = 0; i < strlen( cn ); ++i )
- {
- if( cn[i] == '.' )
- {
- cn_idx = i;
- break;
- }
- }
-
- if( cn_idx == 0 )
- return( 0 );
-
- if( memcmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 &&
- strlen( cn ) - cn_idx == name->len - 1 )
- {
- return( 1 );
- }
-
- return( 0 );
-}
-
-/*
- * Verify the certificate validity
- */
-int x509parse_verify( x509_cert *crt,
- x509_cert *trust_ca,
- x509_crl *ca_crl,
- const char *cn, int *flags,
- int (*f_vrfy)(void *, x509_cert *, int, int),
- void *p_vrfy )
-{
- size_t cn_len;
- int hash_id;
- int pathlen;
- x509_cert *parent;
- x509_name *name;
- unsigned char hash[64];
- x509_sequence *cur = NULL;
-
- *flags = 0;
-
- if( x509parse_time_expired( &crt->valid_to ) )
- *flags = BADCERT_EXPIRED;
-
- if( cn != NULL )
- {
- name = &crt->subject;
- cn_len = strlen( cn );
-
- while( name != NULL )
- {
- if( memcmp( name->oid.p, OID_CN, 3 ) == 0 )
- {
- if( memcmp( name->val.p, cn, cn_len ) == 0 &&
- name->val.len == cn_len )
- break;
-
- if( memcmp( name->val.p, "*.", 2 ) == 0 &&
- x509_wildcard_verify( cn, &name->val ) )
- break;
- }
-
- name = name->next;
- }
-
- if( name == NULL )
- {
- if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
- {
- cur = &crt->subject_alt_names;
-
- while( cur != NULL )
- {
- if( memcmp( cn, cur->buf.p, cn_len ) == 0 &&
- cur->buf.len == cn_len )
- break;
-
- if( memcmp( cur->buf.p, "*.", 2 ) == 0 &&
- x509_wildcard_verify( cn, &cur->buf ) )
- break;
-
- cur = cur->next;
- }
- }
-
- if( cur == NULL )
- *flags |= BADCERT_CN_MISMATCH;
- }
- }
-
- /*
- * Iterate upwards in the given cert chain,
- * ignoring any upper cert with CA != TRUE.
- */
- parent = crt->next;
-
- pathlen = 1;
-
- while( parent != NULL && parent->version != 0 )
- {
- if( parent->ca_istrue == 0 ||
- crt->issuer_raw.len != parent->subject_raw.len ||
- memcmp( crt->issuer_raw.p, parent->subject_raw.p,
- crt->issuer_raw.len ) != 0 )
- {
- parent = parent->next;
- continue;
- }
-
- hash_id = crt->sig_alg;
-
- x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
-
- if( rsa_pkcs1_verify( &parent->rsa, RSA_PUBLIC, hash_id, 0, hash,
- crt->sig.p ) != 0 )
- *flags |= BADCERT_NOT_TRUSTED;
-
- /* Check trusted CA's CRL for the given crt */
- *flags |= x509parse_verifycrl(crt, parent, ca_crl);
-
- /* crt is verified to be a child of the parent cur, call verify callback */
- if( NULL != f_vrfy )
- {
- if( f_vrfy( p_vrfy, crt, pathlen - 1, ( *flags == 0 ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
- else
- *flags = 0;
- }
- else if( *flags != 0 )
- return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
-
- pathlen++;
-
- crt = parent;
- parent = crt->next;
- }
-
- /*
- * Attempt to validate topmost cert with our CA chain.
- */
- *flags |= BADCERT_NOT_TRUSTED;
-
- while( trust_ca != NULL && trust_ca->version != 0 )
- {
- if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
- memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
- crt->issuer_raw.len ) != 0 )
- {
- trust_ca = trust_ca->next;
- continue;
- }
-
- if( trust_ca->max_pathlen > 0 &&
- trust_ca->max_pathlen < pathlen )
- break;
-
- hash_id = crt->sig_alg;
-
- x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
-
- if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
- 0, hash, crt->sig.p ) == 0 )
- {
- /*
- * cert. is signed by a trusted CA
- */
- *flags &= ~BADCERT_NOT_TRUSTED;
- break;
- }
-
- trust_ca = trust_ca->next;
- }
-
- /* Check trusted CA's CRL for the given crt */
- *flags |= x509parse_verifycrl( crt, trust_ca, ca_crl );
-
- /* Verification succeeded, call callback on top cert */
- if( NULL != f_vrfy )
- {
- if( f_vrfy(p_vrfy, crt, pathlen-1, ( *flags == 0 ) ) != 0 )
- return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
- else
- *flags = 0;
- }
- else if( *flags != 0 )
- return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
-
- return( 0 );
-}
-
-/*
- * Unallocate all certificate data
- */
-void x509_free( x509_cert *crt )
-{
- x509_cert *cert_cur = crt;
- x509_cert *cert_prv;
- x509_name *name_cur;
- x509_name *name_prv;
- x509_sequence *seq_cur;
- x509_sequence *seq_prv;
-
- if( crt == NULL )
- return;
-
- do
- {
- rsa_free( &cert_cur->rsa );
-
- name_cur = cert_cur->issuer.next;
- while( name_cur != NULL )
- {
- name_prv = name_cur;
- name_cur = name_cur->next;
- memset( name_prv, 0, sizeof( x509_name ) );
- free( name_prv );
- }
-
- name_cur = cert_cur->subject.next;
- while( name_cur != NULL )
- {
- name_prv = name_cur;
- name_cur = name_cur->next;
- memset( name_prv, 0, sizeof( x509_name ) );
- free( name_prv );
- }
-
- seq_cur = cert_cur->ext_key_usage.next;
- while( seq_cur != NULL )
- {
- seq_prv = seq_cur;
- seq_cur = seq_cur->next;
- memset( seq_prv, 0, sizeof( x509_sequence ) );
- free( seq_prv );
- }
-
- seq_cur = cert_cur->subject_alt_names.next;
- while( seq_cur != NULL )
- {
- seq_prv = seq_cur;
- seq_cur = seq_cur->next;
- memset( seq_prv, 0, sizeof( x509_sequence ) );
- free( seq_prv );
- }
-
- if( cert_cur->raw.p != NULL )
- {
- memset( cert_cur->raw.p, 0, cert_cur->raw.len );
- free( cert_cur->raw.p );
- }
-
- cert_cur = cert_cur->next;
- }
- while( cert_cur != NULL );
-
- cert_cur = crt;
- do
- {
- cert_prv = cert_cur;
- cert_cur = cert_cur->next;
-
- memset( cert_prv, 0, sizeof( x509_cert ) );
- if( cert_prv != crt )
- free( cert_prv );
- }
- while( cert_cur != NULL );
-}
-
-/*
- * Unallocate all CRL data
- */
-void x509_crl_free( x509_crl *crl )
-{
- x509_crl *crl_cur = crl;
- x509_crl *crl_prv;
- x509_name *name_cur;
- x509_name *name_prv;
- x509_crl_entry *entry_cur;
- x509_crl_entry *entry_prv;
-
- if( crl == NULL )
- return;
-
- do
- {
- name_cur = crl_cur->issuer.next;
- while( name_cur != NULL )
- {
- name_prv = name_cur;
- name_cur = name_cur->next;
- memset( name_prv, 0, sizeof( x509_name ) );
- free( name_prv );
- }
-
- entry_cur = crl_cur->entry.next;
- while( entry_cur != NULL )
- {
- entry_prv = entry_cur;
- entry_cur = entry_cur->next;
- memset( entry_prv, 0, sizeof( x509_crl_entry ) );
- free( entry_prv );
- }
-
- if( crl_cur->raw.p != NULL )
- {
- memset( crl_cur->raw.p, 0, crl_cur->raw.len );
- free( crl_cur->raw.p );
- }
-
- crl_cur = crl_cur->next;
- }
- while( crl_cur != NULL );
-
- crl_cur = crl;
- do
- {
- crl_prv = crl_cur;
- crl_cur = crl_cur->next;
-
- memset( crl_prv, 0, sizeof( x509_crl ) );
- if( crl_prv != crl )
- free( crl_prv );
- }
- while( crl_cur != NULL );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include "polarssl/certs.h"
-
-/*
- * Checkup routine
- */
-int x509_self_test( int verbose )
-{
-#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
- int ret;
- int flags;
- size_t i, j;
- x509_cert cacert;
- x509_cert clicert;
- rsa_context rsa;
-#if defined(POLARSSL_DHM_C)
- dhm_context dhm;
-#endif
-
- if( verbose != 0 )
- printf( " X.509 certificate load: " );
-
- memset( &clicert, 0, sizeof( x509_cert ) );
-
- ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
- strlen( test_cli_crt ) );
- if( ret != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( ret );
- }
-
- memset( &cacert, 0, sizeof( x509_cert ) );
-
- ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
- strlen( test_ca_crt ) );
- if( ret != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( ret );
- }
-
- if( verbose != 0 )
- printf( "passed\n X.509 private key load: " );
-
- i = strlen( test_ca_key );
- j = strlen( test_ca_pwd );
-
- rsa_init( &rsa, RSA_PKCS_V15, 0 );
-
- if( ( ret = x509parse_key( &rsa,
- (unsigned char *) test_ca_key, i,
- (unsigned char *) test_ca_pwd, j ) ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( ret );
- }
-
- if( verbose != 0 )
- printf( "passed\n X.509 signature verify: ");
-
- ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &flags, NULL, NULL );
- if( ret != 0 )
- {
- printf("%02x", flags);
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( ret );
- }
-
-#if defined(POLARSSL_DHM_C)
- if( verbose != 0 )
- printf( "passed\n X.509 DHM parameter load: " );
-
- i = strlen( test_dhm_params );
- j = strlen( test_ca_pwd );
-
- if( ( ret = x509parse_dhm( &dhm, (unsigned char *) test_dhm_params, i ) ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( ret );
- }
-
- if( verbose != 0 )
- printf( "passed\n\n" );
-#endif
-
- x509_free( &cacert );
- x509_free( &clicert );
- rsa_free( &rsa );
-#if defined(POLARSSL_DHM_C)
- dhm_free( &dhm );
-#endif
-
- return( 0 );
-#else
- ((void) verbose);
- return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-#endif
-}
-
-#endif
-
-#endif
diff --git a/polarssl/src/library/x509write.c b/polarssl/src/library/x509write.c
deleted file mode 100644
index 400ffa0..0000000
--- a/polarssl/src/library/x509write.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * X509 buffer writing functionality
- *
- * Copyright (C) 2006-2012, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_X509_WRITE_C)
-
-#include "polarssl/asn1write.h"
-#include "polarssl/x509write.h"
-#include "polarssl/x509.h"
-#include "polarssl/sha1.h"
-#include "polarssl/sha2.h"
-#include "polarssl/sha4.h"
-#include "polarssl/md4.h"
-#include "polarssl/md5.h"
-
-int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa )
-{
- int ret;
- unsigned char *c;
- size_t len = 0;
-
- c = buf + size - 1;
-
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
-
- ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- if( c - buf < 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- *--c = 0;
- len += 1;
-
- ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
-
- ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA ) );
-
- ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- return( len );
-}
-
-int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa )
-{
- int ret;
- unsigned char *c;
- size_t len = 0;
-
- c = buf + size - 1;
-
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
- ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
- ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
-
- ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- // TODO: Make NON RSA Specific variant later on
-/* *--c = 0;
- len += 1;
-
- len += asn1_write_len( &c, len);
- len += asn1_write_tag( &c, ASN1_BIT_STRING );
-
- len += asn1_write_oid( &c, OID_PKCS1_RSA );
-
- len += asn1_write_int( &c, 0 );
-
- len += asn1_write_len( &c, len);
- len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
-
-/* for(i = 0; i < len; ++i)
- {
- if (i % 16 == 0 ) printf("\n");
- printf("%02x ", c[i]);
- }
- printf("\n");*/
-
- return( len );
-}
-
-int x509_write_name( unsigned char **p, unsigned char *start, char *oid,
- char *name )
-{
- int ret;
- size_t string_len = 0;
- size_t oid_len = 0;
- size_t len = 0;
-
- // Write PrintableString for all except OID_PKCS9_EMAIL
- //
- if( OID_SIZE( OID_PKCS9_EMAIL ) == strlen( oid ) &&
- memcmp( oid, OID_PKCS9_EMAIL, strlen( oid ) ) == 0 )
- {
- ASN1_CHK_ADD( string_len, asn1_write_ia5_string( p, start, name ) );
- }
- else
- ASN1_CHK_ADD( string_len, asn1_write_printable_string( p, start, name ) );
-
- // Write OID
- //
- ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) );
-
- len = oid_len + string_len;
- ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + string_len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
-
- return( len );
-}
-
-/*
- * Wrapper for x509 hashes.
- *
- * \param out Buffer to receive the hash (Should be at least 64 bytes)
- */
-static void x509_hash( const unsigned char *in, size_t len, int alg,
- unsigned char *out )
-{
- switch( alg )
- {
-#if defined(POLARSSL_MD2_C)
- case SIG_RSA_MD2 : md2( in, len, out ); break;
-#endif
-#if defined(POLARSSL_MD4_C)
- case SIG_RSA_MD4 : md4( in, len, out ); break;
-#endif
-#if defined(POLARSSL_MD5_C)
- case SIG_RSA_MD5 : md5( in, len, out ); break;
-#endif
-#if defined(POLARSSL_SHA1_C)
- case SIG_RSA_SHA1 : sha1( in, len, out ); break;
-#endif
-#if defined(POLARSSL_SHA2_C)
- case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
- case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
-#endif
-#if defined(POLARSSL_SHA4_C)
- case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
- case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
-#endif
- default:
- memset( out, '\xFF', 64 );
- break;
- }
-}
-
-int x509_write_sig( unsigned char **p, unsigned char *start, char *oid,
- unsigned char *sig, size_t size )
-{
- int ret;
- size_t len = 0;
-
- if( *p - start < (int) size + 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- len = size;
- (*p) -= len;
- memcpy( *p, sig, len );
-
- *--(*p) = 0;
- len += 1;
-
- ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
-
- // Write OID
- //
- ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid ) );
-
- return( len );
-}
-
-int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa,
- x509_req_name *req_name, int hash_id )
-{
- int ret;
- char sig_oid[10];
- unsigned char *c, *c2;
- unsigned char hash[64];
- unsigned char sig[POLARSSL_MPI_MAX_SIZE];
- unsigned char tmp_buf[2048];
- size_t sub_len = 0, pub_len = 0, sig_len = 0;
- size_t len = 0;
- x509_req_name *cur = req_name;
-
- c = tmp_buf + 2048 - 1;
-
- ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, 0 ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
-
- ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->E ) );
- ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->N ) );
-
- ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
- ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- if( c - tmp_buf < 1 )
- return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
-
- *--c = 0;
- pub_len += 1;
-
- ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
- ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
-
- ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) );
-
- len += pub_len;
- ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- while( cur != NULL )
- {
- ASN1_CHK_ADD( sub_len, x509_write_name( &c, tmp_buf, cur->oid, cur->name ) );
-
- cur = cur->next;
- }
-
- len += sub_len;
- ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
-
- ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- x509_hash( c, len, hash_id, hash );
-
- rsa_pkcs1_sign( rsa, NULL, NULL, RSA_PRIVATE, hash_id, 0, hash, sig );
-
- // Generate correct OID
- //
- memcpy( sig_oid, OID_PKCS1, 8 );
- sig_oid[8] = hash_id;
- sig_oid[9] = '\0';
-
- c2 = buf + size - 1;
- ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, rsa->len ) );
-
- c2 -= len;
- memcpy( c2, c, len );
-
- len += sig_len;
- ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
- ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
-
- return( len );
-}
-
-#endif
diff --git a/polarssl/src/library/xtea.c b/polarssl/src/library/xtea.c
deleted file mode 100644
index bc473e5..0000000
--- a/polarssl/src/library/xtea.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * An 32-bit implementation of the XTEA algorithm
- *
- * Copyright (C) 2006-2010, Brainspark B.V.
- *
- * This file is part of PolarSSL (http://www.polarssl.org)
- * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_XTEA_C)
-
-#include "polarssl/xtea.h"
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) ); \
-}
-#endif
-
-/*
- * XTEA key schedule
- */
-void xtea_setup( xtea_context *ctx, unsigned char key[16] )
-{
- int i;
-
- memset(ctx, 0, sizeof(xtea_context));
-
- for( i = 0; i < 4; i++ )
- {
- GET_ULONG_BE( ctx->k[i], key, i << 2 );
- }
-}
-
-/*
- * XTEA encrypt function
- */
-int xtea_crypt_ecb( xtea_context *ctx, int mode, unsigned char input[8],
- unsigned char output[8])
-{
- uint32_t *k, v0, v1, i;
-
- k = ctx->k;
-
- GET_ULONG_BE( v0, input, 0 );
- GET_ULONG_BE( v1, input, 4 );
-
- if( mode == XTEA_ENCRYPT )
- {
- uint32_t sum = 0, delta = 0x9E3779B9;
-
- for( i = 0; i < 32; i++ )
- {
- v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
- sum += delta;
- v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
- }
- }
- else /* XTEA_DECRYPT */
- {
- uint32_t delta = 0x9E3779B9, sum = delta * 32;
-
- for( i = 0; i < 32; i++ )
- {
- v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
- sum -= delta;
- v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
- }
- }
-
- PUT_ULONG_BE( v0, output, 0 );
- PUT_ULONG_BE( v1, output, 4 );
-
- return( 0 );
-}
-
-/*
- * XTEA-CBC buffer encryption/decryption
- */
-int xtea_crypt_cbc( xtea_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[8],
- unsigned char *input,
- unsigned char *output)
-{
- int i;
- unsigned char temp[8];
-
- if(length % 8)
- return( POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH );
-
- if( mode == XTEA_DECRYPT )
- {
- while( length > 0 )
- {
- memcpy( temp, input, 8 );
- xtea_crypt_ecb( ctx, mode, input, output );
-
- for(i = 0; i < 8; i++)
- output[i] = (unsigned char)( output[i] ^ iv[i] );
-
- memcpy( iv, temp, 8 );
-
- input += 8;
- output += 8;
- length -= 8;
- }
- }
- else
- {
- while( length > 0 )
- {
- for( i = 0; i < 8; i++ )
- output[i] = (unsigned char)( input[i] ^ iv[i] );
-
- xtea_crypt_ecb( ctx, mode, output, output );
- memcpy( iv, output, 8 );
-
- input += 8;
- output += 8;
- length -= 8;
- }
- }
-
- return( 0 );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-
-#include <string.h>
-#include <stdio.h>
-
-/*
- * XTEA tests vectors (non-official)
- */
-
-static const unsigned char xtea_test_key[6][16] =
-{
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
- 0x0c, 0x0d, 0x0e, 0x0f },
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
- 0x0c, 0x0d, 0x0e, 0x0f },
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
- 0x0c, 0x0d, 0x0e, 0x0f },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00 }
-};
-
-static const unsigned char xtea_test_pt[6][8] =
-{
- { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
- { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
- { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
- { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
- { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
- { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
-};
-
-static const unsigned char xtea_test_ct[6][8] =
-{
- { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
- { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
- { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
- { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
- { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
- { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
-};
-
-/*
- * Checkup routine
- */
-int xtea_self_test( int verbose )
-{
- int i;
- unsigned char buf[8];
- xtea_context ctx;
-
- for( i = 0; i < 6; i++ )
- {
- if( verbose != 0 )
- printf( " XTEA test #%d: ", i + 1 );
-
- memcpy( buf, xtea_test_pt[i], 8 );
-
- xtea_setup( &ctx, (unsigned char *) xtea_test_key[i] );
- xtea_crypt_ecb( &ctx, XTEA_ENCRYPT, buf, buf );
-
- if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 )
- {
- if( verbose != 0 )
- printf( "failed\n" );
-
- return( 1 );
- }
-
- if( verbose != 0 )
- printf( "passed\n" );
- }
-
- if( verbose != 0 )
- printf( "\n" );
-
- return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/pthreads/pthread-win32.vcxproj.filters b/pthreads/pthread-win32.vcxproj.filters
deleted file mode 100644
index 018736f..0000000
--- a/pthreads/pthread-win32.vcxproj.filters
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="include">
- <UniqueIdentifier>{3a19fdc3-6df5-4400-b261-99ce258b4112}</UniqueIdentifier>
- </Filter>
- <Filter Include="src">
- <UniqueIdentifier>{e7061adc-6595-41d4-b2a0-1dfdb96907bc}</UniqueIdentifier>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\config.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\implement.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\need_errno.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\pthread.h">
- <Filter>include</Filter>
- </ClInclude>
- <ClInclude Include="src\semaphore.h">
- <Filter>include</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\pthread.c">
- <Filter>src</Filter>
- </ClCompile>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/pthreads/src/COPYING.LIB b/pthreads/src/COPYING.LIB
deleted file mode 100644
index b1e3f5a..0000000
--- a/pthreads/src/COPYING.LIB
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/pthreads/src/README b/pthreads/src/README
deleted file mode 100644
index 545360b..0000000
--- a/pthreads/src/README
+++ /dev/null
@@ -1,601 +0,0 @@
-PTHREADS-WIN32
-==============
-
-Pthreads-win32 is free software, distributed under the GNU Lesser
-General Public License (LGPL). See the file 'COPYING.LIB' for terms
-and conditions. Also see the file 'COPYING' for information
-specific to pthreads-win32, copyrights and the LGPL.
-
-
-What is it?
------------
-
-Pthreads-win32 is an Open Source Software implementation of the
-Threads component of the POSIX 1003.1c 1995 Standard (or later)
-for Microsoft's Win32 environment. Some functions from POSIX
-1003.1b are also supported including semaphores. Other related
-functions include the set of read-write lock functions. The
-library also supports some of the functionality of the Open
-Group's Single Unix specification, version 2, namely mutex types,
-plus some common and pthreads-win32 specific non-portable
-routines (see README.NONPORTABLE).
-
-See the file "ANNOUNCE" for more information including standards
-conformance details and the list of supported and unsupported
-routines.
-
-
-Prerequisites
--------------
-MSVC or GNU C (MinGW32 MSys development kit)
- To build from source.
-
-QueueUserAPCEx by Panagiotis E. Hadjidoukas
- To support any thread cancelation in C++ library builds or
- to support cancelation of blocked threads in any build.
- This library is not required otherwise.
-
- For true async cancelation of threads (including blocked threads).
- This is a DLL and Windows driver that provides pre-emptive APC
- by forcing threads into an alertable state when the APC is queued.
- Both the DLL and driver are provided with the pthreads-win32.exe
- self-unpacking ZIP, and on the pthreads-win32 FTP site (in source
- and pre-built forms). Currently this is a separate LGPL package to
- pthreads-win32. See the README in the QueueUserAPCEx folder for
- installation instructions.
-
- Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL
- QuserEx.DLL is available and whether the driver AlertDrv.sys is
- loaded. If it is not available, pthreads-win32 will simulate async
- cancelation, which means that it can async cancel only threads that
- are runnable. The simulated async cancellation cannot cancel blocked
- threads.
-
- [FOR SECURITY] To be found Quserex.dll MUST be installed in the
- Windows System Folder. This is not an unreasonable constraint given a
- driver must also be installed and loaded at system startup.
-
-
-Library naming
---------------
-
-Because the library is being built using various exception
-handling schemes and compilers - and because the library
-may not work reliably if these are mixed in an application,
-each different version of the library has it's own name.
-
-Note 1: the incompatibility is really between EH implementations
-of the different compilers. It should be possible to use the
-standard C version from either compiler with C++ applications
-built with a different compiler. If you use an EH version of
-the library, then you must use the same compiler for the
-application. This is another complication and dependency that
-can be avoided by using only the standard C library version.
-
-Note 2: if you use a standard C pthread*.dll with a C++
-application, then any functions that you define that are
-intended to be called via pthread_cleanup_push() must be
-__cdecl.
-
-Note 3: the intention was to also name either the VC or GC
-version (it should be arbitrary) as pthread.dll, including
-pthread.lib and libpthread.a as appropriate. This is no longer
-likely to happen.
-
-Note 4: the compatibility number was added so that applications
-can differentiate between binary incompatible versions of the
-libs and dlls.
-
-In general:
- pthread[VG]{SE,CE,C}[c].dll
- pthread[VG]{SE,CE,C}[c].lib
-
-where:
- [VG] indicates the compiler
- V - MS VC, or
- G - GNU C
-
- {SE,CE,C} indicates the exception handling scheme
- SE - Structured EH, or
- CE - C++ EH, or
- C - no exceptions - uses setjmp/longjmp
-
- c - DLL compatibility number indicating ABI and API
- compatibility with applications built against
- a snapshot with the same compatibility number.
- See 'Version numbering' below.
-
-The name may also be suffixed by a 'd' to indicate a debugging version
-of the library. E.g. pthreadVC2d.lib. Debugging versions contain
-additional information for debugging (symbols etc) and are often not
-optimised in any way (compiled with optimisation turned off).
-
-Examples:
- pthreadVSE.dll (MSVC/SEH)
- pthreadGCE.dll (GNUC/C++ EH)
- pthreadGC.dll (GNUC/not dependent on exceptions)
- pthreadVC1.dll (MSVC/not dependent on exceptions - not binary
- compatible with pthreadVC.dll)
- pthreadVC2.dll (MSVC/not dependent on exceptions - not binary
- compatible with pthreadVC1.dll or pthreadVC.dll)
-
-The GNU library archive file names have correspondingly changed to:
-
- libpthreadGCEc.a
- libpthreadGCc.a
-
-
-Versioning numbering
---------------------
-
-Version numbering is separate from the snapshot dating system, and
-is the canonical version identification system embedded within the
-DLL using the Microsoft version resource system. The versioning
-system chosen follows the GNU Libtool system. See
-http://www.gnu.org/software/libtool/manual.html section 6.2.
-
-See the resource file 'version.rc'.
-
-Microsoft version numbers use 4 integers:
-
- 0.0.0.0
-
-Pthreads-win32 uses the first 3 following the Libtool convention.
-The fourth is commonly used for the build number, but will be reserved
-for future use.
-
- current.revision.age.0
-
-The numbers are changed as follows:
-
-1. If the library source code has changed at all since the last update,
- then increment revision (`c:r:a' becomes `c:r+1:a').
-2. If any interfaces have been added, removed, or changed since the last
- update, increment current, and set revision to 0.
-3. If any interfaces have been added since the last public release, then
- increment age.
-4. If any interfaces have been removed or changed since the last public
- release, then set age to 0.
-
-
-DLL compatibility numbering is an attempt to ensure that applications
-always load a compatible pthreads-win32 DLL by using a DLL naming system
-that is consistent with the version numbering system. It also allows
-older and newer DLLs to coexist in the same filesystem so that older
-applications can continue to be used. For pre .NET Windows systems,
-this inevitably requires incompatible versions of the same DLLs to have
-different names.
-
-Pthreads-win32 has adopted the Cygwin convention of appending a single
-integer number to the DLL name. The number used is based on the library
-version number and is computed as 'current' - 'age'.
-
-(See http://home.att.net/~perlspinr/libversioning.html for a nicely
-detailed explanation.)
-
-Using this method, DLL name/s will only change when the DLL's
-backwards compatibility changes. Note that the addition of new
-'interfaces' will not of itself change the DLL's compatibility for older
-applications.
-
-
-Which of the several dll versions to use?
------------------------------------------
-or,
----
-What are all these pthread*.dll and pthread*.lib files?
--------------------------------------------------------
-
-Simple, use either pthreadGCv.* if you use GCC, or pthreadVCv.* if you
-use MSVC - where 'v' is the DLL versioning (compatibility) number.
-
-Otherwise, you need to choose carefully and know WHY.
-
-The most important choice you need to make is whether to use a
-version that uses exceptions internally, or not. There are versions
-of the library that use exceptions as part of the thread
-cancelation and exit implementation. The default version uses
-setjmp/longjmp.
-
-There is some contension amongst POSIX threads experts as
-to how POSIX threads cancelation and exit should work
-with languages that use exceptions, e.g. C++ and even C
-(Microsoft's Structured Exceptions).
-
-The issue is: should cancelation of a thread in, say,
-a C++ application cause object destructors and C++ exception
-handlers to be invoked as the stack unwinds during thread
-exit, or not?
-
-There seems to be more opinion in favour of using the
-standard C version of the library (no EH) with C++ applications
-for the reason that this appears to be the assumption commercial
-pthreads implementations make. Therefore, if you use an EH version
-of pthreads-win32 then you may be under the illusion that
-your application will be portable, when in fact it is likely to
-behave differently when linked with other pthreads libraries.
-
-Now you may be asking: then why have you kept the EH versions of
-the library?
-
-There are a couple of reasons:
-- there is division amongst the experts and so the code may
- be needed in the future. Yes, it's in the repository and we
- can get it out anytime in the future, but it would be difficult
- to find.
-- pthreads-win32 is one of the few implementations, and possibly
- the only freely available one, that has EH versions. It may be
- useful to people who want to play with or study application
- behaviour under these conditions.
-
-Notes:
-
-[If you use either pthreadVCE or pthreadGCE]
-
-1. [See also the discussion in the FAQ file - Q2, Q4, and Q5]
-
-If your application contains catch(...) blocks in your POSIX
-threads then you will need to replace the "catch(...)" with the macro
-"PtW32Catch", eg.
-
- #ifdef PtW32Catch
- PtW32Catch {
- ...
- }
- #else
- catch(...) {
- ...
- }
- #endif
-
-Otherwise neither pthreads cancelation nor pthread_exit() will work
-reliably when using versions of the library that use C++ exceptions
-for cancelation and thread exit.
-
-This is due to what is believed to be a C++ compliance error in VC++
-whereby you may not have multiple handlers for the same exception in
-the same try/catch block. GNU G++ doesn't have this restriction.
-
-
-Other name changes
-------------------
-
-All snapshots prior to and including snapshot 2000-08-13
-used "_pthread_" as the prefix to library internal
-functions, and "_PTHREAD_" to many library internal
-macros. These have now been changed to "ptw32_" and "PTW32_"
-respectively so as to not conflict with the ANSI standard's
-reservation of identifiers beginning with "_" and "__" for
-use by compiler implementations only.
-
-If you have written any applications and you are linking
-statically with the pthreads-win32 library then you may have
-included a call to _pthread_processInitialize. You will
-now have to change that to ptw32_processInitialize.
-
-
-Cleanup code default style
---------------------------
-
-Previously, if not defined, the cleanup style was determined automatically
-from the compiler used, and one of the following was defined accordingly:
-
- __CLEANUP_SEH MSVC only
- __CLEANUP_CXX C++, including MSVC++, GNU G++
- __CLEANUP_C C, including GNU GCC, not MSVC
-
-These defines determine the style of cleanup (see pthread.h) and,
-most importantly, the way that cancelation and thread exit (via
-pthread_exit) is performed (see the routine ptw32_throw()).
-
-In short, the exceptions versions of the library throw an exception
-when a thread is canceled, or exits via pthread_exit(). This exception is
-caught by a handler in the thread startup routine, so that the
-the correct stack unwinding occurs regardless of where the thread
-is when it's canceled or exits via pthread_exit().
-
-In this snapshot, unless the build explicitly defines (e.g. via a
-compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
-the build NOW always defaults to __CLEANUP_C style cleanup. This style
-uses setjmp/longjmp in the cancelation and pthread_exit implementations,
-and therefore won't do stack unwinding even when linked to applications
-that have it (e.g. C++ apps). This is for consistency with most/all
-commercial Unix POSIX threads implementations.
-
-Although it was not clearly documented before, it is still necessary to
-build your application using the same __CLEANUP_* define as was
-used for the version of the library that you link with, so that the
-correct parts of pthread.h are included. That is, the possible
-defines require the following library versions:
-
- __CLEANUP_SEH pthreadVSE.dll
- __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll
- __CLEANUP_C pthreadVC.dll or pthreadGC.dll
-
-It is recommended that you let pthread.h use it's default __CLEANUP_C
-for both library and application builds. That is, don't define any of
-the above, and then link with pthreadVC.lib (MSVC or MSVC++) and
-libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but
-another reason is that the prebuilt pthreadVCE.dll is currently broken.
-Versions built with MSVC++ later than version 6 may not be broken, but I
-can't verify this yet.
-
-WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY?
-Because no commercial Unix POSIX threads implementation allows you to
-choose to have stack unwinding. Therefore, providing it in pthread-win32
-as a default is dangerous. We still provide the choice but unless
-you consciously choose to do otherwise, your pthreads applications will
-now run or crash in similar ways irrespective of the pthreads platform
-you use. Or at least this is the hope.
-
-
-Building under VC++ using C++ EH, Structured EH, or just C
-----------------------------------------------------------
-
-From the source directory run nmake without any arguments to list
-help information. E.g.
-
-$ nmake
-
-Microsoft (R) Program Maintenance Utility Version 6.00.8168.0
-Copyright (C) Microsoft Corp 1988-1998. All rights reserved.
-
-Run one of the following command lines:
-nmake clean VCE (to build the MSVC dll with C++ exception handling)
-nmake clean VSE (to build the MSVC dll with structured exception handling)
-nmake clean VC (to build the MSVC dll with C cleanup code)
-nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling)
-nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling)
-nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code)
-nmake clean VC-static (to build the MSVC static lib with C cleanup code)
-nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling)
-nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling)
-nmake clean VC-debug (to build the debug MSVC dll with C cleanup code)
-nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling)
-nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling)
-nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code)
-nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code)
-
-
-The pre-built dlls are normally built using the *-inlined targets.
-
-You can run the testsuite by changing to the "tests" directory and
-running nmake. E.g.:
-
-$ cd tests
-$ nmake
-
-Microsoft (R) Program Maintenance Utility Version 6.00.8168.0
-Copyright (C) Microsoft Corp 1988-1998. All rights reserved.
-
-Run one of the following command lines:
-nmake clean VC (to test using VC dll with VC (no EH) applications)
-nmake clean VCX (to test using VC dll with VC++ (EH) applications)
-nmake clean VCE (to test using the VCE dll with VC++ EH applications)
-nmake clean VSE (to test using VSE dll with VC (SEH) applications)
-nmake clean VC-bench (to benchtest using VC dll with C bench app)
-nmake clean VCX-bench (to benchtest using VC dll with C++ bench app)
-nmake clean VCE-bench (to benchtest using VCE dll with C++ bench app)
-nmake clean VSE-bench (to benchtest using VSE dll with SEH bench app)
-nmake clean VC-static (to test using VC static lib with VC (no EH) applications)
-
-
-Building under Mingw32
-----------------------
-
-The dll can be built easily with recent versions of Mingw32.
-(The distributed versions are built using Mingw32 and MsysDTK
-from www.mingw32.org.)
-
-From the source directory, run make for help information. E.g.:
-
-$ make
-Run one of the following command lines:
-make clean GC (to build the GNU C dll with C cleanup code)
-make clean GCE (to build the GNU C dll with C++ exception handling)
-make clean GC-inlined (to build the GNU C inlined dll with C cleanup code)
-make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling)
-make clean GC-static (to build the GNU C inlined static lib with C cleanup code)
-make clean GC-debug (to build the GNU C debug dll with C cleanup code)
-make clean GCE-debug (to build the GNU C debug dll with C++ exception handling)
-make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code)
-make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling)
-make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code)
-
-
-The pre-built dlls are normally built using the *-inlined targets.
-
-You can run the testsuite by changing to the "tests" directory and
-running make for help information. E.g.:
-
-$ cd tests
-$ make
-Run one of the following command lines:
-make clean GC (to test using GC dll with C (no EH) applications)
-make clean GCX (to test using GC dll with C++ (EH) applications)
-make clean GCE (to test using GCE dll with C++ (EH) applications)
-make clean GC-bench (to benchtest using GNU C dll with C cleanup code)
-make clean GCE-bench (to benchtest using GNU C dll with C++ exception handling)
-make clean GC-static (to test using GC static lib with C (no EH) applications)
-
-
-Building under Linux using the Mingw32 cross development tools
---------------------------------------------------------------
-
-You can build the library without leaving Linux by using the Mingw32 cross
-development toolchain. See http://www.libsdl.org/extras/win32/cross/ for
-tools and info. The GNUmakefile contains some support for this, for example:
-
-make CROSS=i386-mingw32msvc- clean GC-inlined
-
-will build pthreadGCn.dll and libpthreadGCn.a (n=version#), provided your
-cross-tools/bin directory is in your PATH (or use the cross-make.sh script
-at the URL above).
-
-
-Building the library as a statically linkable library
------------------------------------------------------
-
-General: PTW32_STATIC_LIB must be defined for both the library build and the
-application build. The makefiles supplied and used by the following 'make'
-command lines will define this for you.
-
-MSVC (creates pthreadVCn.lib as a static link lib):
-
-nmake clean VC-static
-
-
-MinGW32 (creates libpthreadGCn.a as a static link lib):
-
-make clean GC-static
-
-
-Define PTW32_STATIC_LIB when building your application. Also, your
-application must call a two non-portable routines to initialise the
-some state on startup and cleanup before exit. One other routine needs
-to be called to cleanup after any Win32 threads have called POSIX API
-routines. See README.NONPORTABLE or the html reference manual pages for
-details on these routines:
-
-BOOL pthread_win32_process_attach_np (void);
-BOOL pthread_win32_process_detach_np (void);
-BOOL pthread_win32_thread_attach_np (void); // Currently a no-op
-BOOL pthread_win32_thread_detach_np (void);
-
-
-The tests makefiles have the same targets but only check that the
-static library is statically linkable. They don't run the full
-testsuite. To run the full testsuite, build the dlls and run the
-dll test targets.
-
-
-Building the library under Cygwin
----------------------------------
-
-Cygwin is implementing it's own POSIX threads routines and these
-will be the ones to use if you develop using Cygwin.
-
-
-Ready to run binaries
----------------------
-
-For convenience, the following ready-to-run files can be downloaded
-from the FTP site (see under "Availability" below):
-
- pthread.h
- semaphore.h
- sched.h
- pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp
- pthreadVC.lib
- pthreadVCE.dll - built with MSVC++ compiler using C++ EH
- pthreadVCE.lib
- pthreadVSE.dll - built with MSVC compiler using SEH
- pthreadVSE.lib
- pthreadGC.dll - built with Mingw32 GCC
- libpthreadGC.a - derived from pthreadGC.dll
- pthreadGCE.dll - built with Mingw32 G++
- libpthreadGCE.a - derived from pthreadGCE.dll
-
-As of August 2003 pthreads-win32 pthreadG* versions are built and tested
-using the MinGW + MsysDTK environment current as of that date or later.
-The following file MAY be needed for older MinGW environments.
-
- gcc.dll - needed to build and run applications that use
- pthreadGCE.dll.
-
-
-Building applications with GNU compilers
-----------------------------------------
-
-If you're using pthreadGC.dll:
-
-With the three header files, pthreadGC.dll and libpthreadGC.a in the
-same directory as your application myapp.c, you could compile, link
-and run myapp.c under Mingw32 as follows:
-
- gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC
- myapp
-
-Or put pthreadGC.dll in an appropriate directory in your PATH,
-put libpthreadGC.a in your system lib directory, and
-put the three header files in your system include directory,
-then use:
-
- gcc -o myapp.exe myapp.c -lpthreadGC
- myapp
-
-
-If you're using pthreadGCE.dll:
-
-With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a
-in the same directory as your application myapp.c, you could compile,
-link and run myapp.c under Mingw32 as follows:
-
- gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE
- myapp
-
-Or put pthreadGCE.dll and gcc.dll in an appropriate directory in
-your PATH, put libpthreadGCE.a in your system lib directory, and
-put the three header files in your system include directory,
-then use:
-
- gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE
- myapp
-
-
-Availability
-------------
-
-The complete source code in either unbundled, self-extracting
-Zip file, or tar/gzipped format can be found at:
-
- ftp://sources.redhat.com/pub/pthreads-win32
-
-The pre-built DLL, export libraries and matching pthread.h can
-be found at:
-
- ftp://sources.redhat.com/pub/pthreads-win32/dll-latest
-
-Home page:
-
- http://sources.redhat.com/pthreads-win32/
-
-
-Mailing list
-------------
-
-There is a mailing list for discussing pthreads on Win32.
-To join, send email to:
-
- pthreads-win32-subscribe@sources.redhat.com
-
-Unsubscribe by sending mail to:
-
- pthreads-win32-unsubscribe@sources.redhat.com
-
-
-Acknowledgements
-----------------
-
-See the ANNOUNCE file for acknowledgements.
-See the 'CONTRIBUTORS' file for the list of contributors.
-
-As much as possible, the ChangeLog file attributes
-contributions and patches that have been incorporated
-in the library to the individuals responsible.
-
-Finally, thanks to all those who work on and contribute to the
-POSIX and Single Unix Specification standards. The maturity of an
-industry can be measured by it's open standards.
-
-----
-Ross Johnson
-<rpj@callisto.canberra.edu.au>
-
-
-
-
-
-
-
-
diff --git a/pthreads/src/attr.c b/pthreads/src/attr.c
deleted file mode 100644
index a9d55f4..0000000
--- a/pthreads/src/attr.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * attr.c
- *
- * Description:
- * This translation unit agregates operations on thread attribute objects.
- * It is used for inline optimisation.
- *
- * The included modules are used separately when static executable sizes
- * must be minimised.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#include "pthread_attr_init.c"
-#include "pthread_attr_destroy.c"
-#include "pthread_attr_getdetachstate.c"
-#include "pthread_attr_setdetachstate.c"
-#include "pthread_attr_getstackaddr.c"
-#include "pthread_attr_setstackaddr.c"
-#include "pthread_attr_getstacksize.c"
-#include "pthread_attr_setstacksize.c"
-#include "pthread_attr_getscope.c"
-#include "pthread_attr_setscope.c"
diff --git a/pthreads/src/autostatic.c b/pthreads/src/autostatic.c
deleted file mode 100644
index 092aff2..0000000
--- a/pthreads/src/autostatic.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * autostatic.c
- *
- * Description:
- * This translation unit implements static auto-init and auto-exit logic.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if defined(PTW32_STATIC_LIB)
-
-#if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER)
-
-#include "pthread.h"
-#include "implement.h"
-
-static void on_process_init(void)
-{
- pthread_win32_process_attach_np ();
-}
-
-static void on_process_exit(void)
-{
- pthread_win32_thread_detach_np ();
- pthread_win32_process_detach_np ();
-}
-
-#if defined(__MINGW64__) || defined(__MINGW32__)
-# define attribute_section(a) __attribute__((section(a)))
-#elif defined(_MSC_VER)
-# define attribute_section(a) __pragma(section(a,long,read)); __declspec(allocate(a))
-#endif
-
-attribute_section(".ctors") void *gcc_ctor = on_process_init;
-attribute_section(".dtors") void *gcc_dtor = on_process_exit;
-
-attribute_section(".CRT$XCU") void *msc_ctor = on_process_init;
-attribute_section(".CRT$XPU") void *msc_dtor = on_process_exit;
-
-#endif /* defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER) */
-
-#endif /* PTW32_STATIC_LIB */
diff --git a/pthreads/src/barrier.c b/pthreads/src/barrier.c
deleted file mode 100644
index 41b950c..0000000
--- a/pthreads/src/barrier.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * barrier.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-#include "pthread_barrier_init.c"
-#include "pthread_barrier_destroy.c"
-#include "pthread_barrier_wait.c"
-#include "pthread_barrierattr_init.c"
-#include "pthread_barrierattr_destroy.c"
-#include "pthread_barrierattr_getpshared.c"
-#include "pthread_barrierattr_setpshared.c"
diff --git a/pthreads/src/cancel.c b/pthreads/src/cancel.c
deleted file mode 100644
index 1bd14eb..0000000
--- a/pthreads/src/cancel.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * cancel.c
- *
- * Description:
- * POSIX thread functions related to thread cancellation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-#include "pthread_setcancelstate.c"
-#include "pthread_setcanceltype.c"
-#include "pthread_testcancel.c"
-#include "pthread_cancel.c"
diff --git a/pthreads/src/cleanup.c b/pthreads/src/cleanup.c
deleted file mode 100644
index 381d1e8..0000000
--- a/pthreads/src/cleanup.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * cleanup.c
- *
- * Description:
- * This translation unit implements routines associated
- * with cleaning up threads.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-/*
- * The functions ptw32_pop_cleanup and ptw32_push_cleanup
- * are implemented here for applications written in C with no
- * SEH or C++ destructor support.
- */
-
-ptw32_cleanup_t *
-ptw32_pop_cleanup (int execute)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function pops the most recently pushed cleanup
- * handler. If execute is nonzero, then the cleanup handler
- * is executed if non-null.
- *
- * PARAMETERS
- * execute
- * if nonzero, execute the cleanup handler
- *
- *
- * DESCRIPTION
- * This function pops the most recently pushed cleanup
- * handler. If execute is nonzero, then the cleanup handler
- * is executed if non-null.
- * NOTE: specify 'execute' as nonzero to avoid duplication
- * of common cleanup code.
- *
- * RESULTS
- * N/A
- *
- * ------------------------------------------------------
- */
-{
- ptw32_cleanup_t *cleanup;
-
- cleanup = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey);
-
- if (cleanup != NULL)
- {
- if (execute && (cleanup->routine != NULL))
- {
-
- (*cleanup->routine) (cleanup->arg);
-
- }
-
- pthread_setspecific (ptw32_cleanupKey, (void *) cleanup->prev);
-
- }
-
- return (cleanup);
-
-} /* ptw32_pop_cleanup */
-
-
-void
-ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
- ptw32_cleanup_callback_t routine, void *arg)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function pushes a new cleanup handler onto the thread's stack
- * of cleanup handlers. Each cleanup handler pushed onto the stack is
- * popped and invoked with the argument 'arg' when
- * a) the thread exits by calling 'pthread_exit',
- * b) when the thread acts on a cancellation request,
- * c) or when the thread calls pthread_cleanup_pop with a nonzero
- * 'execute' argument
- *
- * PARAMETERS
- * cleanup
- * a pointer to an instance of pthread_cleanup_t,
- *
- * routine
- * pointer to a cleanup handler,
- *
- * arg
- * parameter to be passed to the cleanup handler
- *
- *
- * DESCRIPTION
- * This function pushes a new cleanup handler onto the thread's stack
- * of cleanup handlers. Each cleanup handler pushed onto the stack is
- * popped and invoked with the argument 'arg' when
- * a) the thread exits by calling 'pthread_exit',
- * b) when the thread acts on a cancellation request,
- * c) or when the thrad calls pthread_cleanup_pop with a nonzero
- * 'execute' argument
- * NOTE: pthread_push_cleanup, ptw32_pop_cleanup must be paired
- * in the same lexical scope.
- *
- * RESULTS
- * pthread_cleanup_t *
- * pointer to the previous cleanup
- *
- * ------------------------------------------------------
- */
-{
- cleanup->routine = routine;
- cleanup->arg = arg;
-
- cleanup->prev = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey);
-
- pthread_setspecific (ptw32_cleanupKey, (void *) cleanup);
-
-} /* ptw32_push_cleanup */
diff --git a/pthreads/src/condvar.c b/pthreads/src/condvar.c
deleted file mode 100644
index 704f4d7..0000000
--- a/pthreads/src/condvar.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * condvar.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#include "ptw32_cond_check_need_init.c"
-#include "pthread_condattr_init.c"
-#include "pthread_condattr_destroy.c"
-#include "pthread_condattr_getpshared.c"
-#include "pthread_condattr_setpshared.c"
-#include "pthread_cond_init.c"
-#include "pthread_cond_destroy.c"
-#include "pthread_cond_wait.c"
-#include "pthread_cond_signal.c"
diff --git a/pthreads/src/config.h b/pthreads/src/config.h
deleted file mode 100644
index e231724..0000000
--- a/pthreads/src/config.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* config.h */
-
-#ifndef PTW32_CONFIG_H
-#define PTW32_CONFIG_H
-
-/*********************************************************************
- * Defaults: see target specific redefinitions below.
- *********************************************************************/
-
-/* We're building the pthreads-win32 library */
-#define PTW32_BUILD
-
-/* Do we know about the C type sigset_t? */
-#undef HAVE_SIGSET_T
-
-/* Define if you have the <signal.h> header file. */
-#undef HAVE_SIGNAL_H
-
-/* Define if you have the Borland TASM32 or compatible assembler. */
-#undef HAVE_TASM32
-
-/* Define if you don't have Win32 DuplicateHandle. (eg. WinCE) */
-#undef NEED_DUPLICATEHANDLE
-
-/* Define if you don't have Win32 _beginthreadex. (eg. WinCE) */
-#undef NEED_CREATETHREAD
-
-/* Define if you don't have Win32 errno. (eg. WinCE) */
-#undef NEED_ERRNO
-
-/* Define if you don't have Win32 calloc. (eg. WinCE) */
-#undef NEED_CALLOC
-
-/* Define if you don't have Win32 ftime. (eg. WinCE) */
-#undef NEED_FTIME
-
-/* Define if you don't have Win32 semaphores. (eg. WinCE 2.1 or earlier) */
-#undef NEED_SEM
-
-/* Define if you need to convert string parameters to unicode. (eg. WinCE) */
-#undef NEED_UNICODE_CONSTS
-
-/* Define if your C (not C++) compiler supports "inline" functions. */
-#undef HAVE_C_INLINE
-
-/* Do we know about type mode_t? */
-#undef HAVE_MODE_T
-
-/*
- * Define if GCC has atomic builtins, i.e. __sync_* intrinsics
- * __sync_lock_* is implemented in mingw32 gcc 4.5.2 at least
- * so this define does not turn those on or off. If you get an
- * error from __sync_lock* then consider upgrading your gcc.
- */
-#undef HAVE_GCC_ATOMIC_BUILTINS
-
-/* Define if you have the timespec struct */
-#undef HAVE_STRUCT_TIMESPEC
-
-/* Define if you don't have the GetProcessAffinityMask() */
-#undef NEED_PROCESS_AFFINITY_MASK
-
-/* Define if your version of Windows TLSGetValue() clears WSALastError
- * and calling SetLastError() isn't enough restore it. You'll also need to
- * link against wsock32.lib (or libwsock32.a for MinGW).
- */
-#undef RETAIN_WSALASTERROR
-
-/*
-# ----------------------------------------------------------------------
-# The library can be built with some alternative behaviour to better
-# facilitate development of applications on Win32 that will be ported
-# to other POSIX systems.
-#
-# Nothing described here will make the library non-compliant and strictly
-# compliant applications will not be affected in any way, but
-# applications that make assumptions that POSIX does not guarantee are
-# not strictly compliant and may fail or misbehave with some settings.
-#
-# PTW32_THREAD_ID_REUSE_INCREMENT
-# Purpose:
-# POSIX says that applications should assume that thread IDs can be
-# recycled. However, Solaris (and some other systems) use a [very large]
-# sequence number as the thread ID, which provides virtual uniqueness.
-# This provides a very high but finite level of safety for applications
-# that are not meticulous in tracking thread lifecycles e.g. applications
-# that call functions which target detached threads without some form of
-# thread exit synchronisation.
-#
-# Usage:
-# Set to any value in the range: 0 <= value < 2^wordsize.
-# Set to 0 to emulate reusable thread ID behaviour like Linux or *BSD.
-# Set to 1 for unique thread IDs like Solaris (this is the default).
-# Set to some factor of 2^wordsize to emulate smaller word size types
-# (i.e. will wrap sooner). This might be useful to emulate some embedded
-# systems.
-#
-# define PTW32_THREAD_ID_REUSE_INCREMENT 0
-#
-# ----------------------------------------------------------------------
- */
-#undef PTW32_THREAD_ID_REUSE_INCREMENT
-
-
-/*********************************************************************
- * Target specific groups
- *
- * If you find that these are incorrect or incomplete please report it
- * to the pthreads-win32 maintainer. Thanks.
- *********************************************************************/
-#if defined(WINCE)
-#define NEED_DUPLICATEHANDLE
-#define NEED_CREATETHREAD
-#define NEED_ERRNO
-#define NEED_CALLOC
-#define NEED_FTIME
-/* #define NEED_SEM */
-#define NEED_UNICODE_CONSTS
-#define NEED_PROCESS_AFFINITY_MASK
-/* This may not be needed */
-#define RETAIN_WSALASTERROR
-#endif
-
-#if defined(_UWIN)
-#define HAVE_MODE_T
-#define HAVE_STRUCT_TIMESPEC
-#endif
-
-#if defined(__GNUC__)
-#define HAVE_C_INLINE
-#endif
-
-#if defined(__MINGW64__)
-#define HAVE_MODE_T
-#define HAVE_STRUCT_TIMESPEC
-#elif defined(__MINGW32__)
-#define HAVE_MODE_T
-#endif
-
-#if defined(__BORLANDC__)
-#endif
-
-#if defined(__WATCOMC__)
-#endif
-
-#if defined(__DMC__)
-#define HAVE_SIGNAL_H
-#define HAVE_C_INLINE
-#endif
-
-
-
-#endif
diff --git a/pthreads/src/context.h b/pthreads/src/context.h
deleted file mode 100644
index 3d4511f..0000000
--- a/pthreads/src/context.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * context.h
- *
- * Description:
- * POSIX thread macros related to thread cancellation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef PTW32_CONTEXT_H
-#define PTW32_CONTEXT_H
-
-#undef PTW32_PROGCTR
-
-#if defined(_M_IX86) || (defined(_X86_) && !defined(__amd64__))
-#define PTW32_PROGCTR(Context) ((Context).Eip)
-#endif
-
-#if defined (_M_IA64) || defined(_IA64)
-#define PTW32_PROGCTR(Context) ((Context).StIIP)
-#endif
-
-#if defined(_MIPS_) || defined(MIPS)
-#define PTW32_PROGCTR(Context) ((Context).Fir)
-#endif
-
-#if defined(_ALPHA_)
-#define PTW32_PROGCTR(Context) ((Context).Fir)
-#endif
-
-#if defined(_PPC_)
-#define PTW32_PROGCTR(Context) ((Context).Iar)
-#endif
-
-#if defined(_AMD64_) || defined(__amd64__)
-#define PTW32_PROGCTR(Context) ((Context).Rip)
-#endif
-
-#if defined(_ARM_) || defined(ARM)
-#define PTW32_PROGCTR(Context) ((Context).Pc)
-#endif
-
-#if !defined(PTW32_PROGCTR)
-#error Module contains CPU-specific code; modify and recompile.
-#endif
-
-#endif
diff --git a/pthreads/src/create.c b/pthreads/src/create.c
deleted file mode 100644
index e154185..0000000
--- a/pthreads/src/create.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * create.c
- *
- * Description:
- * This translation unit implements routines associated with spawning a new
- * thread.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#if ! defined(_UWIN) && ! defined(WINCE)
-#include <process.h>
-#endif
-
-int
-pthread_create (pthread_t * tid,
- const pthread_attr_t * attr,
- void *(*start) (void *), void *arg)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function creates a thread running the start function,
- * passing it the parameter value, 'arg'. The 'attr'
- * argument specifies optional creation attributes.
- * The identity of the new thread is returned
- * via 'tid', which should not be NULL.
- *
- * PARAMETERS
- * tid
- * pointer to an instance of pthread_t
- *
- * attr
- * optional pointer to an instance of pthread_attr_t
- *
- * start
- * pointer to the starting routine for the new thread
- *
- * arg
- * optional parameter passed to 'start'
- *
- *
- * DESCRIPTION
- * This function creates a thread running the start function,
- * passing it the parameter value, 'arg'. The 'attr'
- * argument specifies optional creation attributes.
- * The identity of the new thread is returned
- * via 'tid', which should not be the NULL pointer.
- *
- * RESULTS
- * 0 successfully created thread,
- * EINVAL attr invalid,
- * EAGAIN insufficient resources.
- *
- * ------------------------------------------------------
- */
-{
- pthread_t thread;
- ptw32_thread_t * tp;
- register pthread_attr_t a;
- HANDLE threadH = 0;
- int result = EAGAIN;
- int run = PTW32_TRUE;
- ThreadParms *parms = NULL;
- unsigned int stackSize;
- int priority;
- pthread_t self;
-
- /*
- * Before doing anything, check that tid can be stored through
- * without invoking a memory protection error (segfault).
- * Make sure that the assignment below can't be optimised out by the compiler.
- * This is assured by conditionally assigning *tid again at the end.
- */
- tid->x = 0;
-
- if (attr != NULL)
- {
- a = *attr;
- }
- else
- {
- a = NULL;
- }
-
- if ((thread = ptw32_new ()).p == NULL)
- {
- goto FAIL0;
- }
-
- tp = (ptw32_thread_t *) thread.p;
-
- priority = tp->sched_priority;
-
- if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL)
- {
- goto FAIL0;
- }
-
- parms->tid = thread;
- parms->start = start;
- parms->arg = arg;
-
-#if defined(HAVE_SIGSET_T)
-
- /*
- * Threads inherit their initial sigmask from their creator thread.
- */
- self = pthread_self();
- tp->sigmask = ((ptw32_thread_t *)self.p)->sigmask;
-
-#endif /* HAVE_SIGSET_T */
-
-
- if (a != NULL)
- {
- stackSize = (unsigned int)a->stacksize;
- tp->detachState = a->detachstate;
- priority = a->param.sched_priority;
-
-#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
- /* WinCE */
-#else
- /* Everything else */
-
- /*
- * Thread priority must be set to a valid system level
- * without altering the value set by pthread_attr_setschedparam().
- */
-
- /*
- * PTHREAD_EXPLICIT_SCHED is the default because Win32 threads
- * don't inherit their creator's priority. They are started with
- * THREAD_PRIORITY_NORMAL (win32 value). The result of not supplying
- * an 'attr' arg to pthread_create() is equivalent to defaulting to
- * PTHREAD_EXPLICIT_SCHED and priority THREAD_PRIORITY_NORMAL.
- */
- if (PTHREAD_INHERIT_SCHED == a->inheritsched)
- {
- /*
- * If the thread that called pthread_create() is a Win32 thread
- * then the inherited priority could be the result of a temporary
- * system adjustment. This is not the case for POSIX threads.
- */
-#if ! defined(HAVE_SIGSET_T)
- self = pthread_self ();
-#endif
- priority = ((ptw32_thread_t *) self.p)->sched_priority;
- }
-
-#endif
-
- }
- else
- {
- /*
- * Default stackSize
- */
- stackSize = PTHREAD_STACK_MIN;
- }
-
- tp->state = run ? PThreadStateInitial : PThreadStateSuspended;
-
- tp->keys = NULL;
-
- /*
- * Threads must be started in suspended mode and resumed if necessary
- * after _beginthreadex returns us the handle. Otherwise we set up a
- * race condition between the creating and the created threads.
- * Note that we also retain a local copy of the handle for use
- * by us in case thread.p->threadH gets NULLed later but before we've
- * finished with it here.
- */
-
-#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
-
- tp->threadH =
- threadH =
- (HANDLE) _beginthreadex ((void *) NULL, /* No security info */
- stackSize, /* default stack size */
- ptw32_threadStart,
- parms,
- (unsigned)
- CREATE_SUSPENDED,
- (unsigned *) &(tp->thread));
-
- if (threadH != 0)
- {
- if (a != NULL)
- {
- (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority);
- }
-
- if (run)
- {
- ResumeThread (threadH);
- }
- }
-
-#else
-
- {
- ptw32_mcs_local_node_t stateLock;
-
- /*
- * This lock will force pthread_threadStart() to wait until we have
- * the thread handle and have set the priority.
- */
- ptw32_mcs_lock_acquire(&tp->stateLock, &stateLock);
-
- tp->threadH =
- threadH =
- (HANDLE) _beginthread (ptw32_threadStart, stackSize, /* default stack size */
- parms);
-
- /*
- * Make the return code match _beginthreadex's.
- */
- if (threadH == (HANDLE) - 1L)
- {
- tp->threadH = threadH = 0;
- }
- else
- {
- if (!run)
- {
- /*
- * beginthread does not allow for create flags, so we do it now.
- * Note that beginthread itself creates the thread in SUSPENDED
- * mode, and then calls ResumeThread to start it.
- */
- SuspendThread (threadH);
- }
-
- if (a != NULL)
- {
- (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority);
- }
- }
-
- ptw32_mcs_lock_release (&stateLock);
- }
-#endif
-
- result = (threadH != 0) ? 0 : EAGAIN;
-
- /*
- * Fall Through Intentionally
- */
-
- /*
- * ------------
- * Failure Code
- * ------------
- */
-
-FAIL0:
- if (result != 0)
- {
-
- ptw32_threadDestroy (thread);
- tp = NULL;
-
- if (parms != NULL)
- {
- free (parms);
- }
- }
- else
- {
- *tid = thread;
- }
-
-#if defined(_UWIN)
- if (result == 0)
- pthread_count++;
-#endif
- return (result);
-
-} /* pthread_create */
diff --git a/pthreads/src/dll.c b/pthreads/src/dll.c
deleted file mode 100644
index 05e01be..0000000
--- a/pthreads/src/dll.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * dll.c
- *
- * Description:
- * This translation unit implements DLL initialisation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if !defined(PTW32_STATIC_LIB)
-
-#include "pthread.h"
-#include "implement.h"
-
-#if defined(_MSC_VER)
-/*
- * lpvReserved yields an unreferenced formal parameter;
- * ignore it
- */
-#pragma warning( disable : 4100 )
-#endif
-
-#if defined(__cplusplus)
-/*
- * Dear c++: Please don't mangle this name. -thanks
- */
-extern "C"
-#endif /* __cplusplus */
- BOOL WINAPI
-DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
-{
- BOOL result = PTW32_TRUE;
-
- switch (fdwReason)
- {
-
- case DLL_PROCESS_ATTACH:
- result = pthread_win32_process_attach_np ();
- break;
-
- case DLL_THREAD_ATTACH:
- /*
- * A thread is being created
- */
- result = pthread_win32_thread_attach_np ();
- break;
-
- case DLL_THREAD_DETACH:
- /*
- * A thread is exiting cleanly
- */
- result = pthread_win32_thread_detach_np ();
- break;
-
- case DLL_PROCESS_DETACH:
- (void) pthread_win32_thread_detach_np ();
- result = pthread_win32_process_detach_np ();
- break;
- }
-
- return (result);
-
-} /* DllMain */
-
-#endif /* PTW32_STATIC_LIB */
diff --git a/pthreads/src/errno.c b/pthreads/src/errno.c
deleted file mode 100644
index 78aa920..0000000
--- a/pthreads/src/errno.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * errno.c
- *
- * Description:
- * This translation unit implements routines associated with spawning a new
- * thread.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if defined(NEED_ERRNO)
-
-#include "pthread.h"
-#include "implement.h"
-
-static int reallyBad = ENOMEM;
-
-/*
- * Re-entrant errno.
- *
- * Each thread has it's own errno variable in pthread_t.
- *
- * The benefit of using the pthread_t structure
- * instead of another TSD key is TSD keys are limited
- * on Win32 to 64 per process. Secondly, to implement
- * it properly without using pthread_t you'd need
- * to dynamically allocate an int on starting the thread
- * and store it manually into TLS and then ensure that you free
- * it on thread termination. We get all that for free
- * by simply storing the errno on the pthread_t structure.
- *
- * MSVC and Mingw32 already have their own thread-safe errno.
- *
- * #if defined( _REENTRANT ) || defined( _MT )
- * #define errno *_errno()
- *
- * int *_errno( void );
- * #else
- * extern int errno;
- * #endif
- *
- */
-
-int *
-_errno (void)
-{
- pthread_t self;
- int *result;
-
- if ((self = pthread_self ()).p == NULL)
- {
- /*
- * Yikes! unable to allocate a thread!
- * Throw an exception? return an error?
- */
- result = &reallyBad;
- }
- else
- {
- result = (int *)(&self.p->exitStatus);
- }
-
- return (result);
-
-} /* _errno */
-
-#endif /* (NEED_ERRNO) */
diff --git a/pthreads/src/exit.c b/pthreads/src/exit.c
deleted file mode 100644
index 94369d0..0000000
--- a/pthreads/src/exit.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * exit.c
- *
- * Description:
- * This translation unit implements routines associated with exiting from
- * a thread.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#if ! defined(_UWIN) && ! defined(WINCE)
-# include <process.h>
-#endif
-
-#include "pthread_exit.c"
diff --git a/pthreads/src/fork.c b/pthreads/src/fork.c
deleted file mode 100644
index 8a29550..0000000
--- a/pthreads/src/fork.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * fork.c
- *
- * Description:
- * Implementation of fork() for POSIX threads.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-
-#include "pthread.h"
-#include "implement.h"
diff --git a/pthreads/src/global.c b/pthreads/src/global.c
deleted file mode 100644
index f1e9b3f..0000000
--- a/pthreads/src/global.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * global.c
- *
- * Description:
- * This translation unit instantiates data associated with the implementation
- * as a whole.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int ptw32_processInitialized = PTW32_FALSE;
-ptw32_thread_t * ptw32_threadReuseTop = PTW32_THREAD_REUSE_EMPTY;
-ptw32_thread_t * ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY;
-pthread_key_t ptw32_selfThreadKey = NULL;
-pthread_key_t ptw32_cleanupKey = NULL;
-pthread_cond_t ptw32_cond_list_head = NULL;
-pthread_cond_t ptw32_cond_list_tail = NULL;
-
-int ptw32_concurrency = 0;
-
-/* What features have been auto-detected */
-int ptw32_features = 0;
-
-/*
- * Global [process wide] thread sequence Number
- */
-unsigned __int64 ptw32_threadSeqNumber = 0;
-
-/*
- * Function pointer to QueueUserAPCEx if it exists, otherwise
- * it will be set at runtime to a substitute routine which cannot unblock
- * blocked threads.
- */
-DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD) = NULL;
-
-/*
- * Global lock for managing pthread_t struct reuse.
- */
-ptw32_mcs_lock_t ptw32_thread_reuse_lock = 0;
-
-/*
- * Global lock for testing internal state of statically declared mutexes.
- */
-ptw32_mcs_lock_t ptw32_mutex_test_init_lock = 0;
-
-/*
- * Global lock for testing internal state of PTHREAD_COND_INITIALIZER
- * created condition variables.
- */
-ptw32_mcs_lock_t ptw32_cond_test_init_lock = 0;
-
-/*
- * Global lock for testing internal state of PTHREAD_RWLOCK_INITIALIZER
- * created read/write locks.
- */
-ptw32_mcs_lock_t ptw32_rwlock_test_init_lock = 0;
-
-/*
- * Global lock for testing internal state of PTHREAD_SPINLOCK_INITIALIZER
- * created spin locks.
- */
-ptw32_mcs_lock_t ptw32_spinlock_test_init_lock = 0;
-
-/*
- * Global lock for condition variable linked list. The list exists
- * to wake up CVs when a WM_TIMECHANGE message arrives. See
- * w32_TimeChangeHandler.c.
- */
-ptw32_mcs_lock_t ptw32_cond_list_lock = 0;
-
-#if defined(_UWIN)
-/*
- * Keep a count of the number of threads.
- */
-int pthread_count = 0;
-#endif
diff --git a/pthreads/src/implement.h b/pthreads/src/implement.h
deleted file mode 100644
index 6b9f425..0000000
--- a/pthreads/src/implement.h
+++ /dev/null
@@ -1,943 +0,0 @@
-/*
- * implement.h
- *
- * Definitions that don't need to be public.
- *
- * Keeps all the internals out of pthread.h
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: Ross.Johnson@homemail.com.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if !defined(_IMPLEMENT_H)
-#define _IMPLEMENT_H
-
-#if !defined(_WIN32_WINNT)
-#define _WIN32_WINNT 0x0400
-#endif
-
-#include <windows.h>
-
-/*
- * In case windows.h doesn't define it (e.g. WinCE perhaps)
- */
-#if defined(WINCE)
-typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
-#endif
-
-/*
- * note: ETIMEDOUT is correctly defined in winsock.h
- */
-#include <winsock.h>
-
-/*
- * In case ETIMEDOUT hasn't been defined above somehow.
- */
-#if !defined(ETIMEDOUT)
-# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
-#endif
-
-#if !defined(malloc)
-#include <malloc.h>
-#endif
-
-#if defined(__CLEANUP_C)
-# include <setjmp.h>
-#endif
-
-#if !defined(INT_MAX)
-#include <limits.h>
-#endif
-
-/* use local include files during development */
-#include "semaphore.h"
-#include "sched.h"
-
-#if defined(HAVE_C_INLINE) || defined(__cplusplus)
-#define INLINE inline
-#else
-#define INLINE
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER < 1300
-/*
- * MSVC 6 does not use the "volatile" qualifier
- */
-#define PTW32_INTERLOCKED_VOLATILE
-#else
-#define PTW32_INTERLOCKED_VOLATILE volatile
-#endif
-#define PTW32_INTERLOCKED_LONG long
-#define PTW32_INTERLOCKED_SIZE size_t
-#define PTW32_INTERLOCKED_PVOID PVOID
-#define PTW32_INTERLOCKED_LONGPTR PTW32_INTERLOCKED_VOLATILE long*
-#define PTW32_INTERLOCKED_SIZEPTR PTW32_INTERLOCKED_VOLATILE size_t*
-#define PTW32_INTERLOCKED_PVOID_PTR PTW32_INTERLOCKED_VOLATILE PVOID*
-
-#if defined(__MINGW64__) || defined(__MINGW32__)
-# include <stdint.h>
-#elif defined(__BORLANDC__)
-# define int64_t ULONGLONG
-#else
-# define int64_t _int64
-# if defined(_MSC_VER) && _MSC_VER < 1300
- typedef long intptr_t;
-# endif
-#endif
-
-typedef enum
-{
- /*
- * This enumeration represents the state of the thread;
- * The thread is still "alive" if the numeric value of the
- * state is greater or equal "PThreadStateRunning".
- */
- PThreadStateInitial = 0, /* Thread not running */
- PThreadStateRunning, /* Thread alive & kicking */
- PThreadStateSuspended, /* Thread alive but suspended */
- PThreadStateCancelPending, /* Thread alive but */
- /* has cancelation pending. */
- PThreadStateCanceling, /* Thread alive but is */
- /* in the process of terminating */
- /* due to a cancellation request */
- PThreadStateExiting, /* Thread alive but exiting */
- /* due to an exception */
- PThreadStateLast, /* All handlers have been run and now */
- /* final cleanup can be done. */
- PThreadStateReuse /* In reuse pool. */
-}
-PThreadState;
-
-typedef struct ptw32_mcs_node_t_ ptw32_mcs_local_node_t;
-typedef struct ptw32_mcs_node_t_* ptw32_mcs_lock_t;
-typedef struct ptw32_robust_node_t_ ptw32_robust_node_t;
-typedef struct ptw32_thread_t_ ptw32_thread_t;
-
-
-struct ptw32_thread_t_
-{
- unsigned __int64 seqNumber; /* Process-unique thread sequence number */
- HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */
- pthread_t ptHandle; /* This thread's permanent pthread_t handle */
- ptw32_thread_t * prevReuse; /* Links threads on reuse stack */
- volatile PThreadState state;
- ptw32_mcs_lock_t threadLock; /* Used for serialised access to public thread state */
- ptw32_mcs_lock_t stateLock; /* Used for async-cancel safety */
- HANDLE cancelEvent;
- void *exitStatus;
- void *parms;
- void *keys;
- void *nextAssoc;
-#if defined(__CLEANUP_C)
- jmp_buf start_mark; /* Jump buffer follows void* so should be aligned */
-#endif /* __CLEANUP_C */
-#if defined(HAVE_SIGSET_T)
- sigset_t sigmask;
-#endif /* HAVE_SIGSET_T */
- ptw32_mcs_lock_t
- robustMxListLock; /* robustMxList lock */
- ptw32_robust_node_t*
- robustMxList; /* List of currenty held robust mutexes */
- int ptErrno;
- int detachState;
- int sched_priority; /* As set, not as currently is */
- int cancelState;
- int cancelType;
- int implicit:1;
- DWORD thread; /* Win32 thread ID */
-#if defined(_UWIN)
- DWORD dummy[5];
-#endif
- size_t align; /* Force alignment if this struct is packed */
-};
-
-
-/*
- * Special value to mark attribute objects as valid.
- */
-#define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
-
-struct pthread_attr_t_
-{
- unsigned long valid;
- void *stackaddr;
- size_t stacksize;
- int detachstate;
- struct sched_param param;
- int inheritsched;
- int contentionscope;
-#if defined(HAVE_SIGSET_T)
- sigset_t sigmask;
-#endif /* HAVE_SIGSET_T */
-};
-
-
-/*
- * ====================
- * ====================
- * Semaphores, Mutexes and Condition Variables
- * ====================
- * ====================
- */
-
-struct sem_t_
-{
- int value;
- pthread_mutex_t lock;
- HANDLE sem;
-#if defined(NEED_SEM)
- int leftToUnblock;
-#endif
-};
-
-#define PTW32_OBJECT_AUTO_INIT ((void *)(size_t) -1)
-#define PTW32_OBJECT_INVALID NULL
-
-struct pthread_mutex_t_
-{
- LONG lock_idx; /* Provides exclusive access to mutex state
- via the Interlocked* mechanism.
- 0: unlocked/free.
- 1: locked - no other waiters.
- -1: locked - with possible other waiters.
- */
- int recursive_count; /* Number of unlocks a thread needs to perform
- before the lock is released (recursive
- mutexes only). */
- int kind; /* Mutex type. */
- pthread_t ownerThread;
- HANDLE event; /* Mutex release notification to waiting
- threads. */
- ptw32_robust_node_t*
- robustNode; /* Extra state for robust mutexes */
-};
-
-enum ptw32_robust_state_t_
-{
- PTW32_ROBUST_CONSISTENT,
- PTW32_ROBUST_INCONSISTENT,
- PTW32_ROBUST_NOTRECOVERABLE
-};
-
-typedef enum ptw32_robust_state_t_ ptw32_robust_state_t;
-
-/*
- * Node used to manage per-thread lists of currently-held robust mutexes.
- */
-struct ptw32_robust_node_t_
-{
- pthread_mutex_t mx;
- ptw32_robust_state_t stateInconsistent;
- ptw32_robust_node_t* prev;
- ptw32_robust_node_t* next;
-};
-
-struct pthread_mutexattr_t_
-{
- int pshared;
- int kind;
- int robustness;
-};
-
-/*
- * Possible values, other than PTW32_OBJECT_INVALID,
- * for the "interlock" element in a spinlock.
- *
- * In this implementation, when a spinlock is initialised,
- * the number of cpus available to the process is checked.
- * If there is only one cpu then "interlock" is set equal to
- * PTW32_SPIN_USE_MUTEX and u.mutex is an initialised mutex.
- * If the number of cpus is greater than 1 then "interlock"
- * is set equal to PTW32_SPIN_UNLOCKED and the number is
- * stored in u.cpus. This arrangement allows the spinlock
- * routines to attempt an InterlockedCompareExchange on "interlock"
- * immediately and, if that fails, to try the inferior mutex.
- *
- * "u.cpus" isn't used for anything yet, but could be used at
- * some point to optimise spinlock behaviour.
- */
-#define PTW32_SPIN_INVALID (0)
-#define PTW32_SPIN_UNLOCKED (1)
-#define PTW32_SPIN_LOCKED (2)
-#define PTW32_SPIN_USE_MUTEX (3)
-
-struct pthread_spinlock_t_
-{
- long interlock; /* Locking element for multi-cpus. */
- union
- {
- int cpus; /* No. of cpus if multi cpus, or */
- pthread_mutex_t mutex; /* mutex if single cpu. */
- } u;
-};
-
-/*
- * MCS lock queue node - see ptw32_MCS_lock.c
- */
-struct ptw32_mcs_node_t_
-{
- struct ptw32_mcs_node_t_ **lock; /* ptr to tail of queue */
- struct ptw32_mcs_node_t_ *next; /* ptr to successor in queue */
- HANDLE readyFlag; /* set after lock is released by
- predecessor */
- HANDLE nextFlag; /* set after 'next' ptr is set by
- successor */
-};
-
-
-struct pthread_barrier_t_
-{
- unsigned int nCurrentBarrierHeight;
- unsigned int nInitialBarrierHeight;
- int pshared;
- sem_t semBarrierBreeched;
- ptw32_mcs_lock_t lock;
- ptw32_mcs_local_node_t proxynode;
-};
-
-struct pthread_barrierattr_t_
-{
- int pshared;
-};
-
-struct pthread_key_t_
-{
- DWORD key;
- void (*destructor) (void *);
- ptw32_mcs_lock_t keyLock;
- void *threads;
-};
-
-
-typedef struct ThreadParms ThreadParms;
-
-struct ThreadParms
-{
- pthread_t tid;
- void *(*start) (void *);
- void *arg;
-};
-
-
-struct pthread_cond_t_
-{
- long nWaitersBlocked; /* Number of threads blocked */
- long nWaitersGone; /* Number of threads timed out */
- long nWaitersToUnblock; /* Number of threads to unblock */
- sem_t semBlockQueue; /* Queue up threads waiting for the */
- /* condition to become signalled */
- sem_t semBlockLock; /* Semaphore that guards access to */
- /* | waiters blocked count/block queue */
- /* +-> Mandatory Sync.LEVEL-1 */
- pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
- /* | waiters (to)unblock(ed) counts */
- /* +-> Optional* Sync.LEVEL-2 */
- pthread_cond_t next; /* Doubly linked list */
- pthread_cond_t prev;
-};
-
-
-struct pthread_condattr_t_
-{
- int pshared;
-};
-
-#define PTW32_RWLOCK_MAGIC 0xfacade2
-
-struct pthread_rwlock_t_
-{
- pthread_mutex_t mtxExclusiveAccess;
- pthread_mutex_t mtxSharedAccessCompleted;
- pthread_cond_t cndSharedAccessCompleted;
- int nSharedAccessCount;
- int nExclusiveAccessCount;
- int nCompletedSharedAccessCount;
- int nMagic;
-};
-
-struct pthread_rwlockattr_t_
-{
- int pshared;
-};
-
-typedef struct ThreadKeyAssoc ThreadKeyAssoc;
-
-struct ThreadKeyAssoc
-{
- /*
- * Purpose:
- * This structure creates an association between a thread and a key.
- * It is used to implement the implicit invocation of a user defined
- * destroy routine for thread specific data registered by a user upon
- * exiting a thread.
- *
- * Graphically, the arrangement is as follows, where:
- *
- * K - Key with destructor
- * (head of chain is key->threads)
- * T - Thread that has called pthread_setspecific(Kn)
- * (head of chain is thread->keys)
- * A - Association. Each association is a node at the
- * intersection of two doubly-linked lists.
- *
- * T1 T2 T3
- * | | |
- * | | |
- * K1 -----+-----A-----A----->
- * | | |
- * | | |
- * K2 -----A-----A-----+----->
- * | | |
- * | | |
- * K3 -----A-----+-----A----->
- * | | |
- * | | |
- * V V V
- *
- * Access to the association is guarded by two locks: the key's
- * general lock (guarding the row) and the thread's general
- * lock (guarding the column). This avoids the need for a
- * dedicated lock for each association, which not only consumes
- * more handles but requires that the lock resources persist
- * until both the key is deleted and the thread has called the
- * destructor. The two-lock arrangement allows those resources
- * to be freed as soon as either thread or key is concluded.
- *
- * To avoid deadlock, whenever both locks are required both the
- * key and thread locks are acquired consistently in the order
- * "key lock then thread lock". An exception to this exists
- * when a thread calls the destructors, however, this is done
- * carefully (but inelegantly) to avoid deadlock.
- *
- * An association is created when a thread first calls
- * pthread_setspecific() on a key that has a specified
- * destructor.
- *
- * An association is destroyed either immediately after the
- * thread calls the key destructor function on thread exit, or
- * when the key is deleted.
- *
- * Attributes:
- * thread
- * reference to the thread that owns the
- * association. This is actually the pointer to the
- * thread struct itself. Since the association is
- * destroyed before the thread exits, this can never
- * point to a different logical thread to the one that
- * created the assoc, i.e. after thread struct reuse.
- *
- * key
- * reference to the key that owns the association.
- *
- * nextKey
- * The pthread_t->keys attribute is the head of a
- * chain of associations that runs through the nextKey
- * link. This chain provides the 1 to many relationship
- * between a pthread_t and all pthread_key_t on which
- * it called pthread_setspecific.
- *
- * prevKey
- * Similarly.
- *
- * nextThread
- * The pthread_key_t->threads attribute is the head of
- * a chain of associations that runs through the
- * nextThreads link. This chain provides the 1 to many
- * relationship between a pthread_key_t and all the
- * PThreads that have called pthread_setspecific for
- * this pthread_key_t.
- *
- * prevThread
- * Similarly.
- *
- * Notes:
- * 1) As soon as either the key or the thread is no longer
- * referencing the association, it can be destroyed. The
- * association will be removed from both chains.
- *
- * 2) Under WIN32, an association is only created by
- * pthread_setspecific if the user provided a
- * destroyRoutine when they created the key.
- *
- *
- */
- ptw32_thread_t * thread;
- pthread_key_t key;
- ThreadKeyAssoc *nextKey;
- ThreadKeyAssoc *nextThread;
- ThreadKeyAssoc *prevKey;
- ThreadKeyAssoc *prevThread;
-};
-
-
-#if defined(__CLEANUP_SEH)
-/*
- * --------------------------------------------------------------
- * MAKE_SOFTWARE_EXCEPTION
- * This macro constructs a software exception code following
- * the same format as the standard Win32 error codes as defined
- * in WINERROR.H
- * Values are 32 bit values laid out as follows:
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +---+-+-+-----------------------+-------------------------------+
- * |Sev|C|R| Facility | Code |
- * +---+-+-+-----------------------+-------------------------------+
- *
- * Severity Values:
- */
-#define SE_SUCCESS 0x00
-#define SE_INFORMATION 0x01
-#define SE_WARNING 0x02
-#define SE_ERROR 0x03
-
-#define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
-( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \
- ( 1 << 29 ) | /* MS=0, User=1 */ \
- ( 0 << 28 ) | /* Reserved */ \
- ( (_facility) << 16 ) | /* Facility Code */ \
- ( (_exception) << 0 ) /* Exception Code */ \
- ) )
-
-/*
- * We choose one specific Facility/Error code combination to
- * identify our software exceptions vs. WIN32 exceptions.
- * We store our actual component and error code within
- * the optional information array.
- */
-#define EXCEPTION_PTW32_SERVICES \
- MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
- PTW32_SERVICES_FACILITY, \
- PTW32_SERVICES_ERROR )
-
-#define PTW32_SERVICES_FACILITY 0xBAD
-#define PTW32_SERVICES_ERROR 0xDEED
-
-#endif /* __CLEANUP_SEH */
-
-/*
- * Services available through EXCEPTION_PTW32_SERVICES
- * and also used [as parameters to ptw32_throw()] as
- * generic exception selectors.
- */
-
-#define PTW32_EPS_EXIT (1)
-#define PTW32_EPS_CANCEL (2)
-
-
-/* Useful macros */
-#define PTW32_MAX(a,b) ((a)<(b)?(b):(a))
-#define PTW32_MIN(a,b) ((a)>(b)?(b):(a))
-
-
-/* Declared in pthread_cancel.c */
-extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD);
-
-/* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
-#define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *)(size_t) 1)
-
-extern int ptw32_processInitialized;
-extern ptw32_thread_t * ptw32_threadReuseTop;
-extern ptw32_thread_t * ptw32_threadReuseBottom;
-extern pthread_key_t ptw32_selfThreadKey;
-extern pthread_key_t ptw32_cleanupKey;
-extern pthread_cond_t ptw32_cond_list_head;
-extern pthread_cond_t ptw32_cond_list_tail;
-
-extern int ptw32_mutex_default_kind;
-
-extern unsigned __int64 ptw32_threadSeqNumber;
-
-extern int ptw32_concurrency;
-
-extern int ptw32_features;
-
-extern ptw32_mcs_lock_t ptw32_thread_reuse_lock;
-extern ptw32_mcs_lock_t ptw32_mutex_test_init_lock;
-extern ptw32_mcs_lock_t ptw32_cond_list_lock;
-extern ptw32_mcs_lock_t ptw32_cond_test_init_lock;
-extern ptw32_mcs_lock_t ptw32_rwlock_test_init_lock;
-extern ptw32_mcs_lock_t ptw32_spinlock_test_init_lock;
-
-#if defined(_UWIN)
-extern int pthread_count;
-#endif
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif /* __cplusplus */
-
-/*
- * =====================
- * =====================
- * Forward Declarations
- * =====================
- * =====================
- */
-
- int ptw32_is_attr (const pthread_attr_t * attr);
-
- int ptw32_cond_check_need_init (pthread_cond_t * cond);
- int ptw32_mutex_check_need_init (pthread_mutex_t * mutex);
- int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock);
-
- int ptw32_robust_mutex_inherit(pthread_mutex_t * mutex);
- void ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self);
- void ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp);
-
- DWORD
- ptw32_RegisterCancelation (PAPCFUNC callback,
- HANDLE threadH, DWORD callback_arg);
-
- int ptw32_processInitialize (void);
-
- void ptw32_processTerminate (void);
-
- void ptw32_threadDestroy (pthread_t tid);
-
- void ptw32_pop_cleanup_all (int execute);
-
- pthread_t ptw32_new (void);
-
- pthread_t ptw32_threadReusePop (void);
-
- void ptw32_threadReusePush (pthread_t thread);
-
- int ptw32_getprocessors (int *count);
-
- int ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
-
- void ptw32_rwlock_cancelwrwait (void *arg);
-
-#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || (defined(__MSVCRT__) && ! defined(__DMC__))
- unsigned __stdcall
-#else
- void
-#endif
- ptw32_threadStart (void *vthreadParms);
-
- void ptw32_callUserDestroyRoutines (pthread_t thread);
-
- int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key);
-
- void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
-
- int ptw32_semwait (sem_t * sem);
-
- DWORD ptw32_relmillisecs (const struct timespec * abstime);
-
- void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
-
- int ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
-
- void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node);
-
- void ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node);
-
-#if defined(NEED_FTIME)
- void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
- void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
-#endif
-
-/* Declared in misc.c */
-#if defined(NEED_CALLOC)
-#define calloc(n, s) ptw32_calloc(n, s)
- void *ptw32_calloc (size_t n, size_t s);
-#endif
-
-/* Declared in private.c */
-#if defined(_MSC_VER)
-/*
- * Ignore the warning:
- * "C++ exception specification ignored except to indicate that
- * the function is not __declspec(nothrow)."
- */
-#pragma warning(disable:4290)
-#endif
- void ptw32_throw (DWORD exception)
-#if defined(__CLEANUP_CXX)
- throw(ptw32_exception_cancel,ptw32_exception_exit)
-#endif
-;
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-
-#if defined(_UWIN_)
-# if defined(_MT)
-# if defined(__cplusplus)
-extern "C"
-{
-# endif
- _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
- unsigned, void *);
- _CRTIMP void __cdecl _endthread (void);
- _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
- unsigned (__stdcall *) (void *),
- void *, unsigned, unsigned *);
- _CRTIMP void __cdecl _endthreadex (unsigned);
-# if defined(__cplusplus)
-}
-# endif
-# endif
-#else
-# include <process.h>
-# endif
-
-
-/*
- * Use intrinsic versions wherever possible. VC will do this
- * automatically where possible and GCC define these if available:
- * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
- * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
- * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
- * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
- * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
- *
- * The full set of Interlocked intrinsics in GCC are (check versions):
- * type __sync_fetch_and_add (type *ptr, type value, ...)
- * type __sync_fetch_and_sub (type *ptr, type value, ...)
- * type __sync_fetch_and_or (type *ptr, type value, ...)
- * type __sync_fetch_and_and (type *ptr, type value, ...)
- * type __sync_fetch_and_xor (type *ptr, type value, ...)
- * type __sync_fetch_and_nand (type *ptr, type value, ...)
- * type __sync_add_and_fetch (type *ptr, type value, ...)
- * type __sync_sub_and_fetch (type *ptr, type value, ...)
- * type __sync_or_and_fetch (type *ptr, type value, ...)
- * type __sync_and_and_fetch (type *ptr, type value, ...)
- * type __sync_xor_and_fetch (type *ptr, type value, ...)
- * type __sync_nand_and_fetch (type *ptr, type value, ...)
- * bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
- * type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
- * __sync_synchronize (...) // Full memory barrier
- * type __sync_lock_test_and_set (type *ptr, type value, ...) // Acquire barrier
- * void __sync_lock_release (type *ptr, ...) // Release barrier
- *
- * These are all overloaded and take 1,2,4,8 byte scalar or pointer types.
- *
- * The above aren't available in Mingw32 as of gcc 4.5.2 so define our own.
- */
-#if defined(__GNUC__)
-# if defined(_WIN64)
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(location, value, comparand) \
- ({ \
- __typeof (value) _result; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "cmpxchgq %2,(%1)" \
- :"=a" (_result) \
- :"r" (location), "r" (value), "a" (comparand) \
- :"memory", "cc"); \
- _result; \
- })
-# define PTW32_INTERLOCKED_EXCHANGE_64(location, value) \
- ({ \
- __typeof (value) _result; \
- __asm__ __volatile__ \
- ( \
- "xchgq %0,(%1)" \
- :"=r" (_result) \
- :"r" (location), "0" (value) \
- :"memory", "cc"); \
- _result; \
- })
-# define PTW32_INTERLOCKED_EXCHANGE_ADD_64(location, value) \
- ({ \
- __typeof (value) _result; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "xaddq %0,(%1)" \
- :"=r" (_result) \
- :"r" (location), "0" (value) \
- :"memory", "cc"); \
- _result; \
- })
-# define PTW32_INTERLOCKED_INCREMENT_64(location) \
- ({ \
- PTW32_INTERLOCKED_LONG _temp = 1; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "xaddq %0,(%1)" \
- :"+r" (_temp) \
- :"r" (location) \
- :"memory", "cc"); \
- ++_temp; \
- })
-# define PTW32_INTERLOCKED_DECREMENT_64(location) \
- ({ \
- PTW32_INTERLOCKED_LONG _temp = -1; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "xaddq %2,(%1)" \
- :"+r" (_temp) \
- :"r" (location) \
- :"memory", "cc"); \
- --_temp; \
- })
-#endif
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
- ({ \
- __typeof (value) _result; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "cmpxchgl %2,(%1)" \
- :"=a" (_result) \
- :"r" (location), "r" (value), "a" (comparand) \
- :"memory", "cc"); \
- _result; \
- })
-# define PTW32_INTERLOCKED_EXCHANGE_LONG(location, value) \
- ({ \
- __typeof (value) _result; \
- __asm__ __volatile__ \
- ( \
- "xchgl %0,(%1)" \
- :"=r" (_result) \
- :"r" (location), "0" (value) \
- :"memory", "cc"); \
- _result; \
- })
-# define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(location, value) \
- ({ \
- __typeof (value) _result; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "xaddl %0,(%1)" \
- :"=r" (_result) \
- :"r" (location), "0" (value) \
- :"memory", "cc"); \
- _result; \
- })
-# define PTW32_INTERLOCKED_INCREMENT_LONG(location) \
- ({ \
- PTW32_INTERLOCKED_LONG _temp = 1; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "xaddl %0,(%1)" \
- :"+r" (_temp) \
- :"r" (location) \
- :"memory", "cc"); \
- ++_temp; \
- })
-# define PTW32_INTERLOCKED_DECREMENT_LONG(location) \
- ({ \
- PTW32_INTERLOCKED_LONG _temp = -1; \
- __asm__ __volatile__ \
- ( \
- "lock\n\t" \
- "xaddl %0,(%1)" \
- :"+r" (_temp) \
- :"r" (location) \
- :"memory", "cc"); \
- --_temp; \
- })
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(location, value, comparand) \
- PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \
- (PTW32_INTERLOCKED_SIZE)value, \
- (PTW32_INTERLOCKED_SIZE)comparand)
-# define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
- PTW32_INTERLOCKED_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \
- (PTW32_INTERLOCKED_SIZE)value)
-#else
-# if defined(_WIN64)
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64 InterlockedCompareExchange64
-# define PTW32_INTERLOCKED_EXCHANGE_64 InterlockedExchange64
-# define PTW32_INTERLOCKED_EXCHANGE_ADD_64 InterlockedExchangeAdd64
-# define PTW32_INTERLOCKED_INCREMENT_64 InterlockedIncrement64
-# define PTW32_INTERLOCKED_DECREMENT_64 InterlockedDecrement64
-# endif
-# if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
- ((LONG)InterlockedCompareExchange((PVOID *)(location), (PVOID)(value), (PVOID)(comparand)))
-# else
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG InterlockedCompareExchange
-# endif
-# define PTW32_INTERLOCKED_EXCHANGE_LONG InterlockedExchange
-# define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG InterlockedExchangeAdd
-# define PTW32_INTERLOCKED_INCREMENT_LONG InterlockedIncrement
-# define PTW32_INTERLOCKED_DECREMENT_LONG InterlockedDecrement
-# if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchange
-# define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
- ((PVOID)InterlockedExchange((LPLONG)(location), (LONG)(value)))
-# else
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchangePointer
-# define PTW32_INTERLOCKED_EXCHANGE_PTR InterlockedExchangePointer
-# endif
-#endif
-#if defined(_WIN64)
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_64
-# define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_64
-# define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_64
-# define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_64
-# define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_64
-#else
-# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG
-# define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_LONG
-# define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_LONG
-# define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_LONG
-# define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_LONG
-#endif
-
-#if defined(NEED_CREATETHREAD)
-
-/*
- * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
- * in order to avoid warnings because of return type
- */
-
-#define _beginthreadex(security, \
- stack_size, \
- start_proc, \
- arg, \
- flags, \
- pid) \
- CreateThread(security, \
- stack_size, \
- (LPTHREAD_START_ROUTINE) start_proc, \
- arg, \
- flags, \
- pid)
-
-#define _endthreadex ExitThread
-
-#endif /* NEED_CREATETHREAD */
-
-
-#endif /* _IMPLEMENT_H */
diff --git a/pthreads/src/misc.c b/pthreads/src/misc.c
deleted file mode 100644
index 9c2e6c5..0000000
--- a/pthreads/src/misc.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * misc.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#include "pthread_kill.c"
-#include "pthread_once.c"
-#include "pthread_self.c"
-#include "pthread_equal.c"
-#include "pthread_setconcurrency.c"
-#include "pthread_getconcurrency.c"
-#include "ptw32_new.c"
-#include "ptw32_calloc.c"
-#include "ptw32_MCS_lock.c"
-#include "ptw32_relmillisecs.c"
-#include "ptw32_reuse.c"
-#include "w32_CancelableWait.c"
diff --git a/pthreads/src/mutex.c b/pthreads/src/mutex.c
deleted file mode 100644
index c2b3607..0000000
--- a/pthreads/src/mutex.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * mutex.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if ! defined(_UWIN) && ! defined(WINCE)
-# include <process.h>
-#endif
-#if !defined(NEED_FTIME)
-#include <sys/timeb.h>
-#endif
-#include "pthread.h"
-#include "implement.h"
-
-
-#include "ptw32_mutex_check_need_init.c"
-#include "pthread_mutex_init.c"
-#include "pthread_mutex_destroy.c"
-#include "pthread_mutexattr_init.c"
-#include "pthread_mutexattr_destroy.c"
-#include "pthread_mutexattr_getpshared.c"
-#include "pthread_mutexattr_setpshared.c"
-#include "pthread_mutexattr_settype.c"
-#include "pthread_mutexattr_gettype.c"
-#include "pthread_mutexattr_setrobust.c"
-#include "pthread_mutexattr_getrobust.c"
-#include "pthread_mutex_lock.c"
-#include "pthread_mutex_timedlock.c"
-#include "pthread_mutex_unlock.c"
-#include "pthread_mutex_trylock.c"
-#include "pthread_mutex_consistent.c"
diff --git a/pthreads/src/need_errno.h b/pthreads/src/need_errno.h
deleted file mode 100644
index abf1c95..0000000
--- a/pthreads/src/need_errno.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/***
-* errno.h - system wide error numbers (set by system calls)
-*
-* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
-*
-* Purpose:
-* This file defines the system-wide error numbers (set by
-* system calls). Conforms to the XENIX standard. Extended
-* for compatibility with Uniforum standard.
-* [System V]
-*
-* [Public]
-*
-****/
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#if !defined(_INC_ERRNO)
-#define _INC_ERRNO
-
-#if !defined(_WIN32)
-#error ERROR: Only Win32 targets supported!
-#endif
-
-#include <winsock.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-
-/* Define _CRTIMP */
-
-#ifndef _CRTIMP
-#if defined(_DLL)
-#define _CRTIMP __declspec(dllimport)
-#else /* ndef _DLL */
-#define _CRTIMP
-#endif /* _DLL */
-#endif /* _CRTIMP */
-
-
-/* Define __cdecl for non-Microsoft compilers */
-
-#if ( !defined(_MSC_VER) && !defined(__cdecl) )
-#define __cdecl
-#endif
-
-/* Define _CRTAPI1 (for compatibility with the NT SDK) */
-
-#if !defined(_CRTAPI1)
-#if _MSC_VER >= 800 && _M_IX86 >= 300
-#define _CRTAPI1 __cdecl
-#else
-#define _CRTAPI1
-#endif
-#endif
-
-#if !defined(PTW32_STATIC_LIB)
-# if defined(PTW32_BUILD)
-# define PTW32_DLLPORT __declspec (dllexport)
-# else
-# define PTW32_DLLPORT __declspec (dllimport)
-# endif
-#else
-# define PTW32_DLLPORT
-#endif
-
-/* declare reference to errno */
-
-#if (defined(_MT) || defined(_MD) || defined(_DLL)) && !defined(_MAC)
-PTW32_DLLPORT int * __cdecl _errno(void);
-#define errno (*_errno())
-#else /* ndef _MT && ndef _MD && ndef _DLL */
-_CRTIMP extern int errno;
-#endif /* _MT || _MD || _DLL */
-
-/* Error Codes */
-
-#define EPERM 1
-#define ENOENT 2
-#define ESRCH 3
-#define EINTR 4
-#define EIO 5
-#define ENXIO 6
-#define E2BIG 7
-#define ENOEXEC 8
-#define EBADF 9
-#define ECHILD 10
-#define EAGAIN 11
-#define ENOMEM 12
-#define EACCES 13
-#define EFAULT 14
-#define EBUSY 16
-#define EEXIST 17
-#define EXDEV 18
-#define ENODEV 19
-#define ENOTDIR 20
-#define EISDIR 21
-#define EINVAL 22
-#define ENFILE 23
-#define EMFILE 24
-#define ENOTTY 25
-#define EFBIG 27
-#define ENOSPC 28
-#define ESPIPE 29
-#define EROFS 30
-#define EMLINK 31
-#define EPIPE 32
-#define EDOM 33
-#define ERANGE 34
-#define EDEADLK 36
-
-/* defined differently in winsock.h on WinCE */
-#if !defined(ENAMETOOLONG)
-#define ENAMETOOLONG 38
-#endif
-
-#define ENOLCK 39
-#define ENOSYS 40
-
-/* defined differently in winsock.h on WinCE */
-#if !defined(ENOTEMPTY)
-#define ENOTEMPTY 41
-#endif
-
-#define EILSEQ 42
-
-/* POSIX 2008 - robust mutexes */
-#define EOWNERDEAD 43
-#define ENOTRECOVERABLE 44
-
-/*
- * Support EDEADLOCK for compatibiity with older MS-C versions.
- */
-#define EDEADLOCK EDEADLK
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* _INC_ERRNO */
diff --git a/pthreads/src/nonportable.c b/pthreads/src/nonportable.c
deleted file mode 100644
index 742cb96..0000000
--- a/pthreads/src/nonportable.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * nonportable.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#include "pthread_mutexattr_setkind_np.c"
-#include "pthread_mutexattr_getkind_np.c"
-#include "pthread_getw32threadhandle_np.c"
-#include "pthread_getunique_np.c"
-#include "pthread_delay_np.c"
-#include "pthread_num_processors_np.c"
-#include "pthread_win32_attach_detach_np.c"
-#include "pthread_timechange_handler_np.c"
diff --git a/pthreads/src/private.c b/pthreads/src/private.c
deleted file mode 100644
index a16b776..0000000
--- a/pthreads/src/private.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * private.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#include "ptw32_is_attr.c"
-#include "ptw32_processInitialize.c"
-#include "ptw32_processTerminate.c"
-#include "ptw32_threadStart.c"
-#include "ptw32_threadDestroy.c"
-#include "ptw32_tkAssocCreate.c"
-#include "ptw32_tkAssocDestroy.c"
-#include "ptw32_callUserDestroyRoutines.c"
-#include "ptw32_semwait.c"
-#include "ptw32_timespec.c"
-#include "ptw32_throw.c"
-#include "ptw32_getprocessors.c"
diff --git a/pthreads/src/pthread.c b/pthreads/src/pthread.c
deleted file mode 100644
index 60b5341..0000000
--- a/pthreads/src/pthread.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * pthread.c
- *
- * Description:
- * This translation unit agregates pthreads-win32 translation units.
- * It is used for inline optimisation of the library,
- * maximising for speed at the expense of size.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/* The following are ordered for inlining */
-
-#include "private.c"
-#include "attr.c"
-#include "barrier.c"
-#include "cancel.c"
-#include "cleanup.c"
-#include "condvar.c"
-#include "create.c"
-#include "dll.c"
-#include "autostatic.c"
-#include "errno.c"
-#include "exit.c"
-#include "fork.c"
-#include "global.c"
-#include "misc.c"
-#include "mutex.c"
-#include "nonportable.c"
-#include "rwlock.c"
-#include "sched.c"
-#include "semaphore.c"
-#include "signal.c"
-#include "spin.c"
-#include "sync.c"
-#include "tsd.c"
diff --git a/pthreads/src/pthread.h b/pthreads/src/pthread.h
deleted file mode 100644
index 9a19788..0000000
--- a/pthreads/src/pthread.h
+++ /dev/null
@@ -1,1368 +0,0 @@
-/* This is an implementation of the threads API of POSIX 1003.1-2001.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if !defined( PTHREAD_H )
-#define PTHREAD_H
-
-/*
- * See the README file for an explanation of the pthreads-win32 version
- * numbering scheme and how the DLL is named etc.
- */
-#define PTW32_VERSION 2,9,0,0
-#define PTW32_VERSION_STRING "2, 9, 0, 0\0"
-
-/* There are three implementations of cancel cleanup.
- * Note that pthread.h is included in both application
- * compilation units and also internally for the library.
- * The code here and within the library aims to work
- * for all reasonable combinations of environments.
- *
- * The three implementations are:
- *
- * WIN32 SEH
- * C
- * C++
- *
- * Please note that exiting a push/pop block via
- * "return", "exit", "break", or "continue" will
- * lead to different behaviour amongst applications
- * depending upon whether the library was built
- * using SEH, C++, or C. For example, a library built
- * with SEH will call the cleanup routine, while both
- * C++ and C built versions will not.
- */
-
-/*
- * Define defaults for cleanup code.
- * Note: Unless the build explicitly defines one of the following, then
- * we default to standard C style cleanup. This style uses setjmp/longjmp
- * in the cancelation and thread exit implementations and therefore won't
- * do stack unwinding if linked to applications that have it (e.g.
- * C++ apps). This is currently consistent with most/all commercial Unix
- * POSIX threads implementations.
- */
-#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
-# define __CLEANUP_C
-#endif
-
-#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
-#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
-#endif
-
-/*
- * Stop here if we are being included by the resource compiler.
- */
-#if !defined(RC_INVOKED)
-
-#undef PTW32_LEVEL
-
-#if defined(_POSIX_SOURCE)
-#define PTW32_LEVEL 0
-/* Early POSIX */
-#endif
-
-#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
-#undef PTW32_LEVEL
-#define PTW32_LEVEL 1
-/* Include 1b, 1c and 1d */
-#endif
-
-#if defined(INCLUDE_NP)
-#undef PTW32_LEVEL
-#define PTW32_LEVEL 2
-/* Include Non-Portable extensions */
-#endif
-
-#define PTW32_LEVEL_MAX 3
-
-#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL)
-#define PTW32_LEVEL PTW32_LEVEL_MAX
-/* Include everything */
-#endif
-
-#if defined(_UWIN)
-# define HAVE_STRUCT_TIMESPEC 1
-# define HAVE_SIGNAL_H 1
-# undef HAVE_PTW32_CONFIG_H
-# pragma comment(lib, "pthread")
-#endif
-
-/*
- * -------------------------------------------------------------
- *
- *
- * Module: pthread.h
- *
- * Purpose:
- * Provides an implementation of PThreads based upon the
- * standard:
- *
- * POSIX 1003.1-2001
- * and
- * The Single Unix Specification version 3
- *
- * (these two are equivalent)
- *
- * in order to enhance code portability between Windows,
- * various commercial Unix implementations, and Linux.
- *
- * See the ANNOUNCE file for a full list of conforming
- * routines and defined constants, and a list of missing
- * routines and constants not defined in this implementation.
- *
- * Authors:
- * There have been many contributors to this library.
- * The initial implementation was contributed by
- * John Bossom, and several others have provided major
- * sections or revisions of parts of the implementation.
- * Often significant effort has been contributed to
- * find and fix important bugs and other problems to
- * improve the reliability of the library, which sometimes
- * is not reflected in the amount of code which changed as
- * result.
- * As much as possible, the contributors are acknowledged
- * in the ChangeLog file in the source code distribution
- * where their changes are noted in detail.
- *
- * Contributors are listed in the CONTRIBUTORS file.
- *
- * As usual, all bouquets go to the contributors, and all
- * brickbats go to the project maintainer.
- *
- * Maintainer:
- * The code base for this project is coordinated and
- * eventually pre-tested, packaged, and made available by
- *
- * Ross Johnson <rpj@callisto.canberra.edu.au>
- *
- * QA Testers:
- * Ultimately, the library is tested in the real world by
- * a host of competent and demanding scientists and
- * engineers who report bugs and/or provide solutions
- * which are then fixed or incorporated into subsequent
- * versions of the library. Each time a bug is fixed, a
- * test case is written to prove the fix and ensure
- * that later changes to the code don't reintroduce the
- * same error. The number of test cases is slowly growing
- * and therefore so is the code reliability.
- *
- * Compliance:
- * See the file ANNOUNCE for the list of implemented
- * and not-implemented routines and defined options.
- * Of course, these are all defined is this file as well.
- *
- * Web site:
- * The source code and other information about this library
- * are available from
- *
- * http://sources.redhat.com/pthreads-win32/
- *
- * -------------------------------------------------------------
- */
-
-/* Try to avoid including windows.h */
-#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus)
-#define PTW32_INCLUDE_WINDOWS_H
-#endif
-
-#if defined(PTW32_INCLUDE_WINDOWS_H)
-#include <windows.h>
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
-/*
- * VC++6.0 or early compiler's header has no DWORD_PTR type.
- */
-typedef unsigned long DWORD_PTR;
-typedef unsigned long ULONG_PTR;
-#endif
-/*
- * -----------------
- * autoconf switches
- * -----------------
- */
-
-#if defined(HAVE_PTW32_CONFIG_H)
-#include "config.h"
-#endif /* HAVE_PTW32_CONFIG_H */
-
-#if !defined(NEED_FTIME)
-#include <time.h>
-#else /* NEED_FTIME */
-/* use native WIN32 time API */
-#endif /* NEED_FTIME */
-
-#if defined(HAVE_SIGNAL_H)
-#include <signal.h>
-#endif /* HAVE_SIGNAL_H */
-
-#include <limits.h>
-
-/*
- * Boolean values to make us independent of system includes.
- */
-enum {
- PTW32_FALSE = 0,
- PTW32_TRUE = (! PTW32_FALSE)
-};
-
-/*
- * This is a duplicate of what is in the autoconf config.h,
- * which is only used when building the pthread-win32 libraries.
- */
-
-#if !defined(PTW32_CONFIG_H)
-# if defined(WINCE)
-# define NEED_ERRNO
-# define NEED_SEM
-# endif
-# if defined(__MINGW64__)
-# define HAVE_STRUCT_TIMESPEC
-# define HAVE_MODE_T
-# elif defined(_UWIN) || defined(__MINGW32__)
-# define HAVE_MODE_T
-# endif
-#endif
-
-/*
- *
- */
-
-#if PTW32_LEVEL >= PTW32_LEVEL_MAX
-#if defined(NEED_ERRNO)
-#include "need_errno.h"
-#else
-#include <errno.h>
-#endif
-#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
-
-/*
- * Several systems don't define some error numbers.
- */
-#if !defined(ENOTSUP)
-# define ENOTSUP 48 /* This is the value in Solaris. */
-#endif
-
-#if !defined(ETIMEDOUT)
-# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */
-#endif
-
-#if !defined(ENOSYS)
-# define ENOSYS 140 /* Semi-arbitrary value */
-#endif
-
-#if !defined(EDEADLK)
-# if defined(EDEADLOCK)
-# define EDEADLK EDEADLOCK
-# else
-# define EDEADLK 36 /* This is the value in MSVC. */
-# endif
-#endif
-
-/* POSIX 2008 - related to robust mutexes */
-#if !defined(EOWNERDEAD)
-# define EOWNERDEAD 43
-#endif
-#if !defined(ENOTRECOVERABLE)
-# define ENOTRECOVERABLE 44
-#endif
-
-#include <sched.h>
-
-/*
- * To avoid including windows.h we define only those things that we
- * actually need from it.
- */
-#if !defined(PTW32_INCLUDE_WINDOWS_H)
-#if !defined(HANDLE)
-# define PTW32__HANDLE_DEF
-# define HANDLE void *
-#endif
-#if !defined(DWORD)
-# define PTW32__DWORD_DEF
-# define DWORD unsigned long
-#endif
-#endif
-
-#if !defined(HAVE_STRUCT_TIMESPEC)
-#define HAVE_STRUCT_TIMESPEC
-#if !defined(_TIMESPEC_DEFINED)
-#define _TIMESPEC_DEFINED
-struct timespec {
- time_t tv_sec;
- long tv_nsec;
-};
-#endif /* _TIMESPEC_DEFINED */
-#endif /* HAVE_STRUCT_TIMESPEC */
-
-#if !defined(SIG_BLOCK)
-#define SIG_BLOCK 0
-#endif /* SIG_BLOCK */
-
-#if !defined(SIG_UNBLOCK)
-#define SIG_UNBLOCK 1
-#endif /* SIG_UNBLOCK */
-
-#if !defined(SIG_SETMASK)
-#define SIG_SETMASK 2
-#endif /* SIG_SETMASK */
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif /* __cplusplus */
-
-/*
- * -------------------------------------------------------------
- *
- * POSIX 1003.1-2001 Options
- * =========================
- *
- * Options are normally set in <unistd.h>, which is not provided
- * with pthreads-win32.
- *
- * For conformance with the Single Unix Specification (version 3), all of the
- * options below are defined, and have a value of either -1 (not supported)
- * or 200112L (supported).
- *
- * These options can neither be left undefined nor have a value of 0, because
- * either indicates that sysconf(), which is not implemented, may be used at
- * runtime to check the status of the option.
- *
- * _POSIX_THREADS (== 200112L)
- * If == 200112L, you can use threads
- *
- * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
- * If == 200112L, you can control the size of a thread's
- * stack
- * pthread_attr_getstacksize
- * pthread_attr_setstacksize
- *
- * _POSIX_THREAD_ATTR_STACKADDR (== -1)
- * If == 200112L, you can allocate and control a thread's
- * stack. If not supported, the following functions
- * will return ENOSYS, indicating they are not
- * supported:
- * pthread_attr_getstackaddr
- * pthread_attr_setstackaddr
- *
- * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
- * If == 200112L, you can use realtime scheduling.
- * This option indicates that the behaviour of some
- * implemented functions conforms to the additional TPS
- * requirements in the standard. E.g. rwlocks favour
- * writers over readers when threads have equal priority.
- *
- * _POSIX_THREAD_PRIO_INHERIT (== -1)
- * If == 200112L, you can create priority inheritance
- * mutexes.
- * pthread_mutexattr_getprotocol +
- * pthread_mutexattr_setprotocol +
- *
- * _POSIX_THREAD_PRIO_PROTECT (== -1)
- * If == 200112L, you can create priority ceiling mutexes
- * Indicates the availability of:
- * pthread_mutex_getprioceiling
- * pthread_mutex_setprioceiling
- * pthread_mutexattr_getprioceiling
- * pthread_mutexattr_getprotocol +
- * pthread_mutexattr_setprioceiling
- * pthread_mutexattr_setprotocol +
- *
- * _POSIX_THREAD_PROCESS_SHARED (== -1)
- * If set, you can create mutexes and condition
- * variables that can be shared with another
- * process.If set, indicates the availability
- * of:
- * pthread_mutexattr_getpshared
- * pthread_mutexattr_setpshared
- * pthread_condattr_getpshared
- * pthread_condattr_setpshared
- *
- * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
- * If == 200112L you can use the special *_r library
- * functions that provide thread-safe behaviour
- *
- * _POSIX_READER_WRITER_LOCKS (== 200112L)
- * If == 200112L, you can use read/write locks
- *
- * _POSIX_SPIN_LOCKS (== 200112L)
- * If == 200112L, you can use spin locks
- *
- * _POSIX_BARRIERS (== 200112L)
- * If == 200112L, you can use barriers
- *
- * + These functions provide both 'inherit' and/or
- * 'protect' protocol, based upon these macro
- * settings.
- *
- * -------------------------------------------------------------
- */
-
-/*
- * POSIX Options
- */
-#undef _POSIX_THREADS
-#define _POSIX_THREADS 200809L
-
-#undef _POSIX_READER_WRITER_LOCKS
-#define _POSIX_READER_WRITER_LOCKS 200809L
-
-#undef _POSIX_SPIN_LOCKS
-#define _POSIX_SPIN_LOCKS 200809L
-
-#undef _POSIX_BARRIERS
-#define _POSIX_BARRIERS 200809L
-
-#undef _POSIX_THREAD_SAFE_FUNCTIONS
-#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
-
-#undef _POSIX_THREAD_ATTR_STACKSIZE
-#define _POSIX_THREAD_ATTR_STACKSIZE 200809L
-
-/*
- * The following options are not supported
- */
-#undef _POSIX_THREAD_ATTR_STACKADDR
-#define _POSIX_THREAD_ATTR_STACKADDR -1
-
-#undef _POSIX_THREAD_PRIO_INHERIT
-#define _POSIX_THREAD_PRIO_INHERIT -1
-
-#undef _POSIX_THREAD_PRIO_PROTECT
-#define _POSIX_THREAD_PRIO_PROTECT -1
-
-/* TPS is not fully supported. */
-#undef _POSIX_THREAD_PRIORITY_SCHEDULING
-#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
-
-#undef _POSIX_THREAD_PROCESS_SHARED
-#define _POSIX_THREAD_PROCESS_SHARED -1
-
-
-/*
- * POSIX 1003.1-2001 Limits
- * ===========================
- *
- * These limits are normally set in <limits.h>, which is not provided with
- * pthreads-win32.
- *
- * PTHREAD_DESTRUCTOR_ITERATIONS
- * Maximum number of attempts to destroy
- * a thread's thread-specific data on
- * termination (must be at least 4)
- *
- * PTHREAD_KEYS_MAX
- * Maximum number of thread-specific data keys
- * available per process (must be at least 128)
- *
- * PTHREAD_STACK_MIN
- * Minimum supported stack size for a thread
- *
- * PTHREAD_THREADS_MAX
- * Maximum number of threads supported per
- * process (must be at least 64).
- *
- * SEM_NSEMS_MAX
- * The maximum number of semaphores a process can have.
- * (must be at least 256)
- *
- * SEM_VALUE_MAX
- * The maximum value a semaphore can have.
- * (must be at least 32767)
- *
- */
-#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
-#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
-
-#undef PTHREAD_DESTRUCTOR_ITERATIONS
-#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
-
-#undef _POSIX_THREAD_KEYS_MAX
-#define _POSIX_THREAD_KEYS_MAX 128
-
-#undef PTHREAD_KEYS_MAX
-#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
-
-#undef PTHREAD_STACK_MIN
-#define PTHREAD_STACK_MIN 0
-
-#undef _POSIX_THREAD_THREADS_MAX
-#define _POSIX_THREAD_THREADS_MAX 64
-
- /* Arbitrary value */
-#undef PTHREAD_THREADS_MAX
-#define PTHREAD_THREADS_MAX 2019
-
-#undef _POSIX_SEM_NSEMS_MAX
-#define _POSIX_SEM_NSEMS_MAX 256
-
- /* Arbitrary value */
-#undef SEM_NSEMS_MAX
-#define SEM_NSEMS_MAX 1024
-
-#undef _POSIX_SEM_VALUE_MAX
-#define _POSIX_SEM_VALUE_MAX 32767
-
-#undef SEM_VALUE_MAX
-#define SEM_VALUE_MAX INT_MAX
-
-
-#if defined(__GNUC__) && !defined(__declspec)
-# error Please upgrade your GNU compiler to one that supports __declspec.
-#endif
-
-/*
- * When building the library, you should define PTW32_BUILD so that
- * the variables/functions are exported correctly. When using the library,
- * do NOT define PTW32_BUILD, and then the variables/functions will
- * be imported correctly.
- */
-#if !defined(PTW32_STATIC_LIB)
-# if defined(PTW32_BUILD)
-# define PTW32_DLLPORT __declspec (dllexport)
-# else
-# define PTW32_DLLPORT __declspec (dllimport)
-# endif
-#else
-# define PTW32_DLLPORT
-#endif
-
-/*
- * The Open Watcom C/C++ compiler uses a non-standard calling convention
- * that passes function args in registers unless __cdecl is explicitly specified
- * in exposed function prototypes.
- *
- * We force all calls to cdecl even though this could slow Watcom code down
- * slightly. If you know that the Watcom compiler will be used to build both
- * the DLL and application, then you can probably define this as a null string.
- * Remember that pthread.h (this file) is used for both the DLL and application builds.
- */
-#define PTW32_CDECL __cdecl
-
-#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
-# include <sys/types.h>
-#else
-/*
- * Generic handle type - intended to extend uniqueness beyond
- * that available with a simple pointer. It should scale for either
- * IA-32 or IA-64.
- */
-typedef struct {
- void * p; /* Pointer to actual object */
- unsigned int x; /* Extra information - reuse count etc */
-} ptw32_handle_t;
-
-typedef ptw32_handle_t pthread_t;
-typedef struct pthread_attr_t_ * pthread_attr_t;
-typedef struct pthread_once_t_ pthread_once_t;
-typedef struct pthread_key_t_ * pthread_key_t;
-typedef struct pthread_mutex_t_ * pthread_mutex_t;
-typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
-typedef struct pthread_cond_t_ * pthread_cond_t;
-typedef struct pthread_condattr_t_ * pthread_condattr_t;
-#endif
-typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
-typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
-typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
-typedef struct pthread_barrier_t_ * pthread_barrier_t;
-typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
-
-/*
- * ====================
- * ====================
- * POSIX Threads
- * ====================
- * ====================
- */
-
-enum {
-/*
- * pthread_attr_{get,set}detachstate
- */
- PTHREAD_CREATE_JOINABLE = 0, /* Default */
- PTHREAD_CREATE_DETACHED = 1,
-
-/*
- * pthread_attr_{get,set}inheritsched
- */
- PTHREAD_INHERIT_SCHED = 0,
- PTHREAD_EXPLICIT_SCHED = 1, /* Default */
-
-/*
- * pthread_{get,set}scope
- */
- PTHREAD_SCOPE_PROCESS = 0,
- PTHREAD_SCOPE_SYSTEM = 1, /* Default */
-
-/*
- * pthread_setcancelstate paramters
- */
- PTHREAD_CANCEL_ENABLE = 0, /* Default */
- PTHREAD_CANCEL_DISABLE = 1,
-
-/*
- * pthread_setcanceltype parameters
- */
- PTHREAD_CANCEL_ASYNCHRONOUS = 0,
- PTHREAD_CANCEL_DEFERRED = 1, /* Default */
-
-/*
- * pthread_mutexattr_{get,set}pshared
- * pthread_condattr_{get,set}pshared
- */
- PTHREAD_PROCESS_PRIVATE = 0,
- PTHREAD_PROCESS_SHARED = 1,
-
-/*
- * pthread_mutexattr_{get,set}robust
- */
- PTHREAD_MUTEX_STALLED = 0, /* Default */
- PTHREAD_MUTEX_ROBUST = 1,
-
-/*
- * pthread_barrier_wait
- */
- PTHREAD_BARRIER_SERIAL_THREAD = -1
-};
-
-/*
- * ====================
- * ====================
- * Cancelation
- * ====================
- * ====================
- */
-#define PTHREAD_CANCELED ((void *)(size_t) -1)
-
-
-/*
- * ====================
- * ====================
- * Once Key
- * ====================
- * ====================
- */
-#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
-
-struct pthread_once_t_
-{
- int done; /* indicates if user function has been executed */
- void * lock;
- int reserved1;
- int reserved2;
-};
-
-
-/*
- * ====================
- * ====================
- * Object initialisers
- * ====================
- * ====================
- */
-#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1)
-#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2)
-#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3)
-
-/*
- * Compatibility with LinuxThreads
- */
-#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
-#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
-
-#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1)
-
-#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1)
-
-#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1)
-
-
-/*
- * Mutex types.
- */
-enum
-{
- /* Compatibility with LinuxThreads */
- PTHREAD_MUTEX_FAST_NP,
- PTHREAD_MUTEX_RECURSIVE_NP,
- PTHREAD_MUTEX_ERRORCHECK_NP,
- PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
- PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
- /* For compatibility with POSIX */
- PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
- PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
- PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
- PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
-};
-
-
-typedef struct ptw32_cleanup_t ptw32_cleanup_t;
-
-#if defined(_MSC_VER)
-/* Disable MSVC 'anachronism used' warning */
-#pragma warning( disable : 4229 )
-#endif
-
-typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
-
-#if defined(_MSC_VER)
-#pragma warning( default : 4229 )
-#endif
-
-struct ptw32_cleanup_t
-{
- ptw32_cleanup_callback_t routine;
- void *arg;
- struct ptw32_cleanup_t *prev;
-};
-
-#if defined(__CLEANUP_SEH)
- /*
- * WIN32 SEH version of cancel cleanup.
- */
-
-#define pthread_cleanup_push( _rout, _arg ) \
- { \
- ptw32_cleanup_t _cleanup; \
- \
- _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
- _cleanup.arg = (_arg); \
- __try \
- { \
-
-#define pthread_cleanup_pop( _execute ) \
- } \
- __finally \
- { \
- if( _execute || AbnormalTermination()) \
- { \
- (*(_cleanup.routine))( _cleanup.arg ); \
- } \
- } \
- }
-
-#else /* __CLEANUP_SEH */
-
-#if defined(__CLEANUP_C)
-
- /*
- * C implementation of PThreads cancel cleanup
- */
-
-#define pthread_cleanup_push( _rout, _arg ) \
- { \
- ptw32_cleanup_t _cleanup; \
- \
- ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
-
-#define pthread_cleanup_pop( _execute ) \
- (void) ptw32_pop_cleanup( _execute ); \
- }
-
-#else /* __CLEANUP_C */
-
-#if defined(__CLEANUP_CXX)
-
- /*
- * C++ version of cancel cleanup.
- * - John E. Bossom.
- */
-
- class PThreadCleanup {
- /*
- * PThreadCleanup
- *
- * Purpose
- * This class is a C++ helper class that is
- * used to implement pthread_cleanup_push/
- * pthread_cleanup_pop.
- * The destructor of this class automatically
- * pops the pushed cleanup routine regardless
- * of how the code exits the scope
- * (i.e. such as by an exception)
- */
- ptw32_cleanup_callback_t cleanUpRout;
- void * obj;
- int executeIt;
-
- public:
- PThreadCleanup() :
- cleanUpRout( 0 ),
- obj( 0 ),
- executeIt( 0 )
- /*
- * No cleanup performed
- */
- {
- }
-
- PThreadCleanup(
- ptw32_cleanup_callback_t routine,
- void * arg ) :
- cleanUpRout( routine ),
- obj( arg ),
- executeIt( 1 )
- /*
- * Registers a cleanup routine for 'arg'
- */
- {
- }
-
- ~PThreadCleanup()
- {
- if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
- {
- (void) (*cleanUpRout)( obj );
- }
- }
-
- void execute( int exec )
- {
- executeIt = exec;
- }
- };
-
- /*
- * C++ implementation of PThreads cancel cleanup;
- * This implementation takes advantage of a helper
- * class who's destructor automatically calls the
- * cleanup routine if we exit our scope weirdly
- */
-#define pthread_cleanup_push( _rout, _arg ) \
- { \
- PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
- (void *) (_arg) );
-
-#define pthread_cleanup_pop( _execute ) \
- cleanup.execute( _execute ); \
- }
-
-#else
-
-#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-
-#endif /* __CLEANUP_CXX */
-
-#endif /* __CLEANUP_C */
-
-#endif /* __CLEANUP_SEH */
-
-/*
- * ===============
- * ===============
- * Methods
- * ===============
- * ===============
- */
-
-/*
- * PThread Attribute Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
- int *detachstate);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
- void **stackaddr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
- size_t * stacksize);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
- int detachstate);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
- void *stackaddr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
- size_t stacksize);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
- struct sched_param *param);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
- const struct sched_param *param);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
- int);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *,
- int *);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
- int inheritsched);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr,
- int * inheritsched);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
- int);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
- int *);
-
-/*
- * PThread Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
- const pthread_attr_t * attr,
- void *(*start) (void *),
- void *arg);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
- pthread_t t2);
-
-PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
- void **value_ptr);
-
-PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
- int *oldstate);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
- int *oldtype);
-
-PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
- void (*init_routine) (void));
-
-#if PTW32_LEVEL >= PTW32_LEVEL_MAX
-PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
-
-PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
- void (*routine) (void *),
- void *arg);
-#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
-
-/*
- * Thread Specific Data Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
- void (*destructor) (void *));
-
-PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
- const void *value);
-
-PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
-
-
-/*
- * Mutex Attribute Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
- * attr,
- int *pshared);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
- int pshared);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust(
- pthread_mutexattr_t *attr,
- int robust);
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust(
- const pthread_mutexattr_t * attr,
- int * robust);
-
-/*
- * Barrier Attribute Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
- * attr,
- int *pshared);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
- int pshared);
-
-/*
- * Mutex Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
- const pthread_mutexattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex,
- const struct timespec *abstime);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex);
-
-/*
- * Spinlock Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
-
-/*
- * Barrier Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
- const pthread_barrierattr_t * attr,
- unsigned int count);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
-
-/*
- * Condition Variable Attribute Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
- int *pshared);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
- int pshared);
-
-/*
- * Condition Variable Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
- const pthread_condattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
- pthread_mutex_t * mutex);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
- pthread_mutex_t * mutex,
- const struct timespec *abstime);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
-
-/*
- * Scheduling
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
- int policy,
- const struct sched_param *param);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
- int *policy,
- struct sched_param *param);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
-
-/*
- * Read-Write Lock Functions
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
- const pthread_rwlockattr_t *attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
- const struct timespec *abstime);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
- const struct timespec *abstime);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
- int *pshared);
-
-PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
- int pshared);
-
-#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
-
-/*
- * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
- * already have signal.h that don't define these.
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
-
-/*
- * Non-portable functions
- */
-
-/*
- * Compatibility with Linux.
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
- int kind);
-PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
- int *kind);
-
-/*
- * Possibly supported by other POSIX threads implementations
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
-PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
-PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread);
-
-/*
- * Useful if an application wants to statically link
- * the lib rather than load the DLL at run-time.
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
-PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
-PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
-PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
-
-/*
- * Features that are auto-detected at load/run time.
- */
-PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
-enum ptw32_features {
- PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
- PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
-};
-
-/*
- * Register a system time change with the library.
- * Causes the library to perform various functions
- * in response to the change. Should be called whenever
- * the application's top level window receives a
- * WM_TIMECHANGE message. It can be passed directly to
- * pthread_create() as a new thread if desired.
- */
-PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
-
-#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
-
-#if PTW32_LEVEL >= PTW32_LEVEL_MAX
-
-/*
- * Returns the Win32 HANDLE for the POSIX thread.
- */
-PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
-/*
- * Returns the win32 thread ID for POSIX thread.
- */
-PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread);
-
-
-/*
- * Protected Methods
- *
- * This function blocks until the given WIN32 handle
- * is signaled or pthread_cancel had been called.
- * This function allows the caller to hook into the
- * PThreads cancel mechanism. It is implemented using
- *
- * WaitForMultipleObjects
- *
- * on 'waitHandle' and a manually reset WIN32 Event
- * used to implement pthread_cancel. The 'timeout'
- * argument to TimedWait is simply passed to
- * WaitForMultipleObjects.
- */
-PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
-PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
- DWORD timeout);
-
-#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
-
-/*
- * Thread-Safe C Runtime Library Mappings.
- */
-#if !defined(_UWIN)
-# if defined(NEED_ERRNO)
- PTW32_DLLPORT int * PTW32_CDECL _errno( void );
-# else
-# if !defined(errno)
-# if (defined(_MT) || defined(_DLL))
- __declspec(dllimport) extern int * __cdecl _errno(void);
-# define errno (*_errno())
-# endif
-# endif
-# endif
-#endif
-
-/*
- * Some compiler environments don't define some things.
- */
-#if defined(__BORLANDC__)
-# define _ftime ftime
-# define _timeb timeb
-#endif
-
-#if defined(__cplusplus)
-
-/*
- * Internal exceptions
- */
-class ptw32_exception {};
-class ptw32_exception_cancel : public ptw32_exception {};
-class ptw32_exception_exit : public ptw32_exception {};
-
-#endif
-
-#if PTW32_LEVEL >= PTW32_LEVEL_MAX
-
-/* FIXME: This is only required if the library was built using SEH */
-/*
- * Get internal SEH tag
- */
-PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
-
-#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
-
-#if !defined(PTW32_BUILD)
-
-#if defined(__CLEANUP_SEH)
-
-/*
- * Redefine the SEH __except keyword to ensure that applications
- * propagate our internal exceptions up to the library's internal handlers.
- */
-#define __except( E ) \
- __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
- ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
-
-#endif /* __CLEANUP_SEH */
-
-#if defined(__CLEANUP_CXX)
-
-/*
- * Redefine the C++ catch keyword to ensure that applications
- * propagate our internal exceptions up to the library's internal handlers.
- */
-#if defined(_MSC_VER)
- /*
- * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
- * if you want Pthread-Win32 cancelation and pthread_exit to work.
- */
-
-#if !defined(PtW32NoCatchWarn)
-
-#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
-#pragma message("------------------------------------------------------------------")
-#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
-#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
-#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
-#pragma message(" cancelation and pthread_exit to work. For example:")
-#pragma message("")
-#pragma message(" #if defined(PtW32CatchAll)")
-#pragma message(" PtW32CatchAll")
-#pragma message(" #else")
-#pragma message(" catch(...)")
-#pragma message(" #endif")
-#pragma message(" {")
-#pragma message(" /* Catchall block processing */")
-#pragma message(" }")
-#pragma message("------------------------------------------------------------------")
-
-#endif
-
-#define PtW32CatchAll \
- catch( ptw32_exception & ) { throw; } \
- catch( ... )
-
-#else /* _MSC_VER */
-
-#define catch( E ) \
- catch( ptw32_exception & ) { throw; } \
- catch( E )
-
-#endif /* _MSC_VER */
-
-#endif /* __CLEANUP_CXX */
-
-#endif /* ! PTW32_BUILD */
-
-#if defined(__cplusplus)
-} /* End of extern "C" */
-#endif /* __cplusplus */
-
-#if defined(PTW32__HANDLE_DEF)
-# undef HANDLE
-#endif
-#if defined(PTW32__DWORD_DEF)
-# undef DWORD
-#endif
-
-#undef PTW32_LEVEL
-#undef PTW32_LEVEL_MAX
-
-#endif /* ! RC_INVOKED */
-
-#endif /* PTHREAD_H */
diff --git a/pthreads/src/pthread_attr_destroy.c b/pthreads/src/pthread_attr_destroy.c
deleted file mode 100644
index 8b3e04c..0000000
--- a/pthreads/src/pthread_attr_destroy.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * pthread_attr_destroy.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_attr_destroy (pthread_attr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Destroys a thread attributes object.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- *
- * DESCRIPTION
- * Destroys a thread attributes object.
- *
- * NOTES:
- * 1) Does not affect threads created with 'attr'.
- *
- * RESULTS
- * 0 successfully destroyed attr,
- * EINVAL 'attr' is invalid.
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- /*
- * Set the attribute object to a specific invalid value.
- */
- (*attr)->valid = 0;
- free (*attr);
- *attr = NULL;
-
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_getdetachstate.c b/pthreads/src/pthread_attr_getdetachstate.c
deleted file mode 100644
index 188533b..0000000
--- a/pthreads/src/pthread_attr_getdetachstate.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * pthread_attr_getdetachstate.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function determines whether threads created with
- * 'attr' will run detached.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- * detachstate
- * pointer to an integer into which is returned one
- * of:
- *
- * PTHREAD_CREATE_JOINABLE
- * Thread ID is valid, must be joined
- *
- * PTHREAD_CREATE_DETACHED
- * Thread ID is invalid, cannot be joined,
- * canceled, or modified
- *
- *
- * DESCRIPTION
- * This function determines whether threads created with
- * 'attr' will run detached.
- *
- * NOTES:
- * 1) You cannot join or cancel detached threads.
- *
- * RESULTS
- * 0 successfully retrieved detach state,
- * EINVAL 'attr' is invalid
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_is_attr (attr) != 0 || detachstate == NULL)
- {
- return EINVAL;
- }
-
- *detachstate = (*attr)->detachstate;
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_getinheritsched.c b/pthreads/src/pthread_attr_getinheritsched.c
deleted file mode 100644
index 9c6885e..0000000
--- a/pthreads/src/pthread_attr_getinheritsched.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * pthread_attr_getinheritsched.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_attr_getinheritsched (const pthread_attr_t * attr, int *inheritsched)
-{
- if (ptw32_is_attr (attr) != 0 || inheritsched == NULL)
- {
- return EINVAL;
- }
-
- *inheritsched = (*attr)->inheritsched;
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_getschedparam.c b/pthreads/src/pthread_attr_getschedparam.c
deleted file mode 100644
index ab89b22..0000000
--- a/pthreads/src/pthread_attr_getschedparam.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * pthread_attr_getschedparam.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_attr_getschedparam (const pthread_attr_t * attr,
- struct sched_param *param)
-{
- if (ptw32_is_attr (attr) != 0 || param == NULL)
- {
- return EINVAL;
- }
-
- memcpy (param, &(*attr)->param, sizeof (*param));
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_getschedpolicy.c b/pthreads/src/pthread_attr_getschedpolicy.c
deleted file mode 100644
index 94a257d..0000000
--- a/pthreads/src/pthread_attr_getschedpolicy.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * pthread_attr_getschedpolicy.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_attr_getschedpolicy (const pthread_attr_t * attr, int *policy)
-{
- if (ptw32_is_attr (attr) != 0 || policy == NULL)
- {
- return EINVAL;
- }
-
- /*
- * Validate the policy arg.
- * Check that a policy constant wasn't passed rather than &policy.
- */
- if (policy <= (int *) SCHED_MAX)
- {
- return EINVAL;
- }
-
- *policy = SCHED_OTHER;
-
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_getscope.c b/pthreads/src/pthread_attr_getscope.c
deleted file mode 100644
index 2efdb2f..0000000
--- a/pthreads/src/pthread_attr_getscope.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * pthread_attr_getscope.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/* ignore warning "unreferenced formal parameter" */
-#if defined(_MSC_VER)
-#pragma warning( disable : 4100 )
-#endif
-
-int
-pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope)
-{
-#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
- *contentionscope = (*attr)->contentionscope;
- return 0;
-#else
- return ENOSYS;
-#endif
-}
diff --git a/pthreads/src/pthread_attr_getstackaddr.c b/pthreads/src/pthread_attr_getstackaddr.c
deleted file mode 100644
index 1a2da01..0000000
--- a/pthreads/src/pthread_attr_getstackaddr.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * pthread_attr_getstackaddr.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/* ignore warning "unreferenced formal parameter" */
-#if defined(_MSC_VER)
-#pragma warning( disable : 4100 )
-#endif
-
-int
-pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function determines the address of the stack
- * on which threads created with 'attr' will run.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- * stackaddr
- * pointer into which is returned the stack address.
- *
- *
- * DESCRIPTION
- * This function determines the address of the stack
- * on which threads created with 'attr' will run.
- *
- * NOTES:
- * 1) Function supported only if this macro is
- * defined:
- *
- * _POSIX_THREAD_ATTR_STACKADDR
- *
- * 2) Create only one thread for each stack
- * address..
- *
- * RESULTS
- * 0 successfully retreived stack address,
- * EINVAL 'attr' is invalid
- * ENOSYS function not supported
- *
- * ------------------------------------------------------
- */
-{
-#if defined( _POSIX_THREAD_ATTR_STACKADDR )
-
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- *stackaddr = (*attr)->stackaddr;
- return 0;
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_ATTR_STACKADDR */
-}
diff --git a/pthreads/src/pthread_attr_getstacksize.c b/pthreads/src/pthread_attr_getstacksize.c
deleted file mode 100644
index dff9230..0000000
--- a/pthreads/src/pthread_attr_getstacksize.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * pthread_attr_getstacksize.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/* ignore warning "unreferenced formal parameter" */
-#if defined(_MSC_VER)
-#pragma warning( disable : 4100 )
-#endif
-
-int
-pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * stacksize)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function determines the size of the stack on
- * which threads created with 'attr' will run.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- * stacksize
- * pointer to size_t into which is returned the
- * stack size, in bytes.
- *
- *
- * DESCRIPTION
- * This function determines the size of the stack on
- * which threads created with 'attr' will run.
- *
- * NOTES:
- * 1) Function supported only if this macro is
- * defined:
- *
- * _POSIX_THREAD_ATTR_STACKSIZE
- *
- * 2) Use on newly created attributes object to
- * find the default stack size.
- *
- * RESULTS
- * 0 successfully retrieved stack size,
- * EINVAL 'attr' is invalid
- * ENOSYS function not supported
- *
- * ------------------------------------------------------
- */
-{
-#if defined(_POSIX_THREAD_ATTR_STACKSIZE)
-
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- /* Everything is okay. */
- *stacksize = (*attr)->stacksize;
- return 0;
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
-
-}
diff --git a/pthreads/src/pthread_attr_init.c b/pthreads/src/pthread_attr_init.c
deleted file mode 100644
index ae9d3eb..0000000
--- a/pthreads/src/pthread_attr_init.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * pthread_attr_init.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_attr_init (pthread_attr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Initializes a thread attributes object with default
- * attributes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- *
- * DESCRIPTION
- * Initializes a thread attributes object with default
- * attributes.
- *
- * NOTES:
- * 1) Used to define thread attributes
- *
- * RESULTS
- * 0 successfully initialized attr,
- * ENOMEM insufficient memory for attr.
- *
- * ------------------------------------------------------
- */
-{
- pthread_attr_t attr_result;
-
- if (attr == NULL)
- {
- /* This is disallowed. */
- return EINVAL;
- }
-
- attr_result = (pthread_attr_t) malloc (sizeof (*attr_result));
-
- if (attr_result == NULL)
- {
- return ENOMEM;
- }
-
-#if defined(_POSIX_THREAD_ATTR_STACKSIZE)
- /*
- * Default to zero size. Unless changed explicitly this
- * will allow Win32 to set the size to that of the
- * main thread.
- */
- attr_result->stacksize = 0;
-#endif
-
-#if defined(_POSIX_THREAD_ATTR_STACKADDR)
- /* FIXME: Set this to something sensible when we support it. */
- attr_result->stackaddr = NULL;
-#endif
-
- attr_result->detachstate = PTHREAD_CREATE_JOINABLE;
-
-#if defined(HAVE_SIGSET_T)
- memset (&(attr_result->sigmask), 0, sizeof (sigset_t));
-#endif /* HAVE_SIGSET_T */
-
- /*
- * Win32 sets new threads to THREAD_PRIORITY_NORMAL and
- * not to that of the parent thread. We choose to default to
- * this arrangement.
- */
- attr_result->param.sched_priority = THREAD_PRIORITY_NORMAL;
- attr_result->inheritsched = PTHREAD_EXPLICIT_SCHED;
- attr_result->contentionscope = PTHREAD_SCOPE_SYSTEM;
-
- attr_result->valid = PTW32_ATTR_VALID;
-
- *attr = attr_result;
-
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_setdetachstate.c b/pthreads/src/pthread_attr_setdetachstate.c
deleted file mode 100644
index 784642a..0000000
--- a/pthreads/src/pthread_attr_setdetachstate.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * pthread_attr_setdetachstate.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function specifies whether threads created with
- * 'attr' will run detached.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- * detachstate
- * an integer containing one of:
- *
- * PTHREAD_CREATE_JOINABLE
- * Thread ID is valid, must be joined
- *
- * PTHREAD_CREATE_DETACHED
- * Thread ID is invalid, cannot be joined,
- * canceled, or modified
- *
- *
- * DESCRIPTION
- * This function specifies whether threads created with
- * 'attr' will run detached.
- *
- * NOTES:
- * 1) You cannot join or cancel detached threads.
- *
- * RESULTS
- * 0 successfully set detach state,
- * EINVAL 'attr' or 'detachstate' is invalid
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- if (detachstate != PTHREAD_CREATE_JOINABLE &&
- detachstate != PTHREAD_CREATE_DETACHED)
- {
- return EINVAL;
- }
-
- (*attr)->detachstate = detachstate;
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_setinheritsched.c b/pthreads/src/pthread_attr_setinheritsched.c
deleted file mode 100644
index e0a407a..0000000
--- a/pthreads/src/pthread_attr_setinheritsched.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * pthread_attr_setinheritsched.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched)
-{
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- if (PTHREAD_INHERIT_SCHED != inheritsched
- && PTHREAD_EXPLICIT_SCHED != inheritsched)
- {
- return EINVAL;
- }
-
- (*attr)->inheritsched = inheritsched;
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_setschedparam.c b/pthreads/src/pthread_attr_setschedparam.c
deleted file mode 100644
index f246bfa..0000000
--- a/pthreads/src/pthread_attr_setschedparam.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * pthread_attr_setschedparam.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_attr_setschedparam (pthread_attr_t * attr,
- const struct sched_param *param)
-{
- int priority;
-
- if (ptw32_is_attr (attr) != 0 || param == NULL)
- {
- return EINVAL;
- }
-
- priority = param->sched_priority;
-
- /* Validate priority level. */
- if (priority < sched_get_priority_min (SCHED_OTHER) ||
- priority > sched_get_priority_max (SCHED_OTHER))
- {
- return EINVAL;
- }
-
- memcpy (&(*attr)->param, param, sizeof (*param));
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_setschedpolicy.c b/pthreads/src/pthread_attr_setschedpolicy.c
deleted file mode 100644
index 45ff165..0000000
--- a/pthreads/src/pthread_attr_setschedpolicy.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * pthread_attr_setschedpolicy.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy)
-{
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- if (policy != SCHED_OTHER)
- {
- return ENOTSUP;
- }
-
- return 0;
-}
diff --git a/pthreads/src/pthread_attr_setscope.c b/pthreads/src/pthread_attr_setscope.c
deleted file mode 100644
index 39a51df..0000000
--- a/pthreads/src/pthread_attr_setscope.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * pthread_attr_setscope.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/* ignore warning "unreferenced formal parameter" */
-#if defined(_MSC_VER)
-#pragma warning( disable : 4100 )
-#endif
-
-int
-pthread_attr_setscope (pthread_attr_t * attr, int contentionscope)
-{
-#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
- switch (contentionscope)
- {
- case PTHREAD_SCOPE_SYSTEM:
- (*attr)->contentionscope = contentionscope;
- return 0;
- case PTHREAD_SCOPE_PROCESS:
- return ENOTSUP;
- default:
- return EINVAL;
- }
-#else
- return ENOSYS;
-#endif
-}
diff --git a/pthreads/src/pthread_attr_setstackaddr.c b/pthreads/src/pthread_attr_setstackaddr.c
deleted file mode 100644
index 1316c06..0000000
--- a/pthreads/src/pthread_attr_setstackaddr.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * pthread_attr_setstackaddr.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Threads created with 'attr' will run on the stack
- * starting at 'stackaddr'.
- * Stack must be at least PTHREAD_STACK_MIN bytes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- * stackaddr
- * the address of the stack to use
- *
- *
- * DESCRIPTION
- * Threads created with 'attr' will run on the stack
- * starting at 'stackaddr'.
- * Stack must be at least PTHREAD_STACK_MIN bytes.
- *
- * NOTES:
- * 1) Function supported only if this macro is
- * defined:
- *
- * _POSIX_THREAD_ATTR_STACKADDR
- *
- * 2) Create only one thread for each stack
- * address..
- *
- * 3) Ensure that stackaddr is aligned.
- *
- * RESULTS
- * 0 successfully set stack address,
- * EINVAL 'attr' is invalid
- * ENOSYS function not supported
- *
- * ------------------------------------------------------
- */
-{
-#if defined( _POSIX_THREAD_ATTR_STACKADDR )
-
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- (*attr)->stackaddr = stackaddr;
- return 0;
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_ATTR_STACKADDR */
-}
diff --git a/pthreads/src/pthread_attr_setstacksize.c b/pthreads/src/pthread_attr_setstacksize.c
deleted file mode 100644
index eb13589..0000000
--- a/pthreads/src/pthread_attr_setstacksize.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * pthread_attr_setstacksize.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function specifies the size of the stack on
- * which threads created with 'attr' will run.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_attr_t
- *
- * stacksize
- * stack size, in bytes.
- *
- *
- * DESCRIPTION
- * This function specifies the size of the stack on
- * which threads created with 'attr' will run.
- *
- * NOTES:
- * 1) Function supported only if this macro is
- * defined:
- *
- * _POSIX_THREAD_ATTR_STACKSIZE
- *
- * 2) Find the default first (using
- * pthread_attr_getstacksize), then increase
- * by multiplying.
- *
- * 3) Only use if thread needs more than the
- * default.
- *
- * RESULTS
- * 0 successfully set stack size,
- * EINVAL 'attr' is invalid or stacksize too
- * small or too big.
- * ENOSYS function not supported
- *
- * ------------------------------------------------------
- */
-{
-#if defined(_POSIX_THREAD_ATTR_STACKSIZE)
-
-#if PTHREAD_STACK_MIN > 0
-
- /* Verify that the stack size is within range. */
- if (stacksize < PTHREAD_STACK_MIN)
- {
- return EINVAL;
- }
-
-#endif
-
- if (ptw32_is_attr (attr) != 0)
- {
- return EINVAL;
- }
-
- /* Everything is okay. */
- (*attr)->stacksize = stacksize;
- return 0;
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
-
-}
diff --git a/pthreads/src/pthread_barrier_destroy.c b/pthreads/src/pthread_barrier_destroy.c
deleted file mode 100644
index 55163cc..0000000
--- a/pthreads/src/pthread_barrier_destroy.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * pthread_barrier_destroy.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_barrier_destroy (pthread_barrier_t * barrier)
-{
- int result = 0;
- pthread_barrier_t b;
- ptw32_mcs_local_node_t node;
-
- if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
- {
- return EINVAL;
- }
-
- if (0 != ptw32_mcs_lock_try_acquire(&(*barrier)->lock, &node))
- {
- return EBUSY;
- }
-
- b = *barrier;
-
- if (b->nCurrentBarrierHeight < b->nInitialBarrierHeight)
- {
- result = EBUSY;
- }
- else
- {
- if (0 == (result = sem_destroy (&(b->semBarrierBreeched))))
- {
- *barrier = (pthread_barrier_t) PTW32_OBJECT_INVALID;
- /*
- * Release the lock before freeing b.
- *
- * FIXME: There may be successors which, when we release the lock,
- * will be linked into b->lock, which will be corrupted at some
- * point with undefined results for the application. To fix this
- * will require changing pthread_barrier_t from a pointer to
- * pthread_barrier_t_ to an instance. This is a change to the ABI
- * and will require a major version number increment.
- */
- ptw32_mcs_lock_release(&node);
- (void) free (b);
- return 0;
- }
- else
- {
- /*
- * This should not ever be reached.
- * Restore the barrier to working condition before returning.
- */
- (void) sem_init (&(b->semBarrierBreeched), b->pshared, 0);
- }
-
- if (result != 0)
- {
- /*
- * The barrier still exists and is valid
- * in the event of any error above.
- */
- result = EBUSY;
- }
- }
-
- ptw32_mcs_lock_release(&node);
- return (result);
-}
diff --git a/pthreads/src/pthread_barrier_init.c b/pthreads/src/pthread_barrier_init.c
deleted file mode 100644
index 618bfae..0000000
--- a/pthreads/src/pthread_barrier_init.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * pthread_barrier_init.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_barrier_init (pthread_barrier_t * barrier,
- const pthread_barrierattr_t * attr, unsigned int count)
-{
- pthread_barrier_t b;
-
- if (barrier == NULL || count == 0)
- {
- return EINVAL;
- }
-
- if (NULL != (b = (pthread_barrier_t) calloc (1, sizeof (*b))))
- {
- b->pshared = (attr != NULL && *attr != NULL
- ? (*attr)->pshared : PTHREAD_PROCESS_PRIVATE);
-
- b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count;
- b->lock = 0;
-
- if (0 == sem_init (&(b->semBarrierBreeched), b->pshared, 0))
- {
- *barrier = b;
- return 0;
- }
- (void) free (b);
- }
-
- return ENOMEM;
-}
diff --git a/pthreads/src/pthread_barrier_wait.c b/pthreads/src/pthread_barrier_wait.c
deleted file mode 100644
index e0e97e6..0000000
--- a/pthreads/src/pthread_barrier_wait.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * pthread_barrier_wait.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_barrier_wait (pthread_barrier_t * barrier)
-{
- int result;
- pthread_barrier_t b;
-
- ptw32_mcs_local_node_t node;
-
- if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
- {
- return EINVAL;
- }
-
- ptw32_mcs_lock_acquire(&(*barrier)->lock, &node);
-
- b = *barrier;
- if (--b->nCurrentBarrierHeight == 0)
- {
- /*
- * We are the last thread to arrive at the barrier before it releases us.
- * Move our MCS local node to the global scope barrier handle so that the
- * last thread out (not necessarily us) can release the lock.
- */
- ptw32_mcs_node_transfer(&b->proxynode, &node);
-
- /*
- * Any threads that have not quite entered sem_wait below when the
- * multiple_post has completed will nevertheless continue through
- * the semaphore (barrier).
- */
- result = (b->nInitialBarrierHeight > 1
- ? sem_post_multiple (&(b->semBarrierBreeched),
- b->nInitialBarrierHeight - 1) : 0);
- }
- else
- {
- ptw32_mcs_lock_release(&node);
- /*
- * Use the non-cancelable version of sem_wait().
- *
- * It is possible that all nInitialBarrierHeight-1 threads are
- * at this point when the last thread enters the barrier, resets
- * nCurrentBarrierHeight = nInitialBarrierHeight and leaves.
- * If pthread_barrier_destroy is called at that moment then the
- * barrier will be destroyed along with the semas.
- */
- result = ptw32_semwait (&(b->semBarrierBreeched));
- }
-
- if ((PTW32_INTERLOCKED_LONG)PTW32_INTERLOCKED_INCREMENT_LONG((PTW32_INTERLOCKED_LONGPTR)&b->nCurrentBarrierHeight)
- == (PTW32_INTERLOCKED_LONG)b->nInitialBarrierHeight)
- {
- /*
- * We are the last thread to cross this barrier
- */
- ptw32_mcs_lock_release(&b->proxynode);
- if (0 == result)
- {
- result = PTHREAD_BARRIER_SERIAL_THREAD;
- }
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_barrierattr_destroy.c b/pthreads/src/pthread_barrierattr_destroy.c
deleted file mode 100644
index 5ab662e..0000000
--- a/pthreads/src/pthread_barrierattr_destroy.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * pthread_barrier_attr_destroy.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_barrierattr_destroy (pthread_barrierattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Destroys a barrier attributes object. The object can
- * no longer be used.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_barrierattr_t
- *
- *
- * DESCRIPTION
- * Destroys a barrier attributes object. The object can
- * no longer be used.
- *
- * NOTES:
- * 1) Does not affect barrieres created using 'attr'
- *
- * RESULTS
- * 0 successfully released attr,
- * EINVAL 'attr' is invalid.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if (attr == NULL || *attr == NULL)
- {
- result = EINVAL;
- }
- else
- {
- pthread_barrierattr_t ba = *attr;
-
- *attr = NULL;
- free (ba);
- }
-
- return (result);
-} /* pthread_barrierattr_destroy */
diff --git a/pthreads/src/pthread_barrierattr_getpshared.c b/pthreads/src/pthread_barrierattr_getpshared.c
deleted file mode 100644
index 44c467e..0000000
--- a/pthreads/src/pthread_barrierattr_getpshared.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * pthread_barrier_attr_getpshared.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr,
- int *pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Determine whether barriers created with 'attr' can be
- * shared between processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_barrierattr_t
- *
- * pshared
- * will be set to one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- *
- * DESCRIPTION
- * Mutexes creatd with 'attr' can be shared between
- * processes if pthread_barrier_t variable is allocated
- * in memory shared by these processes.
- * NOTES:
- * 1) pshared barriers MUST be allocated in shared
- * memory.
- * 2) The following macro is defined if shared barriers
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully retrieved attribute,
- * EINVAL 'attr' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) && (pshared != NULL))
- {
- *pshared = (*attr)->pshared;
- result = 0;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-} /* pthread_barrierattr_getpshared */
diff --git a/pthreads/src/pthread_barrierattr_init.c b/pthreads/src/pthread_barrierattr_init.c
deleted file mode 100644
index 342f8b0..0000000
--- a/pthreads/src/pthread_barrierattr_init.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * pthread_barrier_attr_init.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_barrierattr_init (pthread_barrierattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Initializes a barrier attributes object with default
- * attributes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_barrierattr_t
- *
- *
- * DESCRIPTION
- * Initializes a barrier attributes object with default
- * attributes.
- *
- * NOTES:
- * 1) Used to define barrier types
- *
- * RESULTS
- * 0 successfully initialized attr,
- * ENOMEM insufficient memory for attr.
- *
- * ------------------------------------------------------
- */
-{
- pthread_barrierattr_t ba;
- int result = 0;
-
- ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba));
-
- if (ba == NULL)
- {
- result = ENOMEM;
- }
- else
- {
- ba->pshared = PTHREAD_PROCESS_PRIVATE;
- }
-
- *attr = ba;
-
- return (result);
-} /* pthread_barrierattr_init */
diff --git a/pthreads/src/pthread_barrierattr_setpshared.c b/pthreads/src/pthread_barrierattr_setpshared.c
deleted file mode 100644
index 08c6fde..0000000
--- a/pthreads/src/pthread_barrierattr_setpshared.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * pthread_barrier_attr_setpshared.c
- *
- * Description:
- * This translation unit implements barrier primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, int pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Barriers created with 'attr' can be shared between
- * processes if pthread_barrier_t variable is allocated
- * in memory shared by these processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_barrierattr_t
- *
- * pshared
- * must be one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- * DESCRIPTION
- * Mutexes creatd with 'attr' can be shared between
- * processes if pthread_barrier_t variable is allocated
- * in memory shared by these processes.
- *
- * NOTES:
- * 1) pshared barriers MUST be allocated in shared
- * memory.
- *
- * 2) The following macro is defined if shared barriers
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or pshared is invalid,
- * ENOSYS PTHREAD_PROCESS_SHARED not supported,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) &&
- ((pshared == PTHREAD_PROCESS_SHARED) ||
- (pshared == PTHREAD_PROCESS_PRIVATE)))
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
-
-#if !defined( _POSIX_THREAD_PROCESS_SHARED )
-
- result = ENOSYS;
- pshared = PTHREAD_PROCESS_PRIVATE;
-
-#else
-
- result = 0;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- else
- {
- result = 0;
- }
-
- (*attr)->pshared = pshared;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_barrierattr_setpshared */
diff --git a/pthreads/src/pthread_cancel.c b/pthreads/src/pthread_cancel.c
deleted file mode 100644
index ae60b72..0000000
--- a/pthreads/src/pthread_cancel.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * pthread_cancel.c
- *
- * Description:
- * POSIX thread functions related to thread cancellation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "context.h"
-
-static void
-ptw32_cancel_self (void)
-{
- ptw32_throw (PTW32_EPS_CANCEL);
-
- /* Never reached */
-}
-
-static void CALLBACK
-ptw32_cancel_callback (ULONG_PTR unused)
-{
- ptw32_throw (PTW32_EPS_CANCEL);
-
- /* Never reached */
-}
-
-/*
- * ptw32_RegisterCancelation() -
- * Must have args of same type as QueueUserAPCEx because this function
- * is a substitute for QueueUserAPCEx if it's not available.
- */
-DWORD
-ptw32_RegisterCancelation (PAPCFUNC unused1, HANDLE threadH, DWORD unused2)
-{
- CONTEXT context;
-
- context.ContextFlags = CONTEXT_CONTROL;
- GetThreadContext (threadH, &context);
- PTW32_PROGCTR (context) = (DWORD_PTR) ptw32_cancel_self;
- SetThreadContext (threadH, &context);
- return 0;
-}
-
-int
-pthread_cancel (pthread_t thread)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function requests cancellation of 'thread'.
- *
- * PARAMETERS
- * thread
- * reference to an instance of pthread_t
- *
- *
- * DESCRIPTION
- * This function requests cancellation of 'thread'.
- * NOTE: cancellation is asynchronous; use pthread_join to
- * wait for termination of 'thread' if necessary.
- *
- * RESULTS
- * 0 successfully requested cancellation,
- * ESRCH no thread found corresponding to 'thread',
- * ENOMEM implicit self thread create failed.
- * ------------------------------------------------------
- */
-{
- int result;
- int cancel_self;
- pthread_t self;
- ptw32_thread_t * tp;
- ptw32_mcs_local_node_t stateLock;
-
- result = pthread_kill (thread, 0);
-
- if (0 != result)
- {
- return result;
- }
-
- if ((self = pthread_self ()).p == NULL)
- {
- return ENOMEM;
- };
-
- /*
- * For self cancellation we need to ensure that a thread can't
- * deadlock itself trying to cancel itself asynchronously
- * (pthread_cancel is required to be an async-cancel
- * safe function).
- */
- cancel_self = pthread_equal (thread, self);
-
- tp = (ptw32_thread_t *) thread.p;
-
- /*
- * Lock for async-cancel safety.
- */
- ptw32_mcs_lock_acquire (&tp->stateLock, &stateLock);
-
- if (tp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
- && tp->cancelState == PTHREAD_CANCEL_ENABLE
- && tp->state < PThreadStateCanceling)
- {
- if (cancel_self)
- {
- tp->state = PThreadStateCanceling;
- tp->cancelState = PTHREAD_CANCEL_DISABLE;
-
- ptw32_mcs_lock_release (&stateLock);
- ptw32_throw (PTW32_EPS_CANCEL);
-
- /* Never reached */
- }
- else
- {
- HANDLE threadH = tp->threadH;
-
- SuspendThread (threadH);
-
- if (WaitForSingleObject (threadH, 0) == WAIT_TIMEOUT)
- {
- tp->state = PThreadStateCanceling;
- tp->cancelState = PTHREAD_CANCEL_DISABLE;
- /*
- * If alertdrv and QueueUserAPCEx is available then the following
- * will result in a call to QueueUserAPCEx with the args given, otherwise
- * this will result in a call to ptw32_RegisterCancelation and only
- * the threadH arg will be used.
- */
- ptw32_register_cancelation ((PAPCFUNC)ptw32_cancel_callback, threadH, 0);
- ptw32_mcs_lock_release (&stateLock);
- ResumeThread (threadH);
- }
- }
- }
- else
- {
- /*
- * Set for deferred cancellation.
- */
- if (tp->state < PThreadStateCancelPending)
- {
- tp->state = PThreadStateCancelPending;
- if (!SetEvent (tp->cancelEvent))
- {
- result = ESRCH;
- }
- }
- else if (tp->state >= PThreadStateCanceling)
- {
- result = ESRCH;
- }
-
- ptw32_mcs_lock_release (&stateLock);
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_cond_destroy.c b/pthreads/src/pthread_cond_destroy.c
deleted file mode 100644
index 40d4a08..0000000
--- a/pthreads/src/pthread_cond_destroy.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * pthread_cond_destroy.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_cond_destroy (pthread_cond_t * cond)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function destroys a condition variable
- *
- *
- * PARAMETERS
- * cond
- * pointer to an instance of pthread_cond_t
- *
- *
- * DESCRIPTION
- * This function destroys a condition variable.
- *
- * NOTES:
- * 1) A condition variable can be destroyed
- * immediately after all the threads that
- * are blocked on it are awakened. e.g.
- *
- * struct list {
- * pthread_mutex_t lm;
- * ...
- * }
- *
- * struct elt {
- * key k;
- * int busy;
- * pthread_cond_t notbusy;
- * ...
- * }
- *
- *
- * struct elt *
- * list_find(struct list *lp, key k)
- * {
- * struct elt *ep;
- *
- * pthread_mutex_lock(&lp->lm);
- * while ((ep = find_elt(l,k) != NULL) && ep->busy)
- * pthread_cond_wait(&ep->notbusy, &lp->lm);
- * if (ep != NULL)
- * ep->busy = 1;
- * pthread_mutex_unlock(&lp->lm);
- * return(ep);
- * }
- *
- * delete_elt(struct list *lp, struct elt *ep)
- * {
- * pthread_mutex_lock(&lp->lm);
- * assert(ep->busy);
- * ... remove ep from list ...
- * ep->busy = 0;
- * (A) pthread_cond_broadcast(&ep->notbusy);
- * pthread_mutex_unlock(&lp->lm);
- * (B) pthread_cond_destroy(&rp->notbusy);
- * free(ep);
- * }
- *
- * In this example, the condition variable
- * and its list element may be freed (line B)
- * immediately after all threads waiting for
- * it are awakened (line A), since the mutex
- * and the code ensure that no other thread
- * can touch the element to be deleted.
- *
- * RESULTS
- * 0 successfully released condition variable,
- * EINVAL 'cond' is invalid,
- * EBUSY 'cond' is in use,
- *
- * ------------------------------------------------------
- */
-{
- pthread_cond_t cv;
- int result = 0, result1 = 0, result2 = 0;
-
- /*
- * Assuming any race condition here is harmless.
- */
- if (cond == NULL || *cond == NULL)
- {
- return EINVAL;
- }
-
- if (*cond != PTHREAD_COND_INITIALIZER)
- {
- ptw32_mcs_local_node_t node;
- ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
-
- cv = *cond;
-
- /*
- * Close the gate; this will synchronize this thread with
- * all already signaled waiters to let them retract their
- * waiter status - SEE NOTE 1 ABOVE!!!
- */
- if (ptw32_semwait (&(cv->semBlockLock)) != 0) /* Non-cancelable */
- {
- result = errno;
- }
- else
- {
- /*
- * !TRY! lock mtxUnblockLock; try will detect busy condition
- * and will not cause a deadlock with respect to concurrent
- * signal/broadcast.
- */
- if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0)
- {
- (void) sem_post (&(cv->semBlockLock));
- }
- }
-
- if (result != 0)
- {
- ptw32_mcs_lock_release(&node);
- return result;
- }
-
- /*
- * Check whether cv is still busy (still has waiters)
- */
- if (cv->nWaitersBlocked > cv->nWaitersGone)
- {
- if (sem_post (&(cv->semBlockLock)) != 0)
- {
- result = errno;
- }
- result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock));
- result2 = EBUSY;
- }
- else
- {
- /*
- * Now it is safe to destroy
- */
- *cond = NULL;
-
- if (sem_destroy (&(cv->semBlockLock)) != 0)
- {
- result = errno;
- }
- if (sem_destroy (&(cv->semBlockQueue)) != 0)
- {
- result1 = errno;
- }
- if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
- {
- result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock));
- }
-
- /* Unlink the CV from the list */
-
- if (ptw32_cond_list_head == cv)
- {
- ptw32_cond_list_head = cv->next;
- }
- else
- {
- cv->prev->next = cv->next;
- }
-
- if (ptw32_cond_list_tail == cv)
- {
- ptw32_cond_list_tail = cv->prev;
- }
- else
- {
- cv->next->prev = cv->prev;
- }
-
- (void) free (cv);
- }
-
- ptw32_mcs_lock_release(&node);
- }
- else
- {
- ptw32_mcs_local_node_t node;
- /*
- * See notes in ptw32_cond_check_need_init() above also.
- */
- ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock, &node);
-
- /*
- * Check again.
- */
- if (*cond == PTHREAD_COND_INITIALIZER)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised cond that has not yet been used (initialised).
- * If we get to here, another thread waiting to initialise
- * this cond will get an EINVAL. That's OK.
- */
- *cond = NULL;
- }
- else
- {
- /*
- * The cv has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- ptw32_mcs_lock_release(&node);
- }
-
- return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
-}
diff --git a/pthreads/src/pthread_cond_init.c b/pthreads/src/pthread_cond_init.c
deleted file mode 100644
index f28fd67..0000000
--- a/pthreads/src/pthread_cond_init.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * pthread_cond_init.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function initializes a condition variable.
- *
- * PARAMETERS
- * cond
- * pointer to an instance of pthread_cond_t
- *
- * attr
- * specifies optional creation attributes.
- *
- *
- * DESCRIPTION
- * This function initializes a condition variable.
- *
- * RESULTS
- * 0 successfully created condition variable,
- * EINVAL 'attr' is invalid,
- * EAGAIN insufficient resources (other than
- * memory,
- * ENOMEM insufficient memory,
- * EBUSY 'cond' is already initialized,
- *
- * ------------------------------------------------------
- */
-{
- int result;
- pthread_cond_t cv = NULL;
-
- if (cond == NULL)
- {
- return EINVAL;
- }
-
- if ((attr != NULL && *attr != NULL) &&
- ((*attr)->pshared == PTHREAD_PROCESS_SHARED))
- {
- /*
- * Creating condition variable that can be shared between
- * processes.
- */
- result = ENOSYS;
- goto DONE;
- }
-
- cv = (pthread_cond_t) calloc (1, sizeof (*cv));
-
- if (cv == NULL)
- {
- result = ENOMEM;
- goto DONE;
- }
-
- cv->nWaitersBlocked = 0;
- cv->nWaitersToUnblock = 0;
- cv->nWaitersGone = 0;
-
- if (sem_init (&(cv->semBlockLock), 0, 1) != 0)
- {
- result = errno;
- goto FAIL0;
- }
-
- if (sem_init (&(cv->semBlockQueue), 0, 0) != 0)
- {
- result = errno;
- goto FAIL1;
- }
-
- if ((result = pthread_mutex_init (&(cv->mtxUnblockLock), 0)) != 0)
- {
- goto FAIL2;
- }
-
- result = 0;
-
- goto DONE;
-
- /*
- * -------------
- * Failed...
- * -------------
- */
-FAIL2:
- (void) sem_destroy (&(cv->semBlockQueue));
-
-FAIL1:
- (void) sem_destroy (&(cv->semBlockLock));
-
-FAIL0:
- (void) free (cv);
- cv = NULL;
-
-DONE:
- if (0 == result)
- {
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
-
- cv->next = NULL;
- cv->prev = ptw32_cond_list_tail;
-
- if (ptw32_cond_list_tail != NULL)
- {
- ptw32_cond_list_tail->next = cv;
- }
-
- ptw32_cond_list_tail = cv;
-
- if (ptw32_cond_list_head == NULL)
- {
- ptw32_cond_list_head = cv;
- }
-
- ptw32_mcs_lock_release(&node);
- }
-
- *cond = cv;
-
- return result;
-
-} /* pthread_cond_init */
diff --git a/pthreads/src/pthread_cond_signal.c b/pthreads/src/pthread_cond_signal.c
deleted file mode 100644
index 2b4f6d4..0000000
--- a/pthreads/src/pthread_cond_signal.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * pthread_cond_signal.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * -------------------------------------------------------------
- * Algorithm:
- * See the comments at the top of pthread_cond_wait.c.
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-static INLINE int
-ptw32_cond_unblock (pthread_cond_t * cond, int unblockAll)
- /*
- * Notes.
- *
- * Does not use the external mutex for synchronisation,
- * therefore semBlockLock is needed.
- * mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the
- * state where the external mutex is not necessarily locked by
- * any thread, ie. between cond_wait unlocking and re-acquiring
- * the lock after having been signaled or a timeout or
- * cancellation.
- *
- * Uses the following CV elements:
- * nWaitersBlocked
- * nWaitersToUnblock
- * nWaitersGone
- * mtxUnblockLock
- * semBlockLock
- * semBlockQueue
- */
-{
- int result;
- pthread_cond_t cv;
- int nSignalsToIssue;
-
- if (cond == NULL || *cond == NULL)
- {
- return EINVAL;
- }
-
- cv = *cond;
-
- /*
- * No-op if the CV is static and hasn't been initialised yet.
- * Assuming that any race condition is harmless.
- */
- if (cv == PTHREAD_COND_INITIALIZER)
- {
- return 0;
- }
-
- if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
- {
- return result;
- }
-
- if (0 != cv->nWaitersToUnblock)
- {
- if (0 == cv->nWaitersBlocked)
- {
- return pthread_mutex_unlock (&(cv->mtxUnblockLock));
- }
- if (unblockAll)
- {
- cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked);
- cv->nWaitersBlocked = 0;
- }
- else
- {
- nSignalsToIssue = 1;
- cv->nWaitersToUnblock++;
- cv->nWaitersBlocked--;
- }
- }
- else if (cv->nWaitersBlocked > cv->nWaitersGone)
- {
- /* Use the non-cancellable version of sem_wait() */
- if (ptw32_semwait (&(cv->semBlockLock)) != 0)
- {
- result = errno;
- (void) pthread_mutex_unlock (&(cv->mtxUnblockLock));
- return result;
- }
- if (0 != cv->nWaitersGone)
- {
- cv->nWaitersBlocked -= cv->nWaitersGone;
- cv->nWaitersGone = 0;
- }
- if (unblockAll)
- {
- nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked;
- cv->nWaitersBlocked = 0;
- }
- else
- {
- nSignalsToIssue = cv->nWaitersToUnblock = 1;
- cv->nWaitersBlocked--;
- }
- }
- else
- {
- return pthread_mutex_unlock (&(cv->mtxUnblockLock));
- }
-
- if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
- {
- if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0)
- {
- result = errno;
- }
- }
-
- return result;
-
-} /* ptw32_cond_unblock */
-
-int
-pthread_cond_signal (pthread_cond_t * cond)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function signals a condition variable, waking
- * one waiting thread.
- * If SCHED_FIFO or SCHED_RR policy threads are waiting
- * the highest priority waiter is awakened; otherwise,
- * an unspecified waiter is awakened.
- *
- * PARAMETERS
- * cond
- * pointer to an instance of pthread_cond_t
- *
- *
- * DESCRIPTION
- * This function signals a condition variable, waking
- * one waiting thread.
- * If SCHED_FIFO or SCHED_RR policy threads are waiting
- * the highest priority waiter is awakened; otherwise,
- * an unspecified waiter is awakened.
- *
- * NOTES:
- *
- * 1) Use when any waiter can respond and only one need
- * respond (all waiters being equal).
- *
- * RESULTS
- * 0 successfully signaled condition,
- * EINVAL 'cond' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- /*
- * The '0'(FALSE) unblockAll arg means unblock ONE waiter.
- */
- return (ptw32_cond_unblock (cond, 0));
-
-} /* pthread_cond_signal */
-
-int
-pthread_cond_broadcast (pthread_cond_t * cond)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function broadcasts the condition variable,
- * waking all current waiters.
- *
- * PARAMETERS
- * cond
- * pointer to an instance of pthread_cond_t
- *
- *
- * DESCRIPTION
- * This function signals a condition variable, waking
- * all waiting threads.
- *
- * NOTES:
- *
- * 1) Use when more than one waiter may respond to
- * predicate change or if any waiting thread may
- * not be able to respond
- *
- * RESULTS
- * 0 successfully signalled condition to all
- * waiting threads,
- * EINVAL 'cond' is invalid
- * ENOSPC a required resource has been exhausted,
- *
- * ------------------------------------------------------
- */
-{
- /*
- * The TRUE unblockAll arg means unblock ALL waiters.
- */
- return (ptw32_cond_unblock (cond, PTW32_TRUE));
-
-} /* pthread_cond_broadcast */
diff --git a/pthreads/src/pthread_cond_wait.c b/pthreads/src/pthread_cond_wait.c
deleted file mode 100644
index 359219a..0000000
--- a/pthreads/src/pthread_cond_wait.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * pthread_cond_wait.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * -------------------------------------------------------------
- * Algorithm:
- * The algorithm used in this implementation is that developed by
- * Alexander Terekhov in colaboration with Louis Thomas. The bulk
- * of the discussion is recorded in the file README.CV, which contains
- * several generations of both colaborators original algorithms. The final
- * algorithm used here is the one referred to as
- *
- * Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
- *
- * presented below in pseudo-code as it appeared:
- *
- *
- * given:
- * semBlockLock - bin.semaphore
- * semBlockQueue - semaphore
- * mtxExternal - mutex or CS
- * mtxUnblockLock - mutex or CS
- * nWaitersGone - int
- * nWaitersBlocked - int
- * nWaitersToUnblock - int
- *
- * wait( timeout ) {
- *
- * [auto: register int result ] // error checking omitted
- * [auto: register int nSignalsWasLeft ]
- * [auto: register int nWaitersWasGone ]
- *
- * sem_wait( semBlockLock );
- * nWaitersBlocked++;
- * sem_post( semBlockLock );
- *
- * unlock( mtxExternal );
- * bTimedOut = sem_wait( semBlockQueue,timeout );
- *
- * lock( mtxUnblockLock );
- * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
- * if ( bTimeout ) { // timeout (or canceled)
- * if ( 0 != nWaitersBlocked ) {
- * nWaitersBlocked--;
- * }
- * else {
- * nWaitersGone++; // count spurious wakeups.
- * }
- * }
- * if ( 0 == --nWaitersToUnblock ) {
- * if ( 0 != nWaitersBlocked ) {
- * sem_post( semBlockLock ); // open the gate.
- * nSignalsWasLeft = 0; // do not open the gate
- * // below again.
- * }
- * else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
- * nWaitersGone = 0;
- * }
- * }
- * }
- * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
- * // spurious semaphore :-)
- * sem_wait( semBlockLock );
- * nWaitersBlocked -= nWaitersGone; // something is going on here
- * // - test of timeouts? :-)
- * sem_post( semBlockLock );
- * nWaitersGone = 0;
- * }
- * unlock( mtxUnblockLock );
- *
- * if ( 1 == nSignalsWasLeft ) {
- * if ( 0 != nWaitersWasGone ) {
- * // sem_adjust( semBlockQueue,-nWaitersWasGone );
- * while ( nWaitersWasGone-- ) {
- * sem_wait( semBlockQueue ); // better now than spurious later
- * }
- * } sem_post( semBlockLock ); // open the gate
- * }
- *
- * lock( mtxExternal );
- *
- * return ( bTimedOut ) ? ETIMEOUT : 0;
- * }
- *
- * signal(bAll) {
- *
- * [auto: register int result ]
- * [auto: register int nSignalsToIssue]
- *
- * lock( mtxUnblockLock );
- *
- * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
- * if ( 0 == nWaitersBlocked ) { // NO-OP
- * return unlock( mtxUnblockLock );
- * }
- * if (bAll) {
- * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
- * nWaitersBlocked = 0;
- * }
- * else {
- * nSignalsToIssue = 1;
- * nWaitersToUnblock++;
- * nWaitersBlocked--;
- * }
- * }
- * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
- * sem_wait( semBlockLock ); // close the gate
- * if ( 0 != nWaitersGone ) {
- * nWaitersBlocked -= nWaitersGone;
- * nWaitersGone = 0;
- * }
- * if (bAll) {
- * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
- * nWaitersBlocked = 0;
- * }
- * else {
- * nSignalsToIssue = nWaitersToUnblock = 1;
- * nWaitersBlocked--;
- * }
- * }
- * else { // NO-OP
- * return unlock( mtxUnblockLock );
- * }
- *
- * unlock( mtxUnblockLock );
- * sem_post( semBlockQueue,nSignalsToIssue );
- * return result;
- * }
- * -------------------------------------------------------------
- *
- * Algorithm 9 / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
- *
- * presented below in pseudo-code; basically 8a...
- * ...BUT W/O "spurious wakes" prevention:
- *
- *
- * given:
- * semBlockLock - bin.semaphore
- * semBlockQueue - semaphore
- * mtxExternal - mutex or CS
- * mtxUnblockLock - mutex or CS
- * nWaitersGone - int
- * nWaitersBlocked - int
- * nWaitersToUnblock - int
- *
- * wait( timeout ) {
- *
- * [auto: register int result ] // error checking omitted
- * [auto: register int nSignalsWasLeft ]
- *
- * sem_wait( semBlockLock );
- * ++nWaitersBlocked;
- * sem_post( semBlockLock );
- *
- * unlock( mtxExternal );
- * bTimedOut = sem_wait( semBlockQueue,timeout );
- *
- * lock( mtxUnblockLock );
- * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
- * --nWaitersToUnblock;
- * }
- * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
- * // spurious semaphore :-)
- * sem_wait( semBlockLock );
- * nWaitersBlocked -= nWaitersGone; // something is going on here
- * // - test of timeouts? :-)
- * sem_post( semBlockLock );
- * nWaitersGone = 0;
- * }
- * unlock( mtxUnblockLock );
- *
- * if ( 1 == nSignalsWasLeft ) {
- * sem_post( semBlockLock ); // open the gate
- * }
- *
- * lock( mtxExternal );
- *
- * return ( bTimedOut ) ? ETIMEOUT : 0;
- * }
- *
- * signal(bAll) {
- *
- * [auto: register int result ]
- * [auto: register int nSignalsToIssue]
- *
- * lock( mtxUnblockLock );
- *
- * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
- * if ( 0 == nWaitersBlocked ) { // NO-OP
- * return unlock( mtxUnblockLock );
- * }
- * if (bAll) {
- * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
- * nWaitersBlocked = 0;
- * }
- * else {
- * nSignalsToIssue = 1;
- * ++nWaitersToUnblock;
- * --nWaitersBlocked;
- * }
- * }
- * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
- * sem_wait( semBlockLock ); // close the gate
- * if ( 0 != nWaitersGone ) {
- * nWaitersBlocked -= nWaitersGone;
- * nWaitersGone = 0;
- * }
- * if (bAll) {
- * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
- * nWaitersBlocked = 0;
- * }
- * else {
- * nSignalsToIssue = nWaitersToUnblock = 1;
- * --nWaitersBlocked;
- * }
- * }
- * else { // NO-OP
- * return unlock( mtxUnblockLock );
- * }
- *
- * unlock( mtxUnblockLock );
- * sem_post( semBlockQueue,nSignalsToIssue );
- * return result;
- * }
- * -------------------------------------------------------------
- *
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * Arguments for cond_wait_cleanup, since we can only pass a
- * single void * to it.
- */
-typedef struct
-{
- pthread_mutex_t *mutexPtr;
- pthread_cond_t cv;
- int *resultPtr;
-} ptw32_cond_wait_cleanup_args_t;
-
-static void PTW32_CDECL
-ptw32_cond_wait_cleanup (void *args)
-{
- ptw32_cond_wait_cleanup_args_t *cleanup_args =
- (ptw32_cond_wait_cleanup_args_t *) args;
- pthread_cond_t cv = cleanup_args->cv;
- int *resultPtr = cleanup_args->resultPtr;
- int nSignalsWasLeft;
- int result;
-
- /*
- * Whether we got here as a result of signal/broadcast or because of
- * timeout on wait or thread cancellation we indicate that we are no
- * longer waiting. The waiter is responsible for adjusting waiters
- * (to)unblock(ed) counts (protected by unblock lock).
- */
- if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
- {
- *resultPtr = result;
- return;
- }
-
- if (0 != (nSignalsWasLeft = cv->nWaitersToUnblock))
- {
- --(cv->nWaitersToUnblock);
- }
- else if (INT_MAX / 2 == ++(cv->nWaitersGone))
- {
- /* Use the non-cancellable version of sem_wait() */
- if (ptw32_semwait (&(cv->semBlockLock)) != 0)
- {
- *resultPtr = errno;
- /*
- * This is a fatal error for this CV,
- * so we deliberately don't unlock
- * cv->mtxUnblockLock before returning.
- */
- return;
- }
- cv->nWaitersBlocked -= cv->nWaitersGone;
- if (sem_post (&(cv->semBlockLock)) != 0)
- {
- *resultPtr = errno;
- /*
- * This is a fatal error for this CV,
- * so we deliberately don't unlock
- * cv->mtxUnblockLock before returning.
- */
- return;
- }
- cv->nWaitersGone = 0;
- }
-
- if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) != 0)
- {
- *resultPtr = result;
- return;
- }
-
- if (1 == nSignalsWasLeft)
- {
- if (sem_post (&(cv->semBlockLock)) != 0)
- {
- *resultPtr = errno;
- return;
- }
- }
-
- /*
- * XSH: Upon successful return, the mutex has been locked and is owned
- * by the calling thread.
- */
- if ((result = pthread_mutex_lock (cleanup_args->mutexPtr)) != 0)
- {
- *resultPtr = result;
- }
-} /* ptw32_cond_wait_cleanup */
-
-static INLINE int
-ptw32_cond_timedwait (pthread_cond_t * cond,
- pthread_mutex_t * mutex, const struct timespec *abstime)
-{
- int result = 0;
- pthread_cond_t cv;
- ptw32_cond_wait_cleanup_args_t cleanup_args;
-
- if (cond == NULL || *cond == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static condition variable. We check
- * again inside the guarded section of ptw32_cond_check_need_init()
- * to avoid race conditions.
- */
- if (*cond == PTHREAD_COND_INITIALIZER)
- {
- result = ptw32_cond_check_need_init (cond);
- }
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
-
- cv = *cond;
-
- /* Thread can be cancelled in sem_wait() but this is OK */
- if (sem_wait (&(cv->semBlockLock)) != 0)
- {
- return errno;
- }
-
- ++(cv->nWaitersBlocked);
-
- if (sem_post (&(cv->semBlockLock)) != 0)
- {
- return errno;
- }
-
- /*
- * Setup this waiter cleanup handler
- */
- cleanup_args.mutexPtr = mutex;
- cleanup_args.cv = cv;
- cleanup_args.resultPtr = &result;
-
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth(0)
-#endif
- pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args);
-
- /*
- * Now we can release 'mutex' and...
- */
- if ((result = pthread_mutex_unlock (mutex)) == 0)
- {
-
- /*
- * ...wait to be awakened by
- * pthread_cond_signal, or
- * pthread_cond_broadcast, or
- * timeout, or
- * thread cancellation
- *
- * Note:
- *
- * sem_timedwait is a cancellation point,
- * hence providing the mechanism for making
- * pthread_cond_wait a cancellation point.
- * We use the cleanup mechanism to ensure we
- * re-lock the mutex and adjust (to)unblock(ed) waiters
- * counts if we are cancelled, timed out or signalled.
- */
- if (sem_timedwait (&(cv->semBlockQueue), abstime) != 0)
- {
- result = errno;
- }
- }
-
- /*
- * Always cleanup
- */
- pthread_cleanup_pop (1);
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth()
-#endif
-
- /*
- * "result" can be modified by the cleanup handler.
- */
- return result;
-
-} /* ptw32_cond_timedwait */
-
-
-int
-pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function waits on a condition variable until
- * awakened by a signal or broadcast.
- *
- * Caller MUST be holding the mutex lock; the
- * lock is released and the caller is blocked waiting
- * on 'cond'. When 'cond' is signaled, the mutex
- * is re-acquired before returning to the caller.
- *
- * PARAMETERS
- * cond
- * pointer to an instance of pthread_cond_t
- *
- * mutex
- * pointer to an instance of pthread_mutex_t
- *
- *
- * DESCRIPTION
- * This function waits on a condition variable until
- * awakened by a signal or broadcast.
- *
- * NOTES:
- *
- * 1) The function must be called with 'mutex' LOCKED
- * by the calling thread, or undefined behaviour
- * will result.
- *
- * 2) This routine atomically releases 'mutex' and causes
- * the calling thread to block on the condition variable.
- * The blocked thread may be awakened by
- * pthread_cond_signal or
- * pthread_cond_broadcast.
- *
- * Upon successful completion, the 'mutex' has been locked and
- * is owned by the calling thread.
- *
- *
- * RESULTS
- * 0 caught condition; mutex released,
- * EINVAL 'cond' or 'mutex' is invalid,
- * EINVAL different mutexes for concurrent waits,
- * EINVAL mutex is not held by the calling thread,
- *
- * ------------------------------------------------------
- */
-{
- /*
- * The NULL abstime arg means INFINITE waiting.
- */
- return (ptw32_cond_timedwait (cond, mutex, NULL));
-
-} /* pthread_cond_wait */
-
-
-int
-pthread_cond_timedwait (pthread_cond_t * cond,
- pthread_mutex_t * mutex,
- const struct timespec *abstime)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function waits on a condition variable either until
- * awakened by a signal or broadcast; or until the time
- * specified by abstime passes.
- *
- * PARAMETERS
- * cond
- * pointer to an instance of pthread_cond_t
- *
- * mutex
- * pointer to an instance of pthread_mutex_t
- *
- * abstime
- * pointer to an instance of (const struct timespec)
- *
- *
- * DESCRIPTION
- * This function waits on a condition variable either until
- * awakened by a signal or broadcast; or until the time
- * specified by abstime passes.
- *
- * NOTES:
- * 1) The function must be called with 'mutex' LOCKED
- * by the calling thread, or undefined behaviour
- * will result.
- *
- * 2) This routine atomically releases 'mutex' and causes
- * the calling thread to block on the condition variable.
- * The blocked thread may be awakened by
- * pthread_cond_signal or
- * pthread_cond_broadcast.
- *
- *
- * RESULTS
- * 0 caught condition; mutex released,
- * EINVAL 'cond', 'mutex', or abstime is invalid,
- * EINVAL different mutexes for concurrent waits,
- * EINVAL mutex is not held by the calling thread,
- * ETIMEDOUT abstime ellapsed before cond was signaled.
- *
- * ------------------------------------------------------
- */
-{
- if (abstime == NULL)
- {
- return EINVAL;
- }
-
- return (ptw32_cond_timedwait (cond, mutex, abstime));
-
-} /* pthread_cond_timedwait */
diff --git a/pthreads/src/pthread_condattr_destroy.c b/pthreads/src/pthread_condattr_destroy.c
deleted file mode 100644
index 58a1482..0000000
--- a/pthreads/src/pthread_condattr_destroy.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * condvar_attr_destroy.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_condattr_destroy (pthread_condattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Destroys a condition variable attributes object.
- * The object can no longer be used.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_condattr_t
- *
- *
- * DESCRIPTION
- * Destroys a condition variable attributes object.
- * The object can no longer be used.
- *
- * NOTES:
- * 1) Does not affect condition variables created
- * using 'attr'
- *
- * RESULTS
- * 0 successfully released attr,
- * EINVAL 'attr' is invalid.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if (attr == NULL || *attr == NULL)
- {
- result = EINVAL;
- }
- else
- {
- (void) free (*attr);
-
- *attr = NULL;
- result = 0;
- }
-
- return result;
-
-} /* pthread_condattr_destroy */
diff --git a/pthreads/src/pthread_condattr_getpshared.c b/pthreads/src/pthread_condattr_getpshared.c
deleted file mode 100644
index a0ac6d8..0000000
--- a/pthreads/src/pthread_condattr_getpshared.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * pthread_condattr_getpshared.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Determine whether condition variables created with 'attr'
- * can be shared between processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_condattr_t
- *
- * pshared
- * will be set to one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- *
- * DESCRIPTION
- * Condition Variables created with 'attr' can be shared
- * between processes if pthread_cond_t variable is allocated
- * in memory shared by these processes.
- * NOTES:
- * 1) pshared condition variables MUST be allocated in
- * shared memory.
- *
- * 2) The following macro is defined if shared mutexes
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully retrieved attribute,
- * EINVAL 'attr' or 'pshared' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) && (pshared != NULL))
- {
- *pshared = (*attr)->pshared;
- result = 0;
- }
- else
- {
- result = EINVAL;
- }
-
- return result;
-
-} /* pthread_condattr_getpshared */
diff --git a/pthreads/src/pthread_condattr_init.c b/pthreads/src/pthread_condattr_init.c
deleted file mode 100644
index 5987878..0000000
--- a/pthreads/src/pthread_condattr_init.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * pthread_condattr_init.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_condattr_init (pthread_condattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Initializes a condition variable attributes object
- * with default attributes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_condattr_t
- *
- *
- * DESCRIPTION
- * Initializes a condition variable attributes object
- * with default attributes.
- *
- * NOTES:
- * 1) Use to define condition variable types
- * 2) It is up to the application to ensure
- * that it doesn't re-init an attribute
- * without destroying it first. Otherwise
- * a memory leak is created.
- *
- * RESULTS
- * 0 successfully initialized attr,
- * ENOMEM insufficient memory for attr.
- *
- * ------------------------------------------------------
- */
-{
- pthread_condattr_t attr_result;
- int result = 0;
-
- attr_result = (pthread_condattr_t) calloc (1, sizeof (*attr_result));
-
- if (attr_result == NULL)
- {
- result = ENOMEM;
- }
-
- *attr = attr_result;
-
- return result;
-
-} /* pthread_condattr_init */
diff --git a/pthreads/src/pthread_condattr_setpshared.c b/pthreads/src/pthread_condattr_setpshared.c
deleted file mode 100644
index 954fb38..0000000
--- a/pthreads/src/pthread_condattr_setpshared.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * pthread_condattr_setpshared.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Mutexes created with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * pshared
- * must be one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- * DESCRIPTION
- * Mutexes creatd with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- *
- * NOTES:
- * 1) pshared mutexes MUST be allocated in shared
- * memory.
- *
- * 2) The following macro is defined if shared mutexes
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or pshared is invalid,
- * ENOSYS PTHREAD_PROCESS_SHARED not supported,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL)
- && ((pshared == PTHREAD_PROCESS_SHARED)
- || (pshared == PTHREAD_PROCESS_PRIVATE)))
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
-
-#if !defined( _POSIX_THREAD_PROCESS_SHARED )
- result = ENOSYS;
- pshared = PTHREAD_PROCESS_PRIVATE;
-#else
- result = 0;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- else
- {
- result = 0;
- }
-
- (*attr)->pshared = pshared;
- }
- else
- {
- result = EINVAL;
- }
-
- return result;
-
-} /* pthread_condattr_setpshared */
diff --git a/pthreads/src/pthread_delay_np.c b/pthreads/src/pthread_delay_np.c
deleted file mode 100644
index e6c96d8..0000000
--- a/pthreads/src/pthread_delay_np.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * pthreads_delay_np.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * pthread_delay_np
- *
- * DESCRIPTION
- *
- * This routine causes a thread to delay execution for a specific period of time.
- * This period ends at the current time plus the specified interval. The routine
- * will not return before the end of the period is reached, but may return an
- * arbitrary amount of time after the period has gone by. This can be due to
- * system load, thread priorities, and system timer granularity.
- *
- * Specifying an interval of zero (0) seconds and zero (0) nanoseconds is
- * allowed and can be used to force the thread to give up the processor or to
- * deliver a pending cancelation request.
- *
- * The timespec structure contains the following two fields:
- *
- * tv_sec is an integer number of seconds.
- * tv_nsec is an integer number of nanoseconds.
- *
- * Return Values
- *
- * If an error condition occurs, this routine returns an integer value indicating
- * the type of error. Possible return values are as follows:
- *
- * 0
- * Successful completion.
- * [EINVAL]
- * The value specified by interval is invalid.
- *
- * Example
- *
- * The following code segment would wait for 5 and 1/2 seconds
- *
- * struct timespec tsWait;
- * int intRC;
- *
- * tsWait.tv_sec = 5;
- * tsWait.tv_nsec = 500000000L;
- * intRC = pthread_delay_np(&tsWait);
- */
-int
-pthread_delay_np (struct timespec *interval)
-{
- DWORD wait_time;
- DWORD secs_in_millisecs;
- DWORD millisecs;
- DWORD status;
- pthread_t self;
- ptw32_thread_t * sp;
-
- if (interval == NULL)
- {
- return EINVAL;
- }
-
- if (interval->tv_sec == 0L && interval->tv_nsec == 0L)
- {
- pthread_testcancel ();
- Sleep (0);
- pthread_testcancel ();
- return (0);
- }
-
- /* convert secs to millisecs */
- secs_in_millisecs = (DWORD)interval->tv_sec * 1000L;
-
- /* convert nanosecs to millisecs (rounding up) */
- millisecs = (interval->tv_nsec + 999999L) / 1000000L;
-
-#if defined(__WATCOMC__)
-#pragma disable_message (124)
-#endif
-
- /*
- * Most compilers will issue a warning 'comparison always 0'
- * because the variable type is unsigned, but we need to keep this
- * for some reason I can't recall now.
- */
- if (0 > (wait_time = secs_in_millisecs + millisecs))
- {
- return EINVAL;
- }
-
-#if defined(__WATCOMC__)
-#pragma enable_message (124)
-#endif
-
- if (NULL == (self = pthread_self ()).p)
- {
- return ENOMEM;
- }
-
- sp = (ptw32_thread_t *) self.p;
-
- if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
- {
- /*
- * Async cancelation won't catch us until wait_time is up.
- * Deferred cancelation will cancel us immediately.
- */
- if (WAIT_OBJECT_0 ==
- (status = WaitForSingleObject (sp->cancelEvent, wait_time)))
- {
- ptw32_mcs_local_node_t stateLock;
- /*
- * Canceling!
- */
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
- if (sp->state < PThreadStateCanceling)
- {
- sp->state = PThreadStateCanceling;
- sp->cancelState = PTHREAD_CANCEL_DISABLE;
- ptw32_mcs_lock_release (&stateLock);
-
- ptw32_throw (PTW32_EPS_CANCEL);
- }
-
- ptw32_mcs_lock_release (&stateLock);
- return ESRCH;
- }
- else if (status != WAIT_TIMEOUT)
- {
- return EINVAL;
- }
- }
- else
- {
- Sleep (wait_time);
- }
-
- return (0);
-}
diff --git a/pthreads/src/pthread_detach.c b/pthreads/src/pthread_detach.c
deleted file mode 100644
index 9ff6587..0000000
--- a/pthreads/src/pthread_detach.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * pthread_detach.c
- *
- * Description:
- * This translation unit implements functions related to thread
- * synchronisation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * Not needed yet, but defining it should indicate clashes with build target
- * environment that should be fixed.
- */
-#if !defined(WINCE)
-# include <signal.h>
-#endif
-
-
-int
-pthread_detach (pthread_t thread)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function detaches the given thread.
- *
- * PARAMETERS
- * thread
- * an instance of a pthread_t
- *
- *
- * DESCRIPTION
- * This function detaches the given thread. You may use it to
- * detach the main thread or to detach a joinable thread.
- * NOTE: detached threads cannot be joined;
- * storage is freed immediately on termination.
- *
- * RESULTS
- * 0 successfully detached the thread,
- * EINVAL thread is not a joinable thread,
- * ENOSPC a required resource has been exhausted,
- * ESRCH no thread could be found for 'thread',
- *
- * ------------------------------------------------------
- */
-{
- int result;
- BOOL destroyIt = PTW32_FALSE;
- ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
-
- if (NULL == tp
- || thread.x != tp->ptHandle.x)
- {
- result = ESRCH;
- }
- else if (PTHREAD_CREATE_DETACHED == tp->detachState)
- {
- result = EINVAL;
- }
- else
- {
- ptw32_mcs_local_node_t stateLock;
- /*
- * Joinable ptw32_thread_t structs are not scavenged until
- * a join or detach is done. The thread may have exited already,
- * but all of the state and locks etc are still there.
- */
- result = 0;
-
- ptw32_mcs_lock_acquire (&tp->stateLock, &stateLock);
- if (tp->state != PThreadStateLast)
- {
- tp->detachState = PTHREAD_CREATE_DETACHED;
- }
- else if (tp->detachState != PTHREAD_CREATE_DETACHED)
- {
- /*
- * Thread is joinable and has exited or is exiting.
- */
- destroyIt = PTW32_TRUE;
- }
- ptw32_mcs_lock_release (&stateLock);
- }
-
- ptw32_mcs_lock_release(&node);
-
- if (result == 0)
- {
- /* Thread is joinable */
-
- if (destroyIt)
- {
- /* The thread has exited or is exiting but has not been joined or
- * detached. Need to wait in case it's still exiting.
- */
- (void) WaitForSingleObject(tp->threadH, INFINITE);
- ptw32_threadDestroy (thread);
- }
- }
-
- return (result);
-
-} /* pthread_detach */
diff --git a/pthreads/src/pthread_equal.c b/pthreads/src/pthread_equal.c
deleted file mode 100644
index 5ddd82a..0000000
--- a/pthreads/src/pthread_equal.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * pthread_equal.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_equal (pthread_t t1, pthread_t t2)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function returns nonzero if t1 and t2 are equal, else
- * returns zero
- *
- * PARAMETERS
- * t1,
- * t2
- * thread IDs
- *
- *
- * DESCRIPTION
- * This function returns nonzero if t1 and t2 are equal, else
- * returns zero.
- *
- * RESULTS
- * non-zero if t1 and t2 refer to the same thread,
- * 0 t1 and t2 do not refer to the same thread
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- /*
- * We also accept NULL == NULL - treating NULL as a thread
- * for this special case, because there is no error that we can return.
- */
- result = ( t1.p == t2.p && t1.x == t2.x );
-
- return (result);
-
-} /* pthread_equal */
diff --git a/pthreads/src/pthread_exit.c b/pthreads/src/pthread_exit.c
deleted file mode 100644
index 37b3c09..0000000
--- a/pthreads/src/pthread_exit.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * pthread_exit.c
- *
- * Description:
- * This translation unit implements routines associated with exiting from
- * a thread.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#if !defined(_UWIN)
-/*# include <process.h> */
-#endif
-
-void
-pthread_exit (void *value_ptr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function terminates the calling thread, returning
- * the value 'value_ptr' to any joining thread.
- *
- * PARAMETERS
- * value_ptr
- * a generic data value (i.e. not the address of a value)
- *
- *
- * DESCRIPTION
- * This function terminates the calling thread, returning
- * the value 'value_ptr' to any joining thread.
- * NOTE: thread should be joinable.
- *
- * RESULTS
- * N/A
- *
- * ------------------------------------------------------
- */
-{
- ptw32_thread_t * sp;
-
- /*
- * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
- * unnecessarily.
- */
- sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
-
-#if defined(_UWIN)
- if (--pthread_count <= 0)
- exit ((int) value_ptr);
-#endif
-
- if (NULL == sp)
- {
- /*
- * A POSIX thread handle was never created. I.e. this is a
- * Win32 thread that has never called a pthreads-win32 routine that
- * required a POSIX handle.
- *
- * Implicit POSIX handles are cleaned up in ptw32_throw() now.
- */
-
-#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
- _endthreadex ((unsigned) (size_t) value_ptr);
-#else
- _endthread ();
-#endif
-
- /* Never reached */
- }
-
- sp->exitStatus = value_ptr;
-
- ptw32_throw (PTW32_EPS_EXIT);
-
- /* Never reached. */
-
-}
diff --git a/pthreads/src/pthread_getconcurrency.c b/pthreads/src/pthread_getconcurrency.c
deleted file mode 100644
index cf9e9c8..0000000
--- a/pthreads/src/pthread_getconcurrency.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * pthread_getconcurrency.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_getconcurrency (void)
-{
- return ptw32_concurrency;
-}
diff --git a/pthreads/src/pthread_getschedparam.c b/pthreads/src/pthread_getschedparam.c
deleted file mode 100644
index 0afcfb7..0000000
--- a/pthreads/src/pthread_getschedparam.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * sched_getschedparam.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_getschedparam (pthread_t thread, int *policy,
- struct sched_param *param)
-{
- int result;
-
- /* Validate the thread id. */
- result = pthread_kill (thread, 0);
- if (0 != result)
- {
- return result;
- }
-
- /*
- * Validate the policy and param args.
- * Check that a policy constant wasn't passed rather than &policy.
- */
- if (policy <= (int *) SCHED_MAX || param == NULL)
- {
- return EINVAL;
- }
-
- /* Fill out the policy. */
- *policy = SCHED_OTHER;
-
- /*
- * This function must return the priority value set by
- * the most recent pthread_setschedparam() or pthread_create()
- * for the target thread. It must not return the actual thread
- * priority as altered by any system priority adjustments etc.
- */
- param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority;
-
- return 0;
-}
diff --git a/pthreads/src/pthread_getspecific.c b/pthreads/src/pthread_getspecific.c
deleted file mode 100644
index 5ee1641..0000000
--- a/pthreads/src/pthread_getspecific.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * pthread_getspecific.c
- *
- * Description:
- * POSIX thread functions which implement thread-specific data (TSD).
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-void *
-pthread_getspecific (pthread_key_t key)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function returns the current value of key in the
- * calling thread. If no value has been set for 'key' in
- * the thread, NULL is returned.
- *
- * PARAMETERS
- * key
- * an instance of pthread_key_t
- *
- *
- * DESCRIPTION
- * This function returns the current value of key in the
- * calling thread. If no value has been set for 'key' in
- * the thread, NULL is returned.
- *
- * RESULTS
- * key value or NULL on failure
- *
- * ------------------------------------------------------
- */
-{
- void * ptr;
-
- if (key == NULL)
- {
- ptr = NULL;
- }
- else
- {
- int lasterror = GetLastError ();
-#if defined(RETAIN_WSALASTERROR)
- int lastWSAerror = WSAGetLastError ();
-#endif
- ptr = TlsGetValue (key->key);
-
- SetLastError (lasterror);
-#if defined(RETAIN_WSALASTERROR)
- WSASetLastError (lastWSAerror);
-#endif
- }
-
- return ptr;
-}
diff --git a/pthreads/src/pthread_getunique_np.c b/pthreads/src/pthread_getunique_np.c
deleted file mode 100644
index 4496c68..0000000
--- a/pthreads/src/pthread_getunique_np.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * pthread_getunique_np.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- *
- */
-unsigned __int64
-pthread_getunique_np (pthread_t thread)
-{
- return ((ptw32_thread_t*)thread.p)->seqNumber;
-}
diff --git a/pthreads/src/pthread_getw32threadhandle_np.c b/pthreads/src/pthread_getw32threadhandle_np.c
deleted file mode 100644
index 309a8f2..0000000
--- a/pthreads/src/pthread_getw32threadhandle_np.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * pthread_getw32threadhandle_np.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * pthread_getw32threadhandle_np()
- *
- * Returns the win32 thread handle that the POSIX
- * thread "thread" is running as.
- *
- * Applications can use the win32 handle to set
- * win32 specific attributes of the thread.
- */
-HANDLE
-pthread_getw32threadhandle_np (pthread_t thread)
-{
- return ((ptw32_thread_t *)thread.p)->threadH;
-}
-
-/*
- * pthread_getw32threadid_np()
- *
- * Returns the win32 thread id that the POSIX
- * thread "thread" is running as.
- */
-DWORD
-pthread_getw32threadid_np (pthread_t thread)
-{
- return ((ptw32_thread_t *)thread.p)->thread;
-}
diff --git a/pthreads/src/pthread_join.c b/pthreads/src/pthread_join.c
deleted file mode 100644
index c2b7c1e..0000000
--- a/pthreads/src/pthread_join.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * pthread_join.c
- *
- * Description:
- * This translation unit implements functions related to thread
- * synchronisation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * Not needed yet, but defining it should indicate clashes with build target
- * environment that should be fixed.
- */
-#if !defined(WINCE)
-# include <signal.h>
-#endif
-
-
-int
-pthread_join (pthread_t thread, void **value_ptr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function waits for 'thread' to terminate and
- * returns the thread's exit value if 'value_ptr' is not
- * NULL. This also detaches the thread on successful
- * completion.
- *
- * PARAMETERS
- * thread
- * an instance of pthread_t
- *
- * value_ptr
- * pointer to an instance of pointer to void
- *
- *
- * DESCRIPTION
- * This function waits for 'thread' to terminate and
- * returns the thread's exit value if 'value_ptr' is not
- * NULL. This also detaches the thread on successful
- * completion.
- * NOTE: detached threads cannot be joined or canceled
- *
- * RESULTS
- * 0 'thread' has completed
- * EINVAL thread is not a joinable thread,
- * ESRCH no thread could be found with ID 'thread',
- * ENOENT thread couldn't find it's own valid handle,
- * EDEADLK attempt to join thread with self
- *
- * ------------------------------------------------------
- */
-{
- int result;
- pthread_t self;
- ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
-
- if (NULL == tp
- || thread.x != tp->ptHandle.x)
- {
- result = ESRCH;
- }
- else if (PTHREAD_CREATE_DETACHED == tp->detachState)
- {
- result = EINVAL;
- }
- else
- {
- result = 0;
- }
-
- ptw32_mcs_lock_release(&node);
-
- if (result == 0)
- {
- /*
- * The target thread is joinable and can't be reused before we join it.
- */
- self = pthread_self();
-
- if (NULL == self.p)
- {
- result = ENOENT;
- }
- else if (pthread_equal (self, thread))
- {
- result = EDEADLK;
- }
- else
- {
- /*
- * Pthread_join is a cancelation point.
- * If we are canceled then our target thread must not be
- * detached (destroyed). This is guarranteed because
- * pthreadCancelableWait will not return if we
- * are canceled.
- */
- result = pthreadCancelableWait (tp->threadH);
-
- if (0 == result)
- {
- if (value_ptr != NULL)
- {
- *value_ptr = tp->exitStatus;
- }
-
- /*
- * The result of making multiple simultaneous calls to
- * pthread_join() or pthread_detach() specifying the same
- * target is undefined.
- */
- result = pthread_detach (thread);
- }
- else
- {
- result = ESRCH;
- }
- }
- }
-
- return (result);
-
-} /* pthread_join */
diff --git a/pthreads/src/pthread_key_create.c b/pthreads/src/pthread_key_create.c
deleted file mode 100644
index bdeee09..0000000
--- a/pthreads/src/pthread_key_create.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * pthread_key_create.c
- *
- * Description:
- * POSIX thread functions which implement thread-specific data (TSD).
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-/* TLS_OUT_OF_INDEXES not defined on WinCE */
-#if !defined(TLS_OUT_OF_INDEXES)
-#define TLS_OUT_OF_INDEXES 0xffffffff
-#endif
-
-int
-pthread_key_create (pthread_key_t * key, void (*destructor) (void *))
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function creates a thread-specific data key visible
- * to all threads. All existing and new threads have a value
- * NULL for key until set using pthread_setspecific. When any
- * thread with a non-NULL value for key terminates, 'destructor'
- * is called with key's current value for that thread.
- *
- * PARAMETERS
- * key
- * pointer to an instance of pthread_key_t
- *
- *
- * DESCRIPTION
- * This function creates a thread-specific data key visible
- * to all threads. All existing and new threads have a value
- * NULL for key until set using pthread_setspecific. When any
- * thread with a non-NULL value for key terminates, 'destructor'
- * is called with key's current value for that thread.
- *
- * RESULTS
- * 0 successfully created semaphore,
- * EAGAIN insufficient resources or PTHREAD_KEYS_MAX
- * exceeded,
- * ENOMEM insufficient memory to create the key,
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_key_t newkey;
-
- if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL)
- {
- result = ENOMEM;
- }
- else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
- {
- result = EAGAIN;
-
- free (newkey);
- newkey = NULL;
- }
- else if (destructor != NULL)
- {
- /*
- * Have to manage associations between thread and key;
- * Therefore, need a lock that allows competing threads
- * to gain exclusive access to the key->threads list.
- *
- * The mutex will only be created when it is first locked.
- */
- newkey->keyLock = 0;
- newkey->destructor = destructor;
- }
-
- *key = newkey;
-
- return (result);
-}
diff --git a/pthreads/src/pthread_key_delete.c b/pthreads/src/pthread_key_delete.c
deleted file mode 100644
index 09d70c6..0000000
--- a/pthreads/src/pthread_key_delete.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * pthread_key_delete.c
- *
- * Description:
- * POSIX thread functions which implement thread-specific data (TSD).
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_key_delete (pthread_key_t key)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function deletes a thread-specific data key. This
- * does not change the value of the thread specific data key
- * for any thread and does not run the key's destructor
- * in any thread so it should be used with caution.
- *
- * PARAMETERS
- * key
- * pointer to an instance of pthread_key_t
- *
- *
- * DESCRIPTION
- * This function deletes a thread-specific data key. This
- * does not change the value of the thread specific data key
- * for any thread and does not run the key's destructor
- * in any thread so it should be used with caution.
- *
- * RESULTS
- * 0 successfully deleted the key,
- * EINVAL key is invalid,
- *
- * ------------------------------------------------------
- */
-{
- ptw32_mcs_local_node_t keyLock;
- int result = 0;
-
- if (key != NULL)
- {
- if (key->threads != NULL && key->destructor != NULL)
- {
- ThreadKeyAssoc *assoc;
- ptw32_mcs_lock_acquire (&(key->keyLock), &keyLock);
- /*
- * Run through all Thread<-->Key associations
- * for this key.
- *
- * While we hold at least one of the locks guarding
- * the assoc, we know that the assoc pointed to by
- * key->threads is valid.
- */
- while ((assoc = (ThreadKeyAssoc *) key->threads) != NULL)
- {
- ptw32_mcs_local_node_t threadLock;
- ptw32_thread_t * thread = assoc->thread;
-
- if (assoc == NULL)
- {
- /* Finished */
- break;
- }
-
- ptw32_mcs_lock_acquire (&(thread->threadLock), &threadLock);
- /*
- * Since we are starting at the head of the key's threads
- * chain, this will also point key->threads at the next assoc.
- * While we hold key->keyLock, no other thread can insert
- * a new assoc via pthread_setspecific.
- */
- ptw32_tkAssocDestroy (assoc);
- ptw32_mcs_lock_release (&threadLock);
- ptw32_mcs_lock_release (&keyLock);
- }
- }
-
- TlsFree (key->key);
- if (key->destructor != NULL)
- {
- /* A thread could be holding the keyLock */
- ptw32_mcs_lock_acquire (&(key->keyLock), &keyLock);
- ptw32_mcs_lock_release (&keyLock);
- }
-
-#if defined( _DEBUG )
- memset ((char *) key, 0, sizeof (*key));
-#endif
- free (key);
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_kill.c b/pthreads/src/pthread_kill.c
deleted file mode 100644
index 5473b43..0000000
--- a/pthreads/src/pthread_kill.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * pthread_kill.c
- *
- * Description:
- * This translation unit implements the pthread_kill routine.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * Not needed yet, but defining it should indicate clashes with build target
- * environment that should be fixed.
- */
-#if !defined(WINCE)
-# include <signal.h>
-#endif
-
-int
-pthread_kill (pthread_t thread, int sig)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function requests that a signal be delivered to the
- * specified thread. If sig is zero, error checking is
- * performed but no signal is actually sent such that this
- * function can be used to check for a valid thread ID.
- *
- * PARAMETERS
- * thread reference to an instances of pthread_t
- * sig signal. Currently only a value of 0 is supported.
- *
- *
- * DESCRIPTION
- * This function requests that a signal be delivered to the
- * specified thread. If sig is zero, error checking is
- * performed but no signal is actually sent such that this
- * function can be used to check for a valid thread ID.
- *
- * RESULTS
- * ESRCH the thread is not a valid thread ID,
- * EINVAL the value of the signal is invalid
- * or unsupported.
- * 0 the signal was successfully sent.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- ptw32_thread_t * tp;
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
-
- tp = (ptw32_thread_t *) thread.p;
-
- if (NULL == tp
- || thread.x != tp->ptHandle.x
- || NULL == tp->threadH)
- {
- result = ESRCH;
- }
-
- ptw32_mcs_lock_release(&node);
-
- if (0 == result && 0 != sig)
- {
- /*
- * Currently does not support any signals.
- */
- result = EINVAL;
- }
-
- return result;
-
-} /* pthread_kill */
diff --git a/pthreads/src/pthread_mutex_consistent.c b/pthreads/src/pthread_mutex_consistent.c
deleted file mode 100644
index b7805e7..0000000
--- a/pthreads/src/pthread_mutex_consistent.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * pthread_mutex_consistent.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/*
- * From the Sun Multi-threaded Programming Guide
- *
- * robustness defines the behavior when the owner of the mutex terminates without unlocking the
- * mutex, usually because its process terminated abnormally. The value of robustness that is
- * defined in pthread.h is PTHREAD_MUTEX_ROBUST or PTHREAD_MUTEX_STALLED. The
- * default value is PTHREAD_MUTEX_STALLED .
- * ■ PTHREAD_MUTEX_STALLED
- * When the owner of the mutex terminates without unlocking the mutex, all subsequent calls
- * to pthread_mutex_lock() are blocked from progress in an unspecified manner.
- * ■ PTHREAD_MUTEX_ROBUST
- * When the owner of the mutex terminates without unlocking the mutex, the mutex is
- * unlocked. The next owner of this mutex acquires the mutex with an error return of
- * EOWNERDEAD.
- * Note – Your application must always check the return code from pthread_mutex_lock() for
- * a mutex initialized with the PTHREAD_MUTEX_ROBUST attribute.
- * ■ The new owner of this mutex should make the state protected by the mutex consistent.
- * This state might have been left inconsistent when the previous owner terminated.
- * ■ If the new owner is able to make the state consistent, call
- * pthread_mutex_consistent() for the mutex before unlocking the mutex. This
- * marks the mutex as consistent and subsequent calls to pthread_mutex_lock() and
- * pthread_mutex_unlock() will behave in the normal manner.
- * ■ If the new owner is not able to make the state consistent, do not call
- * pthread_mutex_consistent() for the mutex, but unlock the mutex.
- * All waiters are woken up and all subsequent calls to pthread_mutex_lock() fail to
- * acquire the mutex. The return code is ENOTRECOVERABLE. The mutex can be made
- * consistent by calling pthread_mutex_destroy() to uninitialize the mutex, and calling
- * pthread_mutex_int() to reinitialize the mutex.However, the state that was protected
- * by the mutex remains inconsistent and some form of application recovery is required.
- * ■ If the thread that acquires the lock with EOWNERDEAD terminates without unlocking the
- * mutex, the next owner acquires the lock with an EOWNERDEAD return code.
- */
-#if !defined(_UWIN)
-/*# include <process.h> */
-#endif
-#include "pthread.h"
-#include "implement.h"
-
-INLINE
-int
-ptw32_robust_mutex_inherit(pthread_mutex_t * mutex)
-{
- int result;
- pthread_mutex_t mx = *mutex;
- ptw32_robust_node_t* robust = mx->robustNode;
-
- switch ((LONG)PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR)&robust->stateInconsistent,
- (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT,
- (PTW32_INTERLOCKED_LONG)-1 /* The terminating thread sets this */))
- {
- case -1L:
- result = EOWNERDEAD;
- break;
- case (LONG)PTW32_ROBUST_NOTRECOVERABLE:
- result = ENOTRECOVERABLE;
- break;
- default:
- result = 0;
- break;
- }
-
- return result;
-}
-
-/*
- * The next two internal support functions depend on only being
- * called by the thread that owns the robust mutex. This enables
- * us to avoid additional locks.
- * Any mutex currently in the thread's robust mutex list is held
- * by the thread, again eliminating the need for locks.
- * The forward/backward links allow the thread to unlock mutexes
- * in any order, not necessarily the reverse locking order.
- * This is all possible because it is an error if a thread that
- * does not own the [robust] mutex attempts to unlock it.
- */
-
-INLINE
-void
-ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self)
-{
- ptw32_robust_node_t** list;
- pthread_mutex_t mx = *mutex;
- ptw32_thread_t* tp = (ptw32_thread_t*)self.p;
- ptw32_robust_node_t* robust = mx->robustNode;
-
- list = &tp->robustMxList;
- mx->ownerThread = self;
- if (NULL == *list)
- {
- robust->prev = NULL;
- robust->next = NULL;
- *list = robust;
- }
- else
- {
- robust->prev = NULL;
- robust->next = *list;
- (*list)->prev = robust;
- *list = robust;
- }
-}
-
-INLINE
-void
-ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp)
-{
- ptw32_robust_node_t** list;
- pthread_mutex_t mx = *mutex;
- ptw32_robust_node_t* robust = mx->robustNode;
-
- list = &(((ptw32_thread_t*)mx->ownerThread.p)->robustMxList);
- mx->ownerThread.p = otp;
- if (robust->next != NULL)
- {
- robust->next->prev = robust->prev;
- }
- if (robust->prev != NULL)
- {
- robust->prev->next = robust->next;
- }
- if (*list == robust)
- {
- *list = robust->next;
- }
-}
-
-
-int
-pthread_mutex_consistent (pthread_mutex_t* mutex)
-{
- pthread_mutex_t mx = *mutex;
- int result = 0;
-
- /*
- * Let the system deal with invalid pointers.
- */
- if (mx == NULL)
- {
- return EINVAL;
- }
-
- if (mx->kind >= 0
- || (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT != PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent,
- (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_CONSISTENT,
- (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT))
- {
- result = EINVAL;
- }
-
- return (result);
-}
-
diff --git a/pthreads/src/pthread_mutex_destroy.c b/pthreads/src/pthread_mutex_destroy.c
deleted file mode 100644
index 7b8c9cd..0000000
--- a/pthreads/src/pthread_mutex_destroy.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * pthread_mutex_destroy.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutex_destroy (pthread_mutex_t * mutex)
-{
- int result = 0;
- pthread_mutex_t mx;
-
- /*
- * Let the system deal with invalid pointers.
- */
-
- /*
- * Check to see if we have something to delete.
- */
- if (*mutex < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
- {
- mx = *mutex;
-
- result = pthread_mutex_trylock (&mx);
-
- /*
- * If trylock succeeded and the mutex is not recursively locked it
- * can be destroyed.
- */
- if (0 == result || ENOTRECOVERABLE == result)
- {
- if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count)
- {
- /*
- * FIXME!!!
- * The mutex isn't held by another thread but we could still
- * be too late invalidating the mutex below since another thread
- * may already have entered mutex_lock and the check for a valid
- * *mutex != NULL.
- */
- *mutex = NULL;
-
- result = (0 == result)?pthread_mutex_unlock(&mx):0;
-
- if (0 == result)
- {
- if (mx->robustNode != NULL)
- {
- free(mx->robustNode);
- }
- if (!CloseHandle (mx->event))
- {
- *mutex = mx;
- result = EINVAL;
- }
- else
- {
- free (mx);
- }
- }
- else
- {
- /*
- * Restore the mutex before we return the error.
- */
- *mutex = mx;
- }
- }
- else /* mx->recursive_count > 1 */
- {
- /*
- * The mutex must be recursive and already locked by us (this thread).
- */
- mx->recursive_count--; /* Undo effect of pthread_mutex_trylock() above */
- result = EBUSY;
- }
- }
- }
- else
- {
- ptw32_mcs_local_node_t node;
-
- /*
- * See notes in ptw32_mutex_check_need_init() above also.
- */
-
- ptw32_mcs_lock_acquire(&ptw32_mutex_test_init_lock, &node);
-
- /*
- * Check again.
- */
- if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised mutex that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this mutex will get an EINVAL.
- */
- *mutex = NULL;
- }
- else
- {
- /*
- * The mutex has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
- ptw32_mcs_lock_release(&node);
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_mutex_init.c b/pthreads/src/pthread_mutex_init.c
deleted file mode 100644
index daf805e..0000000
--- a/pthreads/src/pthread_mutex_init.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * pthread_mutex_init.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
-{
- int result = 0;
- pthread_mutex_t mx;
-
- if (mutex == NULL)
- {
- return EINVAL;
- }
-
- if (attr != NULL && *attr != NULL)
- {
- if ((*attr)->pshared == PTHREAD_PROCESS_SHARED)
- {
- /*
- * Creating mutex that can be shared between
- * processes.
- */
-#if _POSIX_THREAD_PROCESS_SHARED >= 0
-
- /*
- * Not implemented yet.
- */
-
-#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet.
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
- }
- }
-
- mx = (pthread_mutex_t) calloc (1, sizeof (*mx));
-
- if (mx == NULL)
- {
- result = ENOMEM;
- }
- else
- {
- mx->lock_idx = 0;
- mx->recursive_count = 0;
- mx->robustNode = NULL;
- if (attr == NULL || *attr == NULL)
- {
- mx->kind = PTHREAD_MUTEX_DEFAULT;
- }
- else
- {
- mx->kind = (*attr)->kind;
- if ((*attr)->robustness == PTHREAD_MUTEX_ROBUST)
- {
- /*
- * Use the negative range to represent robust types.
- * Replaces a memory fetch with a register negate and incr
- * in pthread_mutex_lock etc.
- *
- * Map 0,1,..,n to -1,-2,..,(-n)-1
- */
- mx->kind = -mx->kind - 1;
-
- mx->robustNode = (ptw32_robust_node_t*) malloc(sizeof(ptw32_robust_node_t));
- mx->robustNode->stateInconsistent = PTW32_ROBUST_CONSISTENT;
- mx->robustNode->mx = mx;
- mx->robustNode->next = NULL;
- mx->robustNode->prev = NULL;
- }
- }
-
- mx->ownerThread.p = NULL;
-
- mx->event = CreateEvent (NULL, PTW32_FALSE, /* manual reset = No */
- PTW32_FALSE, /* initial state = not signaled */
- NULL); /* event name */
-
- if (0 == mx->event)
- {
- result = ENOSPC;
- free (mx);
- mx = NULL;
- }
- }
-
- *mutex = mx;
-
- return (result);
-}
diff --git a/pthreads/src/pthread_mutex_lock.c b/pthreads/src/pthread_mutex_lock.c
deleted file mode 100644
index eee9abe..0000000
--- a/pthreads/src/pthread_mutex_lock.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * pthread_mutex_lock.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if !defined(_UWIN)
-/*# include <process.h> */
-#endif
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_mutex_lock (pthread_mutex_t * mutex)
-{
- int kind;
- pthread_mutex_t mx;
- int result = 0;
-
- /*
- * Let the system deal with invalid pointers.
- */
- if (*mutex == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static mutex. We check
- * again inside the guarded section of ptw32_mutex_check_need_init()
- * to avoid race conditions.
- */
- if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
- {
- if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
- {
- return (result);
- }
- }
-
- mx = *mutex;
- kind = mx->kind;
-
- if (kind >= 0)
- {
- /* Non-robust */
- if (PTHREAD_MUTEX_NORMAL == kind)
- {
- if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1) != 0)
- {
- while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
- {
- result = EINVAL;
- break;
- }
- }
- }
- }
- else
- {
- pthread_t self = pthread_self();
-
- if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1,
- (PTW32_INTERLOCKED_LONG) 0) == 0)
- {
- mx->recursive_count = 1;
- mx->ownerThread = self;
- }
- else
- {
- if (pthread_equal (mx->ownerThread, self))
- {
- if (kind == PTHREAD_MUTEX_RECURSIVE)
- {
- mx->recursive_count++;
- }
- else
- {
- result = EDEADLK;
- }
- }
- else
- {
- while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
- {
- result = EINVAL;
- break;
- }
- }
-
- if (0 == result)
- {
- mx->recursive_count = 1;
- mx->ownerThread = self;
- }
- }
- }
- }
- }
- else
- {
- /*
- * Robust types
- * All types record the current owner thread.
- * The mutex is added to a per thread list when ownership is acquired.
- */
- ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
-
- if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
- (PTW32_INTERLOCKED_LONGPTR)statePtr,
- (PTW32_INTERLOCKED_LONG)0))
- {
- result = ENOTRECOVERABLE;
- }
- else
- {
- pthread_t self = pthread_self();
-
- kind = -kind - 1; /* Convert to non-robust range */
-
- if (PTHREAD_MUTEX_NORMAL == kind)
- {
- if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1) != 0)
- {
- while (0 == (result = ptw32_robust_mutex_inherit(mutex))
- && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
- {
- result = EINVAL;
- break;
- }
- if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
- PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
- (PTW32_INTERLOCKED_LONGPTR)statePtr,
- (PTW32_INTERLOCKED_LONG)0))
- {
- /* Unblock the next thread */
- SetEvent(mx->event);
- result = ENOTRECOVERABLE;
- break;
- }
- }
- }
- if (0 == result || EOWNERDEAD == result)
- {
- /*
- * Add mutex to the per-thread robust mutex currently-held list.
- * If the thread terminates, all mutexes in this list will be unlocked.
- */
- ptw32_robust_mutex_add(mutex, self);
- }
- }
- else
- {
- if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1,
- (PTW32_INTERLOCKED_LONG) 0) == 0)
- {
- mx->recursive_count = 1;
- /*
- * Add mutex to the per-thread robust mutex currently-held list.
- * If the thread terminates, all mutexes in this list will be unlocked.
- */
- ptw32_robust_mutex_add(mutex, self);
- }
- else
- {
- if (pthread_equal (mx->ownerThread, self))
- {
- if (PTHREAD_MUTEX_RECURSIVE == kind)
- {
- mx->recursive_count++;
- }
- else
- {
- result = EDEADLK;
- }
- }
- else
- {
- while (0 == (result = ptw32_robust_mutex_inherit(mutex))
- && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
- {
- result = EINVAL;
- break;
- }
- if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
- PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
- (PTW32_INTERLOCKED_LONGPTR)statePtr,
- (PTW32_INTERLOCKED_LONG)0))
- {
- /* Unblock the next thread */
- SetEvent(mx->event);
- result = ENOTRECOVERABLE;
- break;
- }
- }
-
- if (0 == result || EOWNERDEAD == result)
- {
- mx->recursive_count = 1;
- /*
- * Add mutex to the per-thread robust mutex currently-held list.
- * If the thread terminates, all mutexes in this list will be unlocked.
- */
- ptw32_robust_mutex_add(mutex, self);
- }
- }
- }
- }
- }
- }
-
- return (result);
-}
-
diff --git a/pthreads/src/pthread_mutex_timedlock.c b/pthreads/src/pthread_mutex_timedlock.c
deleted file mode 100644
index 1745316..0000000
--- a/pthreads/src/pthread_mutex_timedlock.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * pthread_mutex_timedlock.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-static INLINE int
-ptw32_timed_eventwait (HANDLE event, const struct timespec *abstime)
- /*
- * ------------------------------------------------------
- * DESCRIPTION
- * This function waits on an event until signaled or until
- * abstime passes.
- * If abstime has passed when this routine is called then
- * it returns a result to indicate this.
- *
- * If 'abstime' is a NULL pointer then this function will
- * block until it can successfully decrease the value or
- * until interrupted by a signal.
- *
- * This routine is not a cancelation point.
- *
- * RESULTS
- * 0 successfully signaled,
- * ETIMEDOUT abstime passed
- * EINVAL 'event' is not a valid event,
- *
- * ------------------------------------------------------
- */
-{
-
- DWORD milliseconds;
- DWORD status;
-
- if (event == NULL)
- {
- return EINVAL;
- }
- else
- {
- if (abstime == NULL)
- {
- milliseconds = INFINITE;
- }
- else
- {
- /*
- * Calculate timeout as milliseconds from current system time.
- */
- milliseconds = ptw32_relmillisecs (abstime);
- }
-
- status = WaitForSingleObject (event, milliseconds);
-
- if (status == WAIT_OBJECT_0)
- {
- return 0;
- }
- else if (status == WAIT_TIMEOUT)
- {
- return ETIMEDOUT;
- }
- else
- {
- return EINVAL;
- }
- }
-
- return 0;
-
-} /* ptw32_timed_semwait */
-
-
-int
-pthread_mutex_timedlock (pthread_mutex_t * mutex,
- const struct timespec *abstime)
-{
- pthread_mutex_t mx;
- int kind;
- int result = 0;
-
- /*
- * Let the system deal with invalid pointers.
- */
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static mutex. We check
- * again inside the guarded section of ptw32_mutex_check_need_init()
- * to avoid race conditions.
- */
- if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
- {
- if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
- {
- return (result);
- }
- }
-
- mx = *mutex;
- kind = mx->kind;
-
- if (kind >= 0)
- {
- if (mx->kind == PTHREAD_MUTEX_NORMAL)
- {
- if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1) != 0)
- {
- while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
- {
- return result;
- }
- }
- }
- }
- else
- {
- pthread_t self = pthread_self();
-
- if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1,
- (PTW32_INTERLOCKED_LONG) 0) == 0)
- {
- mx->recursive_count = 1;
- mx->ownerThread = self;
- }
- else
- {
- if (pthread_equal (mx->ownerThread, self))
- {
- if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
- {
- mx->recursive_count++;
- }
- else
- {
- return EDEADLK;
- }
- }
- else
- {
- while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
- {
- return result;
- }
- }
-
- mx->recursive_count = 1;
- mx->ownerThread = self;
- }
- }
- }
- }
- else
- {
- /*
- * Robust types
- * All types record the current owner thread.
- * The mutex is added to a per thread list when ownership is acquired.
- */
- ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
-
- if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
- (PTW32_INTERLOCKED_LONGPTR)statePtr,
- (PTW32_INTERLOCKED_LONG)0))
- {
- result = ENOTRECOVERABLE;
- }
- else
- {
- pthread_t self = pthread_self();
-
- kind = -kind - 1; /* Convert to non-robust range */
-
- if (PTHREAD_MUTEX_NORMAL == kind)
- {
- if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1) != 0)
- {
- while (0 == (result = ptw32_robust_mutex_inherit(mutex))
- && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
- {
- return result;
- }
- if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
- PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
- (PTW32_INTERLOCKED_LONGPTR)statePtr,
- (PTW32_INTERLOCKED_LONG)0))
- {
- /* Unblock the next thread */
- SetEvent(mx->event);
- result = ENOTRECOVERABLE;
- break;
- }
- }
-
- if (0 == result || EOWNERDEAD == result)
- {
- /*
- * Add mutex to the per-thread robust mutex currently-held list.
- * If the thread terminates, all mutexes in this list will be unlocked.
- */
- ptw32_robust_mutex_add(mutex, self);
- }
- }
- }
- else
- {
- pthread_t self = pthread_self();
-
- if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1,
- (PTW32_INTERLOCKED_LONG) 0))
- {
- mx->recursive_count = 1;
- /*
- * Add mutex to the per-thread robust mutex currently-held list.
- * If the thread terminates, all mutexes in this list will be unlocked.
- */
- ptw32_robust_mutex_add(mutex, self);
- }
- else
- {
- if (pthread_equal (mx->ownerThread, self))
- {
- if (PTHREAD_MUTEX_RECURSIVE == kind)
- {
- mx->recursive_count++;
- }
- else
- {
- return EDEADLK;
- }
- }
- else
- {
- while (0 == (result = ptw32_robust_mutex_inherit(mutex))
- && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) -1) != 0)
- {
- if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
- {
- return result;
- }
- }
-
- if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
- PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
- (PTW32_INTERLOCKED_LONGPTR)statePtr,
- (PTW32_INTERLOCKED_LONG)0))
- {
- /* Unblock the next thread */
- SetEvent(mx->event);
- result = ENOTRECOVERABLE;
- }
- else if (0 == result || EOWNERDEAD == result)
- {
- mx->recursive_count = 1;
- /*
- * Add mutex to the per-thread robust mutex currently-held list.
- * If the thread terminates, all mutexes in this list will be unlocked.
- */
- ptw32_robust_mutex_add(mutex, self);
- }
- }
- }
- }
- }
- }
-
- return result;
-}
diff --git a/pthreads/src/pthread_mutex_trylock.c b/pthreads/src/pthread_mutex_trylock.c
deleted file mode 100644
index d6b6872..0000000
--- a/pthreads/src/pthread_mutex_trylock.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * pthread_mutex_trylock.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutex_trylock (pthread_mutex_t * mutex)
-{
- pthread_mutex_t mx;
- int kind;
- int result = 0;
-
- /*
- * Let the system deal with invalid pointers.
- */
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static mutex. We check
- * again inside the guarded section of ptw32_mutex_check_need_init()
- * to avoid race conditions.
- */
- if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
- {
- if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
- {
- return (result);
- }
- }
-
- mx = *mutex;
- kind = mx->kind;
-
- if (kind >= 0)
- {
- /* Non-robust */
- if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG (
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1,
- (PTW32_INTERLOCKED_LONG) 0))
- {
- if (kind != PTHREAD_MUTEX_NORMAL)
- {
- mx->recursive_count = 1;
- mx->ownerThread = pthread_self ();
- }
- }
- else
- {
- if (kind == PTHREAD_MUTEX_RECURSIVE &&
- pthread_equal (mx->ownerThread, pthread_self ()))
- {
- mx->recursive_count++;
- }
- else
- {
- result = EBUSY;
- }
- }
- }
- else
- {
- /*
- * Robust types
- * All types record the current owner thread.
- * The mutex is added to a per thread list when ownership is acquired.
- */
- pthread_t self;
- ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
-
- if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
- PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
- (PTW32_INTERLOCKED_LONGPTR)statePtr,
- (PTW32_INTERLOCKED_LONG)0))
- {
- return ENOTRECOVERABLE;
- }
-
- self = pthread_self();
- kind = -kind - 1; /* Convert to non-robust range */
-
- if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG (
- (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 1,
- (PTW32_INTERLOCKED_LONG) 0))
- {
- if (kind != PTHREAD_MUTEX_NORMAL)
- {
- mx->recursive_count = 1;
- }
- ptw32_robust_mutex_add(mutex, self);
- }
- else
- {
- if (PTHREAD_MUTEX_RECURSIVE == kind &&
- pthread_equal (mx->ownerThread, pthread_self ()))
- {
- mx->recursive_count++;
- }
- else
- {
- if (EOWNERDEAD == (result = ptw32_robust_mutex_inherit(mutex)))
- {
- mx->recursive_count = 1;
- ptw32_robust_mutex_add(mutex, self);
- }
- else
- {
- if (0 == result)
- {
- result = EBUSY;
- }
- }
- }
- }
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_mutex_unlock.c b/pthreads/src/pthread_mutex_unlock.c
deleted file mode 100644
index 3d65d1a..0000000
--- a/pthreads/src/pthread_mutex_unlock.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * pthread_mutex_unlock.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutex_unlock (pthread_mutex_t * mutex)
-{
- int result = 0;
- int kind;
- pthread_mutex_t mx;
-
- /*
- * Let the system deal with invalid pointers.
- */
-
- mx = *mutex;
-
- /*
- * If the thread calling us holds the mutex then there is no
- * race condition. If another thread holds the
- * lock then we shouldn't be in here.
- */
- if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
- {
- kind = mx->kind;
-
- if (kind >= 0)
- {
- if (kind == PTHREAD_MUTEX_NORMAL)
- {
- LONG idx;
-
- idx = (LONG) PTW32_INTERLOCKED_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR)&mx->lock_idx,
- (PTW32_INTERLOCKED_LONG)0);
- if (idx != 0)
- {
- if (idx < 0)
- {
- /*
- * Someone may be waiting on that mutex.
- */
- if (SetEvent (mx->event) == 0)
- {
- result = EINVAL;
- }
- }
- }
- }
- else
- {
- if (pthread_equal (mx->ownerThread, pthread_self()))
- {
- if (kind != PTHREAD_MUTEX_RECURSIVE
- || 0 == --mx->recursive_count)
- {
- mx->ownerThread.p = NULL;
-
- if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR)&mx->lock_idx,
- (PTW32_INTERLOCKED_LONG)0) < 0L)
- {
- /* Someone may be waiting on that mutex */
- if (SetEvent (mx->event) == 0)
- {
- result = EINVAL;
- }
- }
- }
- }
- else
- {
- result = EPERM;
- }
- }
- }
- else
- {
- /* Robust types */
- pthread_t self = pthread_self();
- kind = -kind - 1; /* Convert to non-robust range */
-
- /*
- * The thread must own the lock regardless of type if the mutex
- * is robust.
- */
- if (pthread_equal (mx->ownerThread, self))
- {
- PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->robustNode->stateInconsistent,
- (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE,
- (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT);
- if (PTHREAD_MUTEX_NORMAL == kind)
- {
- ptw32_robust_mutex_remove(mutex, NULL);
-
- if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 0) < 0)
- {
- /*
- * Someone may be waiting on that mutex.
- */
- if (SetEvent (mx->event) == 0)
- {
- result = EINVAL;
- }
- }
- }
- else
- {
- if (kind != PTHREAD_MUTEX_RECURSIVE
- || 0 == --mx->recursive_count)
- {
- ptw32_robust_mutex_remove(mutex, NULL);
-
- if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 0) < 0)
- {
- /*
- * Someone may be waiting on that mutex.
- */
- if (SetEvent (mx->event) == 0)
- {
- result = EINVAL;
- }
- }
- }
- }
- }
- else
- {
- result = EPERM;
- }
- }
- }
- else if (mx != PTHREAD_MUTEX_INITIALIZER)
- {
- result = EINVAL;
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_mutexattr_destroy.c b/pthreads/src/pthread_mutexattr_destroy.c
deleted file mode 100644
index 9d424bf..0000000
--- a/pthreads/src/pthread_mutexattr_destroy.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * pthread_mutexattr_destroy.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Destroys a mutex attributes object. The object can
- * no longer be used.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- *
- * DESCRIPTION
- * Destroys a mutex attributes object. The object can
- * no longer be used.
- *
- * NOTES:
- * 1) Does not affect mutexes created using 'attr'
- *
- * RESULTS
- * 0 successfully released attr,
- * EINVAL 'attr' is invalid.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if (attr == NULL || *attr == NULL)
- {
- result = EINVAL;
- }
- else
- {
- pthread_mutexattr_t ma = *attr;
-
- *attr = NULL;
- free (ma);
- }
-
- return (result);
-} /* pthread_mutexattr_destroy */
diff --git a/pthreads/src/pthread_mutexattr_getkind_np.c b/pthreads/src/pthread_mutexattr_getkind_np.c
deleted file mode 100644
index 2d82ec6..0000000
--- a/pthreads/src/pthread_mutexattr_getkind_np.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * pthread_mutexattr_getkind_np.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_mutexattr_getkind_np (pthread_mutexattr_t * attr, int *kind)
-{
- return pthread_mutexattr_gettype (attr, kind);
-}
diff --git a/pthreads/src/pthread_mutexattr_getpshared.c b/pthreads/src/pthread_mutexattr_getpshared.c
deleted file mode 100644
index 42f9589..0000000
--- a/pthreads/src/pthread_mutexattr_getpshared.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * pthread_mutexattr_getpshared.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Determine whether mutexes created with 'attr' can be
- * shared between processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * pshared
- * will be set to one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- *
- * DESCRIPTION
- * Mutexes creatd with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- * NOTES:
- * 1) pshared mutexes MUST be allocated in shared
- * memory.
- * 2) The following macro is defined if shared mutexes
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully retrieved attribute,
- * EINVAL 'attr' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) && (pshared != NULL))
- {
- *pshared = (*attr)->pshared;
- result = 0;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_mutexattr_getpshared */
diff --git a/pthreads/src/pthread_mutexattr_getrobust.c b/pthreads/src/pthread_mutexattr_getrobust.c
deleted file mode 100644
index be00483..0000000
--- a/pthreads/src/pthread_mutexattr_getrobust.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * pthread_mutexattr_getrobust.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_getrobust (const pthread_mutexattr_t * attr, int * robust)
- /*
- * ------------------------------------------------------
- *
- * DOCPUBLIC
- * The pthread_mutexattr_setrobust() and
- * pthread_mutexattr_getrobust() functions respectively set and
- * get the mutex robust attribute. This attribute is set in the
- * robust parameter to these functions.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * robust
- * must be one of:
- *
- * PTHREAD_MUTEX_STALLED
- *
- * PTHREAD_MUTEX_ROBUST
- *
- * DESCRIPTION
- * The pthread_mutexattr_setrobust() and
- * pthread_mutexattr_getrobust() functions respectively set and
- * get the mutex robust attribute. This attribute is set in the
- * robust parameter to these functions. The default value of the
- * robust attribute is PTHREAD_MUTEX_STALLED.
- *
- * The robustness of mutex is contained in the robustness attribute
- * of the mutex attributes. Valid mutex robustness values are:
- *
- * PTHREAD_MUTEX_STALLED
- * No special actions are taken if the owner of the mutex is
- * terminated while holding the mutex lock. This can lead to
- * deadlocks if no other thread can unlock the mutex.
- * This is the default value.
- *
- * PTHREAD_MUTEX_ROBUST
- * If the process containing the owning thread of a robust mutex
- * terminates while holding the mutex lock, the next thread that
- * acquires the mutex shall be notified about the termination by
- * the return value [EOWNERDEAD] from the locking function. If the
- * owning thread of a robust mutex terminates while holding the mutex
- * lock, the next thread that acquires the mutex may be notified
- * about the termination by the return value [EOWNERDEAD]. The
- * notified thread can then attempt to mark the state protected by
- * the mutex as consistent again by a call to
- * pthread_mutex_consistent(). After a subsequent successful call to
- * pthread_mutex_unlock(), the mutex lock shall be released and can
- * be used normally by other threads. If the mutex is unlocked without
- * a call to pthread_mutex_consistent(), it shall be in a permanently
- * unusable state and all attempts to lock the mutex shall fail with
- * the error [ENOTRECOVERABLE]. The only permissible operation on such
- * a mutex is pthread_mutex_destroy().
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or 'robust' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result = EINVAL;
-
- if ((attr != NULL && *attr != NULL && robust != NULL))
- {
- *robust = (*attr)->robustness;
- result = 0;
- }
-
- return (result);
-} /* pthread_mutexattr_getrobust */
diff --git a/pthreads/src/pthread_mutexattr_gettype.c b/pthreads/src/pthread_mutexattr_gettype.c
deleted file mode 100644
index c63fcfa..0000000
--- a/pthreads/src/pthread_mutexattr_gettype.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * pthread_mutexattr_gettype.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind)
-{
- int result = 0;
-
- if (attr != NULL && *attr != NULL && kind != NULL)
- {
- *kind = (*attr)->kind;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_mutexattr_init.c b/pthreads/src/pthread_mutexattr_init.c
deleted file mode 100644
index d2797ff..0000000
--- a/pthreads/src/pthread_mutexattr_init.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * pthread_mutexattr_init.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_init (pthread_mutexattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Initializes a mutex attributes object with default
- * attributes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- *
- * DESCRIPTION
- * Initializes a mutex attributes object with default
- * attributes.
- *
- * NOTES:
- * 1) Used to define mutex types
- *
- * RESULTS
- * 0 successfully initialized attr,
- * ENOMEM insufficient memory for attr.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_mutexattr_t ma;
-
- ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma));
-
- if (ma == NULL)
- {
- result = ENOMEM;
- }
- else
- {
- ma->pshared = PTHREAD_PROCESS_PRIVATE;
- ma->kind = PTHREAD_MUTEX_DEFAULT;
- }
-
- *attr = ma;
-
- return (result);
-} /* pthread_mutexattr_init */
diff --git a/pthreads/src/pthread_mutexattr_setkind_np.c b/pthreads/src/pthread_mutexattr_setkind_np.c
deleted file mode 100644
index faa9366..0000000
--- a/pthreads/src/pthread_mutexattr_setkind_np.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * pthread_mutexattr_setkind_np.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_mutexattr_setkind_np (pthread_mutexattr_t * attr, int kind)
-{
- return pthread_mutexattr_settype (attr, kind);
-}
diff --git a/pthreads/src/pthread_mutexattr_setpshared.c b/pthreads/src/pthread_mutexattr_setpshared.c
deleted file mode 100644
index cfa6f71..0000000
--- a/pthreads/src/pthread_mutexattr_setpshared.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * pthread_mutexattr_setpshared.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Mutexes created with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * pshared
- * must be one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- * DESCRIPTION
- * Mutexes creatd with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- *
- * NOTES:
- * 1) pshared mutexes MUST be allocated in shared
- * memory.
- *
- * 2) The following macro is defined if shared mutexes
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or pshared is invalid,
- * ENOSYS PTHREAD_PROCESS_SHARED not supported,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) &&
- ((pshared == PTHREAD_PROCESS_SHARED) ||
- (pshared == PTHREAD_PROCESS_PRIVATE)))
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
-
-#if !defined( _POSIX_THREAD_PROCESS_SHARED )
-
- result = ENOSYS;
- pshared = PTHREAD_PROCESS_PRIVATE;
-
-#else
-
- result = 0;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- else
- {
- result = 0;
- }
-
- (*attr)->pshared = pshared;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_mutexattr_setpshared */
diff --git a/pthreads/src/pthread_mutexattr_setrobust.c b/pthreads/src/pthread_mutexattr_setrobust.c
deleted file mode 100644
index b1acef7..0000000
--- a/pthreads/src/pthread_mutexattr_setrobust.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * pthread_mutexattr_setrobust.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_setrobust (pthread_mutexattr_t * attr, int robust)
- /*
- * ------------------------------------------------------
- *
- * DOCPUBLIC
- * The pthread_mutexattr_setrobust() and
- * pthread_mutexattr_getrobust() functions respectively set and
- * get the mutex robust attribute. This attribute is set in the
- * robust parameter to these functions.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * robust
- * must be one of:
- *
- * PTHREAD_MUTEX_STALLED
- *
- * PTHREAD_MUTEX_ROBUST
- *
- * DESCRIPTION
- * The pthread_mutexattr_setrobust() and
- * pthread_mutexattr_getrobust() functions respectively set and
- * get the mutex robust attribute. This attribute is set in the
- * robust parameter to these functions. The default value of the
- * robust attribute is PTHREAD_MUTEX_STALLED.
- *
- * The robustness of mutex is contained in the robustness attribute
- * of the mutex attributes. Valid mutex robustness values are:
- *
- * PTHREAD_MUTEX_STALLED
- * No special actions are taken if the owner of the mutex is
- * terminated while holding the mutex lock. This can lead to
- * deadlocks if no other thread can unlock the mutex.
- * This is the default value.
- *
- * PTHREAD_MUTEX_ROBUST
- * If the process containing the owning thread of a robust mutex
- * terminates while holding the mutex lock, the next thread that
- * acquires the mutex shall be notified about the termination by
- * the return value [EOWNERDEAD] from the locking function. If the
- * owning thread of a robust mutex terminates while holding the mutex
- * lock, the next thread that acquires the mutex may be notified
- * about the termination by the return value [EOWNERDEAD]. The
- * notified thread can then attempt to mark the state protected by
- * the mutex as consistent again by a call to
- * pthread_mutex_consistent(). After a subsequent successful call to
- * pthread_mutex_unlock(), the mutex lock shall be released and can
- * be used normally by other threads. If the mutex is unlocked without
- * a call to pthread_mutex_consistent(), it shall be in a permanently
- * unusable state and all attempts to lock the mutex shall fail with
- * the error [ENOTRECOVERABLE]. The only permissible operation on such
- * a mutex is pthread_mutex_destroy().
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or 'robust' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result = EINVAL;
-
- if ((attr != NULL && *attr != NULL))
- {
- switch (robust)
- {
- case PTHREAD_MUTEX_STALLED:
- case PTHREAD_MUTEX_ROBUST:
- (*attr)->robustness = robust;
- result = 0;
- break;
- }
- }
-
- return (result);
-} /* pthread_mutexattr_setrobust */
diff --git a/pthreads/src/pthread_mutexattr_settype.c b/pthreads/src/pthread_mutexattr_settype.c
deleted file mode 100644
index 8365daf..0000000
--- a/pthreads/src/pthread_mutexattr_settype.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * pthread_mutexattr_settype.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind)
- /*
- * ------------------------------------------------------
- *
- * DOCPUBLIC
- * The pthread_mutexattr_settype() and
- * pthread_mutexattr_gettype() functions respectively set and
- * get the mutex type attribute. This attribute is set in the
- * type parameter to these functions.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * type
- * must be one of:
- *
- * PTHREAD_MUTEX_DEFAULT
- *
- * PTHREAD_MUTEX_NORMAL
- *
- * PTHREAD_MUTEX_ERRORCHECK
- *
- * PTHREAD_MUTEX_RECURSIVE
- *
- * DESCRIPTION
- * The pthread_mutexattr_settype() and
- * pthread_mutexattr_gettype() functions respectively set and
- * get the mutex type attribute. This attribute is set in the
- * type parameter to these functions. The default value of the
- * type attribute is PTHREAD_MUTEX_DEFAULT.
- *
- * The type of mutex is contained in the type attribute of the
- * mutex attributes. Valid mutex types include:
- *
- * PTHREAD_MUTEX_NORMAL
- * This type of mutex does not detect deadlock. A
- * thread attempting to relock this mutex without
- * first unlocking it will deadlock. Attempting to
- * unlock a mutex locked by a different thread
- * results in undefined behavior. Attempting to
- * unlock an unlocked mutex results in undefined
- * behavior.
- *
- * PTHREAD_MUTEX_ERRORCHECK
- * This type of mutex provides error checking. A
- * thread attempting to relock this mutex without
- * first unlocking it will return with an error. A
- * thread attempting to unlock a mutex which another
- * thread has locked will return with an error. A
- * thread attempting to unlock an unlocked mutex will
- * return with an error.
- *
- * PTHREAD_MUTEX_DEFAULT
- * Same as PTHREAD_MUTEX_NORMAL.
- *
- * PTHREAD_MUTEX_RECURSIVE
- * A thread attempting to relock this mutex without
- * first unlocking it will succeed in locking the
- * mutex. The relocking deadlock which can occur with
- * mutexes of type PTHREAD_MUTEX_NORMAL cannot occur
- * with this type of mutex. Multiple locks of this
- * mutex require the same number of unlocks to
- * release the mutex before another thread can
- * acquire the mutex. A thread attempting to unlock a
- * mutex which another thread has locked will return
- * with an error. A thread attempting to unlock an
- * unlocked mutex will return with an error. This
- * type of mutex is only supported for mutexes whose
- * process shared attribute is
- * PTHREAD_PROCESS_PRIVATE.
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or 'type' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if ((attr != NULL && *attr != NULL))
- {
- switch (kind)
- {
- case PTHREAD_MUTEX_FAST_NP:
- case PTHREAD_MUTEX_RECURSIVE_NP:
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- (*attr)->kind = kind;
- break;
- default:
- result = EINVAL;
- break;
- }
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-} /* pthread_mutexattr_settype */
diff --git a/pthreads/src/pthread_num_processors_np.c b/pthreads/src/pthread_num_processors_np.c
deleted file mode 100644
index 3067d11..0000000
--- a/pthreads/src/pthread_num_processors_np.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * pthread_num_processors_np.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * pthread_num_processors_np()
- *
- * Get the number of CPUs available to the process.
- */
-int
-pthread_num_processors_np (void)
-{
- int count;
-
- if (ptw32_getprocessors (&count) != 0)
- {
- count = 1;
- }
-
- return (count);
-}
diff --git a/pthreads/src/pthread_once.c b/pthreads/src/pthread_once.c
deleted file mode 100644
index ef2c1f1..0000000
--- a/pthreads/src/pthread_once.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * pthread_once.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_once (pthread_once_t * once_control, void (*init_routine) (void))
-{
- if (once_control == NULL || init_routine == NULL)
- {
- return EINVAL;
- }
-
- if ((PTW32_INTERLOCKED_LONG)PTW32_FALSE ==
- (PTW32_INTERLOCKED_LONG)PTW32_INTERLOCKED_EXCHANGE_ADD_LONG((PTW32_INTERLOCKED_LONGPTR)&once_control->done,
- (PTW32_INTERLOCKED_LONG)0)) /* MBR fence */
- {
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire((ptw32_mcs_lock_t *)&once_control->lock, &node);
-
- if (!once_control->done)
- {
-
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth(0)
-#endif
-
- pthread_cleanup_push(ptw32_mcs_lock_release, &node);
- (*init_routine)();
- pthread_cleanup_pop(0);
-
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth()
-#endif
-
- once_control->done = PTW32_TRUE;
- }
-
- ptw32_mcs_lock_release(&node);
- }
-
- return 0;
-
-} /* pthread_once */
diff --git a/pthreads/src/pthread_rwlock_destroy.c b/pthreads/src/pthread_rwlock_destroy.c
deleted file mode 100644
index 245a892..0000000
--- a/pthreads/src/pthread_rwlock_destroy.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * pthread_rwlock_destroy.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_destroy (pthread_rwlock_t * rwlock)
-{
- pthread_rwlock_t rwl;
- int result = 0, result1 = 0, result2 = 0;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- if (*rwlock != PTHREAD_RWLOCK_INITIALIZER)
- {
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if ((result =
- pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- /*
- * Check whether any threads own/wait for the lock (wait for ex.access);
- * report "BUSY" if so.
- */
- if (rwl->nExclusiveAccessCount > 0
- || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount)
- {
- result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
- result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- result2 = EBUSY;
- }
- else
- {
- rwl->nMagic = 0;
-
- if ((result =
- pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- pthread_mutex_unlock (&rwl->mtxExclusiveAccess);
- return result;
- }
-
- if ((result =
- pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- *rwlock = NULL; /* Invalidate rwlock before anything else */
- result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted));
- result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
- result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
- (void) free (rwl);
- }
- }
- else
- {
- ptw32_mcs_local_node_t node;
- /*
- * See notes in ptw32_rwlock_check_need_init() above also.
- */
- ptw32_mcs_lock_acquire(&ptw32_rwlock_test_init_lock, &node);
-
- /*
- * Check again.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised rwlock that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this rwlock will get an EINVAL.
- */
- *rwlock = NULL;
- }
- else
- {
- /*
- * The rwlock has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- ptw32_mcs_lock_release(&node);
- }
-
- return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
-}
diff --git a/pthreads/src/pthread_rwlock_init.c b/pthreads/src/pthread_rwlock_init.c
deleted file mode 100644
index 597c1ff..0000000
--- a/pthreads/src/pthread_rwlock_init.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * pthread_rwlock_init.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_init (pthread_rwlock_t * rwlock,
- const pthread_rwlockattr_t * attr)
-{
- int result;
- pthread_rwlock_t rwl = 0;
-
- if (rwlock == NULL)
- {
- return EINVAL;
- }
-
- if (attr != NULL && *attr != NULL)
- {
- result = EINVAL; /* Not supported */
- goto DONE;
- }
-
- rwl = (pthread_rwlock_t) calloc (1, sizeof (*rwl));
-
- if (rwl == NULL)
- {
- result = ENOMEM;
- goto DONE;
- }
-
- rwl->nSharedAccessCount = 0;
- rwl->nExclusiveAccessCount = 0;
- rwl->nCompletedSharedAccessCount = 0;
-
- result = pthread_mutex_init (&rwl->mtxExclusiveAccess, NULL);
- if (result != 0)
- {
- goto FAIL0;
- }
-
- result = pthread_mutex_init (&rwl->mtxSharedAccessCompleted, NULL);
- if (result != 0)
- {
- goto FAIL1;
- }
-
- result = pthread_cond_init (&rwl->cndSharedAccessCompleted, NULL);
- if (result != 0)
- {
- goto FAIL2;
- }
-
- rwl->nMagic = PTW32_RWLOCK_MAGIC;
-
- result = 0;
- goto DONE;
-
-FAIL2:
- (void) pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
-
-FAIL1:
- (void) pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
-
-FAIL0:
- (void) free (rwl);
- rwl = NULL;
-
-DONE:
- *rwlock = rwl;
-
- return result;
-}
diff --git a/pthreads/src/pthread_rwlock_rdlock.c b/pthreads/src/pthread_rwlock_rdlock.c
deleted file mode 100644
index 91e1808..0000000
--- a/pthreads/src/pthread_rwlock_rdlock.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * pthread_rwlock_rdlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_rdlock (pthread_rwlock_t * rwlock)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init (rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if (++rwl->nSharedAccessCount == INT_MAX)
- {
- if ((result =
- pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
-
- if ((result =
- pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
- }
-
- return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
-}
diff --git a/pthreads/src/pthread_rwlock_timedrdlock.c b/pthreads/src/pthread_rwlock_timedrdlock.c
deleted file mode 100644
index 7133778..0000000
--- a/pthreads/src/pthread_rwlock_timedrdlock.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * pthread_rwlock_timedrdlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock,
- const struct timespec *abstime)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init (rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result =
- pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
- {
- return result;
- }
-
- if (++rwl->nSharedAccessCount == INT_MAX)
- {
- if ((result =
- pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
- abstime)) != 0)
- {
- if (result == ETIMEDOUT)
- {
- ++rwl->nCompletedSharedAccessCount;
- }
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
-
- if ((result =
- pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
- }
-
- return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
-}
diff --git a/pthreads/src/pthread_rwlock_timedwrlock.c b/pthreads/src/pthread_rwlock_timedwrlock.c
deleted file mode 100644
index 8c111bb..0000000
--- a/pthreads/src/pthread_rwlock_timedwrlock.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * pthread_rwlock_timedwrlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock,
- const struct timespec *abstime)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init (rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result =
- pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
- {
- return result;
- }
-
- if ((result =
- pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
- abstime)) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- if (rwl->nExclusiveAccessCount == 0)
- {
- if (rwl->nCompletedSharedAccessCount > 0)
- {
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
- }
-
- if (rwl->nSharedAccessCount > 0)
- {
- rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
-
- /*
- * This routine may be a cancelation point
- * according to POSIX 1003.1j section 18.1.2.
- */
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth(0)
-#endif
- pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);
-
- do
- {
- result =
- pthread_cond_timedwait (&(rwl->cndSharedAccessCompleted),
- &(rwl->mtxSharedAccessCompleted),
- abstime);
- }
- while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
-
- pthread_cleanup_pop ((result != 0) ? 1 : 0);
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth()
-#endif
-
- if (result == 0)
- {
- rwl->nSharedAccessCount = 0;
- }
- }
- }
-
- if (result == 0)
- {
- rwl->nExclusiveAccessCount++;
- }
-
- return result;
-}
diff --git a/pthreads/src/pthread_rwlock_tryrdlock.c b/pthreads/src/pthread_rwlock_tryrdlock.c
deleted file mode 100644
index 0fc5458..0000000
--- a/pthreads/src/pthread_rwlock_tryrdlock.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * pthread_rwlock_tryrdlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_tryrdlock (pthread_rwlock_t * rwlock)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init (rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if (++rwl->nSharedAccessCount == INT_MAX)
- {
- if ((result =
- pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
-
- if ((result =
- pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
- }
-
- return (pthread_mutex_unlock (&rwl->mtxExclusiveAccess));
-}
diff --git a/pthreads/src/pthread_rwlock_trywrlock.c b/pthreads/src/pthread_rwlock_trywrlock.c
deleted file mode 100644
index 9997c5d..0000000
--- a/pthreads/src/pthread_rwlock_trywrlock.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * pthread_rwlock_trywrlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_trywrlock (pthread_rwlock_t * rwlock)
-{
- int result, result1;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init (rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if ((result =
- pthread_mutex_trylock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return ((result1 != 0) ? result1 : result);
- }
-
- if (rwl->nExclusiveAccessCount == 0)
- {
- if (rwl->nCompletedSharedAccessCount > 0)
- {
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
- }
-
- if (rwl->nSharedAccessCount > 0)
- {
- if ((result =
- pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- if ((result =
- pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) == 0)
- {
- result = EBUSY;
- }
- }
- else
- {
- rwl->nExclusiveAccessCount = 1;
- }
- }
- else
- {
- result = EBUSY;
- }
-
- return result;
-}
diff --git a/pthreads/src/pthread_rwlock_unlock.c b/pthreads/src/pthread_rwlock_unlock.c
deleted file mode 100644
index d48d187..0000000
--- a/pthreads/src/pthread_rwlock_unlock.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * pthread_rwlock_unlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_unlock (pthread_rwlock_t * rwlock)
-{
- int result, result1;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return (EINVAL);
- }
-
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- /*
- * Assume any race condition here is harmless.
- */
- return 0;
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if (rwl->nExclusiveAccessCount == 0)
- {
- if ((result =
- pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- return result;
- }
-
- if (++rwl->nCompletedSharedAccessCount == 0)
- {
- result = pthread_cond_signal (&(rwl->cndSharedAccessCompleted));
- }
-
- result1 = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
- }
- else
- {
- rwl->nExclusiveAccessCount--;
-
- result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
- result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
-
- }
-
- return ((result != 0) ? result : result1);
-}
diff --git a/pthreads/src/pthread_rwlock_wrlock.c b/pthreads/src/pthread_rwlock_wrlock.c
deleted file mode 100644
index e8b4fbb..0000000
--- a/pthreads/src/pthread_rwlock_wrlock.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * pthread_rwlock_wrlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlock_wrlock (pthread_rwlock_t * rwlock)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init (rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- if (rwl->nExclusiveAccessCount == 0)
- {
- if (rwl->nCompletedSharedAccessCount > 0)
- {
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
- }
-
- if (rwl->nSharedAccessCount > 0)
- {
- rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
-
- /*
- * This routine may be a cancelation point
- * according to POSIX 1003.1j section 18.1.2.
- */
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth(0)
-#endif
- pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);
-
- do
- {
- result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted),
- &(rwl->mtxSharedAccessCompleted));
- }
- while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
-
- pthread_cleanup_pop ((result != 0) ? 1 : 0);
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth()
-#endif
-
- if (result == 0)
- {
- rwl->nSharedAccessCount = 0;
- }
- }
- }
-
- if (result == 0)
- {
- rwl->nExclusiveAccessCount++;
- }
-
- return result;
-}
diff --git a/pthreads/src/pthread_rwlockattr_destroy.c b/pthreads/src/pthread_rwlockattr_destroy.c
deleted file mode 100644
index 868e727..0000000
--- a/pthreads/src/pthread_rwlockattr_destroy.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * pthread_rwlockattr_destroy.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Destroys a rwlock attributes object. The object can
- * no longer be used.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- *
- * DESCRIPTION
- * Destroys a rwlock attributes object. The object can
- * no longer be used.
- *
- * NOTES:
- * 1) Does not affect rwlockss created using 'attr'
- *
- * RESULTS
- * 0 successfully released attr,
- * EINVAL 'attr' is invalid.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if (attr == NULL || *attr == NULL)
- {
- result = EINVAL;
- }
- else
- {
- pthread_rwlockattr_t rwa = *attr;
-
- *attr = NULL;
- free (rwa);
- }
-
- return (result);
-} /* pthread_rwlockattr_destroy */
diff --git a/pthreads/src/pthread_rwlockattr_getpshared.c b/pthreads/src/pthread_rwlockattr_getpshared.c
deleted file mode 100644
index eeace20..0000000
--- a/pthreads/src/pthread_rwlockattr_getpshared.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * pthread_rwlockattr_getpshared.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
- int *pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Determine whether rwlocks created with 'attr' can be
- * shared between processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- * pshared
- * will be set to one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- *
- * DESCRIPTION
- * Rwlocks creatd with 'attr' can be shared between
- * processes if pthread_rwlock_t variable is allocated
- * in memory shared by these processes.
- * NOTES:
- * 1) pshared rwlocks MUST be allocated in shared
- * memory.
- * 2) The following macro is defined if shared rwlocks
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully retrieved attribute,
- * EINVAL 'attr' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) && (pshared != NULL))
- {
- *pshared = (*attr)->pshared;
- result = 0;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_rwlockattr_getpshared */
diff --git a/pthreads/src/pthread_rwlockattr_init.c b/pthreads/src/pthread_rwlockattr_init.c
deleted file mode 100644
index a2d2b94..0000000
--- a/pthreads/src/pthread_rwlockattr_init.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * pthread_rwlockattr_init.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlockattr_init (pthread_rwlockattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Initializes a rwlock attributes object with default
- * attributes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- *
- * DESCRIPTION
- * Initializes a rwlock attributes object with default
- * attributes.
- *
- * RESULTS
- * 0 successfully initialized attr,
- * ENOMEM insufficient memory for attr.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_rwlockattr_t rwa;
-
- rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa));
-
- if (rwa == NULL)
- {
- result = ENOMEM;
- }
- else
- {
- rwa->pshared = PTHREAD_PROCESS_PRIVATE;
- }
-
- *attr = rwa;
-
- return (result);
-} /* pthread_rwlockattr_init */
diff --git a/pthreads/src/pthread_rwlockattr_setpshared.c b/pthreads/src/pthread_rwlockattr_setpshared.c
deleted file mode 100644
index a83dd70..0000000
--- a/pthreads/src/pthread_rwlockattr_setpshared.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * pthread_rwlockattr_setpshared.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Rwlocks created with 'attr' can be shared between
- * processes if pthread_rwlock_t variable is allocated
- * in memory shared by these processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- * pshared
- * must be one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- * DESCRIPTION
- * Rwlocks creatd with 'attr' can be shared between
- * processes if pthread_rwlock_t variable is allocated
- * in memory shared by these processes.
- *
- * NOTES:
- * 1) pshared rwlocks MUST be allocated in shared
- * memory.
- *
- * 2) The following macro is defined if shared rwlocks
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or pshared is invalid,
- * ENOSYS PTHREAD_PROCESS_SHARED not supported,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) &&
- ((pshared == PTHREAD_PROCESS_SHARED) ||
- (pshared == PTHREAD_PROCESS_PRIVATE)))
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
-
-#if !defined( _POSIX_THREAD_PROCESS_SHARED )
-
- result = ENOSYS;
- pshared = PTHREAD_PROCESS_PRIVATE;
-
-#else
-
- result = 0;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- else
- {
- result = 0;
- }
-
- (*attr)->pshared = pshared;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_rwlockattr_setpshared */
diff --git a/pthreads/src/pthread_self.c b/pthreads/src/pthread_self.c
deleted file mode 100644
index 9a1765f..0000000
--- a/pthreads/src/pthread_self.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * pthread_self.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-pthread_t
-pthread_self (void)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function returns a reference to the current running
- * thread.
- *
- * PARAMETERS
- * N/A
- *
- *
- * DESCRIPTION
- * This function returns a reference to the current running
- * thread.
- *
- * RESULTS
- * pthread_t reference to the current thread
- *
- * ------------------------------------------------------
- */
-{
- pthread_t self;
- pthread_t nil = {NULL, 0};
- ptw32_thread_t * sp;
-
-#if defined(_UWIN)
- if (!ptw32_selfThreadKey)
- return nil;
-#endif
-
- sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
-
- if (sp != NULL)
- {
- self = sp->ptHandle;
- }
- else
- {
- /*
- * Need to create an implicit 'self' for the currently
- * executing thread.
- */
- self = ptw32_new ();
- sp = (ptw32_thread_t *) self.p;
-
- if (sp != NULL)
- {
- /*
- * This is a non-POSIX thread which has chosen to call
- * a POSIX threads function for some reason. We assume that
- * it isn't joinable, but we do assume that it's
- * (deferred) cancelable.
- */
- sp->implicit = 1;
- sp->detachState = PTHREAD_CREATE_DETACHED;
- sp->thread = GetCurrentThreadId ();
-
-#if defined(NEED_DUPLICATEHANDLE)
- /*
- * DuplicateHandle does not exist on WinCE.
- *
- * NOTE:
- * GetCurrentThread only returns a pseudo-handle
- * which is only valid in the current thread context.
- * Therefore, you should not pass the handle to
- * other threads for whatever purpose.
- */
- sp->threadH = GetCurrentThread ();
-#else
- if (!DuplicateHandle (GetCurrentProcess (),
- GetCurrentThread (),
- GetCurrentProcess (),
- &sp->threadH,
- 0, FALSE, DUPLICATE_SAME_ACCESS))
- {
- /*
- * Should not do this, but we have no alternative if
- * we can't get a Win32 thread handle.
- * Thread structs are never freed.
- */
- ptw32_threadReusePush (self);
- /*
- * As this is a win32 thread calling us and we have failed,
- * return a value that makes sense to win32.
- */
- return nil;
- }
-#endif
-
- /*
- * No need to explicitly serialise access to sched_priority
- * because the new handle is not yet public.
- */
- sp->sched_priority = GetThreadPriority (sp->threadH);
- pthread_setspecific (ptw32_selfThreadKey, (void *) sp);
- }
- }
-
- return (self);
-
-} /* pthread_self */
diff --git a/pthreads/src/pthread_setcancelstate.c b/pthreads/src/pthread_setcancelstate.c
deleted file mode 100644
index bbcd624..0000000
--- a/pthreads/src/pthread_setcancelstate.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * pthread_setcancelstate.c
- *
- * Description:
- * POSIX thread functions related to thread cancellation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_setcancelstate (int state, int *oldstate)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function atomically sets the calling thread's
- * cancelability state to 'state' and returns the previous
- * cancelability state at the location referenced by
- * 'oldstate'
- *
- * PARAMETERS
- * state,
- * oldstate
- * PTHREAD_CANCEL_ENABLE
- * cancellation is enabled,
- *
- * PTHREAD_CANCEL_DISABLE
- * cancellation is disabled
- *
- *
- * DESCRIPTION
- * This function atomically sets the calling thread's
- * cancelability state to 'state' and returns the previous
- * cancelability state at the location referenced by
- * 'oldstate'.
- *
- * NOTES:
- * 1) Use to disable cancellation around 'atomic' code that
- * includes cancellation points
- *
- * COMPATIBILITY ADDITIONS
- * If 'oldstate' is NULL then the previous state is not returned
- * but the function still succeeds. (Solaris)
- *
- * RESULTS
- * 0 successfully set cancelability type,
- * EINVAL 'state' is invalid
- *
- * ------------------------------------------------------
- */
-{
- ptw32_mcs_local_node_t stateLock;
- int result = 0;
- pthread_t self = pthread_self ();
- ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
-
- if (sp == NULL
- || (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE))
- {
- return EINVAL;
- }
-
- /*
- * Lock for async-cancel safety.
- */
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
-
- if (oldstate != NULL)
- {
- *oldstate = sp->cancelState;
- }
-
- sp->cancelState = state;
-
- /*
- * Check if there is a pending asynchronous cancel
- */
- if (state == PTHREAD_CANCEL_ENABLE
- && sp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
- && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
- {
- sp->state = PThreadStateCanceling;
- sp->cancelState = PTHREAD_CANCEL_DISABLE;
- ResetEvent (sp->cancelEvent);
- ptw32_mcs_lock_release (&stateLock);
- ptw32_throw (PTW32_EPS_CANCEL);
-
- /* Never reached */
- }
-
- ptw32_mcs_lock_release (&stateLock);
-
- return (result);
-
-} /* pthread_setcancelstate */
diff --git a/pthreads/src/pthread_setcanceltype.c b/pthreads/src/pthread_setcanceltype.c
deleted file mode 100644
index 72b0af5..0000000
--- a/pthreads/src/pthread_setcanceltype.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * pthread_setcanceltype.c
- *
- * Description:
- * POSIX thread functions related to thread cancellation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_setcanceltype (int type, int *oldtype)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function atomically sets the calling thread's
- * cancelability type to 'type' and returns the previous
- * cancelability type at the location referenced by
- * 'oldtype'
- *
- * PARAMETERS
- * type,
- * oldtype
- * PTHREAD_CANCEL_DEFERRED
- * only deferred cancelation is allowed,
- *
- * PTHREAD_CANCEL_ASYNCHRONOUS
- * Asynchronous cancellation is allowed
- *
- *
- * DESCRIPTION
- * This function atomically sets the calling thread's
- * cancelability type to 'type' and returns the previous
- * cancelability type at the location referenced by
- * 'oldtype'
- *
- * NOTES:
- * 1) Use with caution; most code is not safe for use
- * with asynchronous cancelability.
- *
- * COMPATIBILITY ADDITIONS
- * If 'oldtype' is NULL then the previous type is not returned
- * but the function still succeeds. (Solaris)
- *
- * RESULTS
- * 0 successfully set cancelability type,
- * EINVAL 'type' is invalid
- *
- * ------------------------------------------------------
- */
-{
- ptw32_mcs_local_node_t stateLock;
- int result = 0;
- pthread_t self = pthread_self ();
- ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
-
- if (sp == NULL
- || (type != PTHREAD_CANCEL_DEFERRED
- && type != PTHREAD_CANCEL_ASYNCHRONOUS))
- {
- return EINVAL;
- }
-
- /*
- * Lock for async-cancel safety.
- */
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
-
- if (oldtype != NULL)
- {
- *oldtype = sp->cancelType;
- }
-
- sp->cancelType = type;
-
- /*
- * Check if there is a pending asynchronous cancel
- */
- if (sp->cancelState == PTHREAD_CANCEL_ENABLE
- && type == PTHREAD_CANCEL_ASYNCHRONOUS
- && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
- {
- sp->state = PThreadStateCanceling;
- sp->cancelState = PTHREAD_CANCEL_DISABLE;
- ResetEvent (sp->cancelEvent);
- ptw32_mcs_lock_release (&stateLock);
- ptw32_throw (PTW32_EPS_CANCEL);
-
- /* Never reached */
- }
-
- ptw32_mcs_lock_release (&stateLock);
-
- return (result);
-
-} /* pthread_setcanceltype */
diff --git a/pthreads/src/pthread_setconcurrency.c b/pthreads/src/pthread_setconcurrency.c
deleted file mode 100644
index f62346f..0000000
--- a/pthreads/src/pthread_setconcurrency.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * pthread_setconcurrency.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_setconcurrency (int level)
-{
- if (level < 0)
- {
- return EINVAL;
- }
- else
- {
- ptw32_concurrency = level;
- return 0;
- }
-}
diff --git a/pthreads/src/pthread_setschedparam.c b/pthreads/src/pthread_setschedparam.c
deleted file mode 100644
index b762753..0000000
--- a/pthreads/src/pthread_setschedparam.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * sched_setschedparam.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-pthread_setschedparam (pthread_t thread, int policy,
- const struct sched_param *param)
-{
- int result;
-
- /* Validate the thread id. */
- result = pthread_kill (thread, 0);
- if (0 != result)
- {
- return result;
- }
-
- /* Validate the scheduling policy. */
- if (policy < SCHED_MIN || policy > SCHED_MAX)
- {
- return EINVAL;
- }
-
- /* Ensure the policy is SCHED_OTHER. */
- if (policy != SCHED_OTHER)
- {
- return ENOTSUP;
- }
-
- return (ptw32_setthreadpriority (thread, policy, param->sched_priority));
-}
-
-
-int
-ptw32_setthreadpriority (pthread_t thread, int policy, int priority)
-{
- int prio;
- ptw32_mcs_local_node_t threadLock;
- int result = 0;
- ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
-
- prio = priority;
-
- /* Validate priority level. */
- if (prio < sched_get_priority_min (policy) ||
- prio > sched_get_priority_max (policy))
- {
- return EINVAL;
- }
-
-#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
-/* WinCE */
-#else
-/* Everything else */
-
- if (THREAD_PRIORITY_IDLE < prio && THREAD_PRIORITY_LOWEST > prio)
- {
- prio = THREAD_PRIORITY_LOWEST;
- }
- else if (THREAD_PRIORITY_TIME_CRITICAL > prio
- && THREAD_PRIORITY_HIGHEST < prio)
- {
- prio = THREAD_PRIORITY_HIGHEST;
- }
-
-#endif
-
- ptw32_mcs_lock_acquire (&tp->threadLock, &threadLock);
-
- /* If this fails, the current priority is unchanged. */
- if (0 == SetThreadPriority (tp->threadH, prio))
- {
- result = EINVAL;
- }
- else
- {
- /*
- * Must record the thread's sched_priority as given,
- * not as finally adjusted.
- */
- tp->sched_priority = priority;
- }
-
- ptw32_mcs_lock_release (&threadLock);
-
- return result;
-}
diff --git a/pthreads/src/pthread_setspecific.c b/pthreads/src/pthread_setspecific.c
deleted file mode 100644
index 0f29e70..0000000
--- a/pthreads/src/pthread_setspecific.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * pthread_setspecific.c
- *
- * Description:
- * POSIX thread functions which implement thread-specific data (TSD).
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_setspecific (pthread_key_t key, const void *value)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function sets the value of the thread specific
- * key in the calling thread.
- *
- * PARAMETERS
- * key
- * an instance of pthread_key_t
- * value
- * the value to set key to
- *
- *
- * DESCRIPTION
- * This function sets the value of the thread specific
- * key in the calling thread.
- *
- * RESULTS
- * 0 successfully set value
- * EAGAIN could not set value
- * ENOENT SERIOUS!!
- *
- * ------------------------------------------------------
- */
-{
- pthread_t self;
- int result = 0;
-
- if (key != ptw32_selfThreadKey)
- {
- /*
- * Using pthread_self will implicitly create
- * an instance of pthread_t for the current
- * thread if one wasn't explicitly created
- */
- self = pthread_self ();
- if (self.p == NULL)
- {
- return ENOENT;
- }
- }
- else
- {
- /*
- * Resolve catch-22 of registering thread with selfThread
- * key
- */
- ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
-
- if (sp == NULL)
- {
- if (value == NULL)
- {
- return ENOENT;
- }
- self = *((pthread_t *) value);
- }
- else
- {
- self = sp->ptHandle;
- }
- }
-
- result = 0;
-
- if (key != NULL)
- {
- if (self.p != NULL && key->destructor != NULL && value != NULL)
- {
- ptw32_mcs_local_node_t keyLock;
- ptw32_mcs_local_node_t threadLock;
- ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
- /*
- * Only require associations if we have to
- * call user destroy routine.
- * Don't need to locate an existing association
- * when setting data to NULL for WIN32 since the
- * data is stored with the operating system; not
- * on the association; setting assoc to NULL short
- * circuits the search.
- */
- ThreadKeyAssoc *assoc;
-
- ptw32_mcs_lock_acquire(&(key->keyLock), &keyLock);
- ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock);
-
- assoc = (ThreadKeyAssoc *) sp->keys;
- /*
- * Locate existing association
- */
- while (assoc != NULL)
- {
- if (assoc->key == key)
- {
- /*
- * Association already exists
- */
- break;
- }
- assoc = assoc->nextKey;
- }
-
- /*
- * create an association if not found
- */
- if (assoc == NULL)
- {
- result = ptw32_tkAssocCreate (sp, key);
- }
-
- ptw32_mcs_lock_release(&threadLock);
- ptw32_mcs_lock_release(&keyLock);
- }
-
- if (result == 0)
- {
- if (!TlsSetValue (key->key, (LPVOID) value))
- {
- result = EAGAIN;
- }
- }
- }
-
- return (result);
-} /* pthread_setspecific */
diff --git a/pthreads/src/pthread_spin_destroy.c b/pthreads/src/pthread_spin_destroy.c
deleted file mode 100644
index 786c4e3..0000000
--- a/pthreads/src/pthread_spin_destroy.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * pthread_spin_destroy.c
- *
- * Description:
- * This translation unit implements spin lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_spin_destroy (pthread_spinlock_t * lock)
-{
- register pthread_spinlock_t s;
- int result = 0;
-
- if (lock == NULL || *lock == NULL)
- {
- return EINVAL;
- }
-
- if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER)
- {
- if (s->interlock == PTW32_SPIN_USE_MUTEX)
- {
- result = pthread_mutex_destroy (&(s->u.mutex));
- }
- else if ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED !=
- PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_INVALID,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
- {
- result = EINVAL;
- }
-
- if (0 == result)
- {
- /*
- * We are relying on the application to ensure that all other threads
- * have finished with the spinlock before destroying it.
- */
- *lock = NULL;
- (void) free (s);
- }
- }
- else
- {
- /*
- * See notes in ptw32_spinlock_check_need_init() above also.
- */
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_spinlock_test_init_lock, &node);
-
- /*
- * Check again.
- */
- if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised spinlock that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this mutex will get an EINVAL.
- */
- *lock = NULL;
- }
- else
- {
- /*
- * The spinlock has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- ptw32_mcs_lock_release(&node);
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_spin_init.c b/pthreads/src/pthread_spin_init.c
deleted file mode 100644
index 553af7e..0000000
--- a/pthreads/src/pthread_spin_init.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * pthread_spin_init.c
- *
- * Description:
- * This translation unit implements spin lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_spin_init (pthread_spinlock_t * lock, int pshared)
-{
- pthread_spinlock_t s;
- int cpus = 0;
- int result = 0;
-
- if (lock == NULL)
- {
- return EINVAL;
- }
-
- if (0 != ptw32_getprocessors (&cpus))
- {
- cpus = 1;
- }
-
- if (cpus > 1)
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
- /*
- * Creating spinlock that can be shared between
- * processes.
- */
-#if _POSIX_THREAD_PROCESS_SHARED >= 0
-
- /*
- * Not implemented yet.
- */
-
-#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet.
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- }
-
- s = (pthread_spinlock_t) calloc (1, sizeof (*s));
-
- if (s == NULL)
- {
- return ENOMEM;
- }
-
- if (cpus > 1)
- {
- s->u.cpus = cpus;
- s->interlock = PTW32_SPIN_UNLOCKED;
- }
- else
- {
- pthread_mutexattr_t ma;
- result = pthread_mutexattr_init (&ma);
-
- if (0 == result)
- {
- ma->pshared = pshared;
- result = pthread_mutex_init (&(s->u.mutex), &ma);
- if (0 == result)
- {
- s->interlock = PTW32_SPIN_USE_MUTEX;
- }
- }
- (void) pthread_mutexattr_destroy (&ma);
- }
-
- if (0 == result)
- {
- *lock = s;
- }
- else
- {
- (void) free (s);
- *lock = NULL;
- }
-
- return (result);
-}
diff --git a/pthreads/src/pthread_spin_lock.c b/pthreads/src/pthread_spin_lock.c
deleted file mode 100644
index b560e14..0000000
--- a/pthreads/src/pthread_spin_lock.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * pthread_spin_lock.c
- *
- * Description:
- * This translation unit implements spin lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_spin_lock (pthread_spinlock_t * lock)
-{
- register pthread_spinlock_t s;
-
- if (NULL == lock || NULL == *lock)
- {
- return (EINVAL);
- }
-
- if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
- {
- int result;
-
- if ((result = ptw32_spinlock_check_need_init (lock)) != 0)
- {
- return (result);
- }
- }
-
- s = *lock;
-
- while ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED ==
- PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
- {
- }
-
- if (s->interlock == PTW32_SPIN_LOCKED)
- {
- return 0;
- }
- else if (s->interlock == PTW32_SPIN_USE_MUTEX)
- {
- return pthread_mutex_lock (&(s->u.mutex));
- }
-
- return EINVAL;
-}
diff --git a/pthreads/src/pthread_spin_trylock.c b/pthreads/src/pthread_spin_trylock.c
deleted file mode 100644
index a6c65af..0000000
--- a/pthreads/src/pthread_spin_trylock.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * pthread_spin_trylock.c
- *
- * Description:
- * This translation unit implements spin lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_spin_trylock (pthread_spinlock_t * lock)
-{
- register pthread_spinlock_t s;
-
- if (NULL == lock || NULL == *lock)
- {
- return (EINVAL);
- }
-
- if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
- {
- int result;
-
- if ((result = ptw32_spinlock_check_need_init (lock)) != 0)
- {
- return (result);
- }
- }
-
- s = *lock;
-
- switch ((long)
- PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
- {
- case PTW32_SPIN_UNLOCKED:
- return 0;
- case PTW32_SPIN_LOCKED:
- return EBUSY;
- case PTW32_SPIN_USE_MUTEX:
- return pthread_mutex_trylock (&(s->u.mutex));
- }
-
- return EINVAL;
-}
diff --git a/pthreads/src/pthread_spin_unlock.c b/pthreads/src/pthread_spin_unlock.c
deleted file mode 100644
index 3a6932a..0000000
--- a/pthreads/src/pthread_spin_unlock.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * pthread_spin_unlock.c
- *
- * Description:
- * This translation unit implements spin lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-pthread_spin_unlock (pthread_spinlock_t * lock)
-{
- register pthread_spinlock_t s;
-
- if (NULL == lock || NULL == *lock)
- {
- return (EINVAL);
- }
-
- s = *lock;
-
- if (s == PTHREAD_SPINLOCK_INITIALIZER)
- {
- return EPERM;
- }
-
- switch ((long)
- PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED))
- {
- case PTW32_SPIN_LOCKED:
- case PTW32_SPIN_UNLOCKED:
- return 0;
- case PTW32_SPIN_USE_MUTEX:
- return pthread_mutex_unlock (&(s->u.mutex));
- }
-
- return EINVAL;
-}
diff --git a/pthreads/src/pthread_testcancel.c b/pthreads/src/pthread_testcancel.c
deleted file mode 100644
index 6658650..0000000
--- a/pthreads/src/pthread_testcancel.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * pthread_testcancel.c
- *
- * Description:
- * POSIX thread functions related to thread cancellation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-void
-pthread_testcancel (void)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function creates a deferred cancellation point
- * in the calling thread. The call has no effect if the
- * current cancelability state is
- * PTHREAD_CANCEL_DISABLE
- *
- * PARAMETERS
- * N/A
- *
- *
- * DESCRIPTION
- * This function creates a deferred cancellation point
- * in the calling thread. The call has no effect if the
- * current cancelability state is
- * PTHREAD_CANCEL_DISABLE
- *
- * NOTES:
- * 1) Cancellation is asynchronous. Use pthread_join
- * to wait for termination of thread if necessary
- *
- * RESULTS
- * N/A
- *
- * ------------------------------------------------------
- */
-{
- ptw32_mcs_local_node_t stateLock;
- pthread_t self = pthread_self ();
- ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
-
- if (sp == NULL)
- {
- return;
- }
-
- /*
- * Pthread_cancel() will have set sp->state to PThreadStateCancelPending
- * and set an event, so no need to enter kernel space if
- * sp->state != PThreadStateCancelPending - that only slows us down.
- */
- if (sp->state != PThreadStateCancelPending)
- {
- return;
- }
-
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
-
- if (sp->cancelState != PTHREAD_CANCEL_DISABLE)
- {
- ResetEvent(sp->cancelEvent);
- sp->state = PThreadStateCanceling;
- sp->cancelState = PTHREAD_CANCEL_DISABLE;
- ptw32_mcs_lock_release (&stateLock);
- ptw32_throw (PTW32_EPS_CANCEL);
- /* Never returns here */
- }
-
- ptw32_mcs_lock_release (&stateLock);
-} /* pthread_testcancel */
diff --git a/pthreads/src/pthread_timechange_handler_np.c b/pthreads/src/pthread_timechange_handler_np.c
deleted file mode 100644
index 0f97e74..0000000
--- a/pthreads/src/pthread_timechange_handler_np.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * pthread_timechange_handler_np.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * Notes on handling system time adjustments (especially negative ones).
- * ---------------------------------------------------------------------
- *
- * This solution was suggested by Alexander Terekhov, but any errors
- * in the implementation are mine - [Ross Johnson]
- *
- * 1) The problem: threads doing a timedwait on a CV may expect to timeout
- * at a specific absolute time according to a system timer. If the
- * system clock is adjusted backwards then those threads sleep longer than
- * expected. Also, pthreads-win32 converts absolute times to intervals in
- * order to make use of the underlying Win32, and so waiting threads may
- * awake before their proper abstimes.
- *
- * 2) We aren't able to distinquish between threads on timed or untimed waits,
- * so we wake them all at the time of the adjustment so that they can
- * re-evaluate their conditions and re-compute their timeouts.
- *
- * 3) We rely on correctly written applications for this to work. Specifically,
- * they must be able to deal properly with spurious wakeups. That is,
- * they must re-test their condition upon wakeup and wait again if
- * the condition is not satisfied.
- */
-
-void *
-pthread_timechange_handler_np (void *arg)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Broadcasts all CVs to force re-evaluation and
- * new timeouts if required.
- *
- * PARAMETERS
- * NONE
- *
- *
- * DESCRIPTION
- * Broadcasts all CVs to force re-evaluation and
- * new timeouts if required.
- *
- * This routine may be passed directly to pthread_create()
- * as a new thread in order to run asynchronously.
- *
- *
- * RESULTS
- * 0 successfully broadcast all CVs
- * EAGAIN Not all CVs were broadcast
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_cond_t cv;
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
-
- cv = ptw32_cond_list_head;
-
- while (cv != NULL && 0 == result)
- {
- result = pthread_cond_broadcast (&cv);
- cv = cv->next;
- }
-
- ptw32_mcs_lock_release(&node);
-
- return (void *) (size_t) (result != 0 ? EAGAIN : 0);
-}
diff --git a/pthreads/src/pthread_win32_attach_detach_np.c b/pthreads/src/pthread_win32_attach_detach_np.c
deleted file mode 100644
index bfad450..0000000
--- a/pthreads/src/pthread_win32_attach_detach_np.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * pthread_win32_attach_detach_np.c
- *
- * Description:
- * This translation unit implements non-portable thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-/*
- * Handle to quserex.dll
- */
-static HINSTANCE ptw32_h_quserex;
-
-BOOL
-pthread_win32_process_attach_np ()
-{
- TCHAR QuserExDLLPathBuf[1024];
- BOOL result = TRUE;
-
- result = ptw32_processInitialize ();
-
-#if defined(_UWIN)
- pthread_count++;
-#endif
-
-#if defined(__GNUC__)
- ptw32_features = 0;
-#else
- /*
- * This is obsolete now.
- */
- ptw32_features = PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE;
-#endif
-
- /*
- * Load QUSEREX.DLL and try to get address of QueueUserAPCEx.
- * Because QUSEREX.DLL requires a driver to be installed we will
- * assume the DLL is in the system directory.
- *
- * This should take care of any security issues.
- */
-#if defined(__GNUC__) || _MSC_VER < 1400
- if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf)))
- {
- (void) strncat(QuserExDLLPathBuf,
- "\\QUSEREX.DLL",
- sizeof(QuserExDLLPathBuf) - strlen(QuserExDLLPathBuf) - 1);
- ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf);
- }
-#else
- /* strncat is secure - this is just to avoid a warning */
- if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf)) &&
- 0 == strncat_s(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf), "\\QUSEREX.DLL", 12))
- {
- ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf);
- }
-#endif
-
- if (ptw32_h_quserex != NULL)
- {
- ptw32_register_cancelation = (DWORD (*)(PAPCFUNC, HANDLE, DWORD))
-#if defined(NEED_UNICODE_CONSTS)
- GetProcAddress (ptw32_h_quserex,
- (const TCHAR *) TEXT ("QueueUserAPCEx"));
-#else
- GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx");
-#endif
- }
-
- if (NULL == ptw32_register_cancelation)
- {
- ptw32_register_cancelation = ptw32_RegisterCancelation;
-
- if (ptw32_h_quserex != NULL)
- {
- (void) FreeLibrary (ptw32_h_quserex);
- }
- ptw32_h_quserex = 0;
- }
- else
- {
- /* Initialise QueueUserAPCEx */
- BOOL (*queue_user_apc_ex_init) (VOID);
-
- queue_user_apc_ex_init = (BOOL (*)(VOID))
-#if defined(NEED_UNICODE_CONSTS)
- GetProcAddress (ptw32_h_quserex,
- (const TCHAR *) TEXT ("QueueUserAPCEx_Init"));
-#else
- GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Init");
-#endif
-
- if (queue_user_apc_ex_init == NULL || !queue_user_apc_ex_init ())
- {
- ptw32_register_cancelation = ptw32_RegisterCancelation;
-
- (void) FreeLibrary (ptw32_h_quserex);
- ptw32_h_quserex = 0;
- }
- }
-
- if (ptw32_h_quserex)
- {
- ptw32_features |= PTW32_ALERTABLE_ASYNC_CANCEL;
- }
-
- return result;
-}
-
-
-BOOL
-pthread_win32_process_detach_np ()
-{
- if (ptw32_processInitialized)
- {
- ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
-
- if (sp != NULL)
- {
- /*
- * Detached threads have their resources automatically
- * cleaned up upon exit (others must be 'joined').
- */
- if (sp->detachState == PTHREAD_CREATE_DETACHED)
- {
- ptw32_threadDestroy (sp->ptHandle);
- TlsSetValue (ptw32_selfThreadKey->key, NULL);
- }
- }
-
- /*
- * The DLL is being unmapped from the process's address space
- */
- ptw32_processTerminate ();
-
- if (ptw32_h_quserex)
- {
- /* Close QueueUserAPCEx */
- BOOL (*queue_user_apc_ex_fini) (VOID);
-
- queue_user_apc_ex_fini = (BOOL (*)(VOID))
-#if defined(NEED_UNICODE_CONSTS)
- GetProcAddress (ptw32_h_quserex,
- (const TCHAR *) TEXT ("QueueUserAPCEx_Fini"));
-#else
- GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Fini");
-#endif
-
- if (queue_user_apc_ex_fini != NULL)
- {
- (void) queue_user_apc_ex_fini ();
- }
- (void) FreeLibrary (ptw32_h_quserex);
- }
- }
-
- return TRUE;
-}
-
-BOOL
-pthread_win32_thread_attach_np ()
-{
- return TRUE;
-}
-
-BOOL
-pthread_win32_thread_detach_np ()
-{
- if (ptw32_processInitialized)
- {
- /*
- * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle
- * unnecessarily.
- */
- ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
-
- if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle.
- {
- ptw32_mcs_local_node_t stateLock;
- ptw32_callUserDestroyRoutines (sp->ptHandle);
-
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
- sp->state = PThreadStateLast;
- /*
- * If the thread is joinable at this point then it MUST be joined
- * or detached explicitly by the application.
- */
- ptw32_mcs_lock_release (&stateLock);
-
- /*
- * Robust Mutexes
- */
- while (sp->robustMxList != NULL)
- {
- pthread_mutex_t mx = sp->robustMxList->mx;
- ptw32_robust_mutex_remove(&mx, sp);
- (void) PTW32_INTERLOCKED_EXCHANGE_LONG(
- (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent,
- (PTW32_INTERLOCKED_LONG)-1);
- /*
- * If there are no waiters then the next thread to block will
- * sleep, wakeup immediately and then go back to sleep.
- * See pthread_mutex_lock.c.
- */
- SetEvent(mx->event);
- }
-
-
- if (sp->detachState == PTHREAD_CREATE_DETACHED)
- {
- ptw32_threadDestroy (sp->ptHandle);
-
- TlsSetValue (ptw32_selfThreadKey->key, NULL);
- }
- }
- }
-
- return TRUE;
-}
-
-BOOL
-pthread_win32_test_features_np (int feature_mask)
-{
- return ((ptw32_features & feature_mask) == feature_mask);
-}
diff --git a/pthreads/src/ptw32_MCS_lock.c b/pthreads/src/ptw32_MCS_lock.c
deleted file mode 100644
index d69cf80..0000000
--- a/pthreads/src/ptw32_MCS_lock.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * ptw32_MCS_lock.c
- *
- * Description:
- * This translation unit implements queue-based locks.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/*
- * About MCS locks:
- *
- * MCS locks are queue-based locks, where the queue nodes are local to the
- * thread. The 'lock' is nothing more than a global pointer that points to
- * the last node in the queue, or is NULL if the queue is empty.
- *
- * Originally designed for use as spin locks requiring no kernel resources
- * for synchronisation or blocking, the implementation below has adapted
- * the MCS spin lock for use as a general mutex that will suspend threads
- * when there is lock contention.
- *
- * Because the queue nodes are thread-local, most of the memory read/write
- * operations required to add or remove nodes from the queue do not trigger
- * cache-coherence updates.
- *
- * Like 'named' mutexes, MCS locks consume system resources transiently -
- * they are able to acquire and free resources automatically - but MCS
- * locks do not require any unique 'name' to identify the lock to all
- * threads using it.
- *
- * Usage of MCS locks:
- *
- * - you need a global ptw32_mcs_lock_t instance initialised to 0 or NULL.
- * - you need a local thread-scope ptw32_mcs_local_node_t instance, which
- * may serve several different locks but you need at least one node for
- * every lock held concurrently by a thread.
- *
- * E.g.:
- *
- * ptw32_mcs_lock_t lock1 = 0;
- * ptw32_mcs_lock_t lock2 = 0;
- *
- * void *mythread(void *arg)
- * {
- * ptw32_mcs_local_node_t node;
- *
- * ptw32_mcs_acquire (&lock1, &node);
- * ptw32_mcs_lock_release (&node);
- *
- * ptw32_mcs_lock_acquire (&lock2, &node);
- * ptw32_mcs_lock_release (&node);
- * {
- * ptw32_mcs_local_node_t nodex;
- *
- * ptw32_mcs_lock_acquire (&lock1, &node);
- * ptw32_mcs_lock_acquire (&lock2, &nodex);
- *
- * ptw32_mcs_lock_release (&nodex);
- * ptw32_mcs_lock_release (&node);
- * }
- * return (void *)0;
- * }
- */
-
-#include "pthread.h"
-#include "sched.h"
-#include "implement.h"
-
-/*
- * ptw32_mcs_flag_set -- notify another thread about an event.
- *
- * Set event if an event handle has been stored in the flag, and
- * set flag to -1 otherwise. Note that -1 cannot be a valid handle value.
- */
-INLINE void
-ptw32_mcs_flag_set (HANDLE * flag)
-{
- HANDLE e = (HANDLE)(PTW32_INTERLOCKED_SIZE)PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
- (PTW32_INTERLOCKED_SIZEPTR)flag,
- (PTW32_INTERLOCKED_SIZE)-1,
- (PTW32_INTERLOCKED_SIZE)0);
- if ((HANDLE)0 != e)
- {
- /* another thread has already stored an event handle in the flag */
- SetEvent(e);
- }
-}
-
-/*
- * ptw32_mcs_flag_set -- wait for notification from another.
- *
- * Store an event handle in the flag and wait on it if the flag has not been
- * set, and proceed without creating an event otherwise.
- */
-INLINE void
-ptw32_mcs_flag_wait (HANDLE * flag)
-{
- if ((PTW32_INTERLOCKED_LONG)0 ==
- PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)flag,
- (PTW32_INTERLOCKED_SIZE)0)) /* MBR fence */
- {
- /* the flag is not set. create event. */
-
- HANDLE e = CreateEvent(NULL, PTW32_FALSE, PTW32_FALSE, NULL);
-
- if ((PTW32_INTERLOCKED_SIZE)0 == PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
- (PTW32_INTERLOCKED_SIZEPTR)flag,
- (PTW32_INTERLOCKED_SIZE)e,
- (PTW32_INTERLOCKED_SIZE)0))
- {
- /* stored handle in the flag. wait on it now. */
- WaitForSingleObject(e, INFINITE);
- }
-
- CloseHandle(e);
- }
-}
-
-/*
- * ptw32_mcs_lock_acquire -- acquire an MCS lock.
- *
- * See:
- * J. M. Mellor-Crummey and M. L. Scott.
- * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors.
- * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991.
- */
-#if defined(PTW32_BUILD_INLINED)
-INLINE
-#endif /* PTW32_BUILD_INLINED */
-void
-ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node)
-{
- ptw32_mcs_local_node_t *pred;
-
- node->lock = lock;
- node->nextFlag = 0;
- node->readyFlag = 0;
- node->next = 0; /* initially, no successor */
-
- /* queue for the lock */
- pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock,
- (PTW32_INTERLOCKED_PVOID)node);
-
- if (0 != pred)
- {
- /* the lock was not free. link behind predecessor. */
- pred->next = node;
- ptw32_mcs_flag_set(&pred->nextFlag);
- ptw32_mcs_flag_wait(&node->readyFlag);
- }
-}
-
-/*
- * ptw32_mcs_lock_release -- release an MCS lock.
- *
- * See:
- * J. M. Mellor-Crummey and M. L. Scott.
- * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors.
- * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991.
- */
-#if defined(PTW32_BUILD_INLINED)
-INLINE
-#endif /* PTW32_BUILD_INLINED */
-void
-ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node)
-{
- ptw32_mcs_lock_t *lock = node->lock;
- ptw32_mcs_local_node_t *next =
- (ptw32_mcs_local_node_t *)
- PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */
-
- if (0 == next)
- {
- /* no known successor */
-
- if (node == (ptw32_mcs_local_node_t *)
- PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock,
- (PTW32_INTERLOCKED_PVOID)0,
- (PTW32_INTERLOCKED_PVOID)node))
- {
- /* no successor, lock is free now */
- return;
- }
-
- /* wait for successor */
- ptw32_mcs_flag_wait(&node->nextFlag);
- next = (ptw32_mcs_local_node_t *)
- PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */
- }
-
- /* pass the lock */
- ptw32_mcs_flag_set(&next->readyFlag);
-}
-
-/*
- * ptw32_mcs_lock_try_acquire
- */
-#if defined(PTW32_BUILD_INLINED)
-INLINE
-#endif /* PTW32_BUILD_INLINED */
-int
-ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node)
-{
- node->lock = lock;
- node->nextFlag = 0;
- node->readyFlag = 0;
- node->next = 0; /* initially, no successor */
-
- return ((PTW32_INTERLOCKED_PVOID)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock,
- (PTW32_INTERLOCKED_PVOID)node,
- (PTW32_INTERLOCKED_PVOID)0)
- == (PTW32_INTERLOCKED_PVOID)0) ? 0 : EBUSY;
-}
-
-/*
- * ptw32_mcs_node_transfer -- move an MCS lock local node, usually from thread
- * space to, for example, global space so that another thread can release
- * the lock on behalf of the current lock owner.
- *
- * Example: used in pthread_barrier_wait where we want the last thread out of
- * the barrier to release the lock owned by the last thread to enter the barrier
- * (the one that releases all threads but not necessarily the last to leave).
- *
- * Should only be called by the thread that has the lock.
- */
-#if defined(PTW32_BUILD_INLINED)
-INLINE
-#endif /* PTW32_BUILD_INLINED */
-void
-ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node)
-{
- new_node->lock = old_node->lock;
- new_node->nextFlag = 0; /* Not needed - used only in initial Acquire */
- new_node->readyFlag = 0; /* Not needed - we were waiting on this */
- new_node->next = 0;
-
- if ((ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)new_node->lock,
- (PTW32_INTERLOCKED_PVOID)new_node,
- (PTW32_INTERLOCKED_PVOID)old_node)
- != old_node)
- {
- /*
- * A successor has queued after us, so wait for them to link to us
- */
- while (old_node->next == 0)
- {
- sched_yield();
- }
- new_node->next = old_node->next;
- }
-}
diff --git a/pthreads/src/ptw32_callUserDestroyRoutines.c b/pthreads/src/ptw32_callUserDestroyRoutines.c
deleted file mode 100644
index f290f7b..0000000
--- a/pthreads/src/ptw32_callUserDestroyRoutines.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * ptw32_callUserDestroyRoutines.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#if defined(__CLEANUP_CXX)
-# if defined(_MSC_VER)
-# include <eh.h>
-# elif defined(__WATCOMC__)
-# include <eh.h>
-# include <exceptio.h>
-# else
-# if defined(__GNUC__) && __GNUC__ < 3
-# include <new.h>
-# else
-# include <new>
- using
- std::terminate;
-# endif
-# endif
-#endif
-
-void
-ptw32_callUserDestroyRoutines (pthread_t thread)
- /*
- * -------------------------------------------------------------------
- * DOCPRIVATE
- *
- * This the routine runs through all thread keys and calls
- * the destroy routines on the user's data for the current thread.
- * It simulates the behaviour of POSIX Threads.
- *
- * PARAMETERS
- * thread
- * an instance of pthread_t
- *
- * RETURNS
- * N/A
- * -------------------------------------------------------------------
- */
-{
- ThreadKeyAssoc * assoc;
-
- if (thread.p != NULL)
- {
- ptw32_mcs_local_node_t threadLock;
- ptw32_mcs_local_node_t keyLock;
- int assocsRemaining;
- int iterations = 0;
- ptw32_thread_t * sp = (ptw32_thread_t *) thread.p;
-
- /*
- * Run through all Thread<-->Key associations
- * for the current thread.
- *
- * Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times.
- */
- do
- {
- assocsRemaining = 0;
- iterations++;
-
- ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock);
- /*
- * The pointer to the next assoc is stored in the thread struct so that
- * the assoc destructor in pthread_key_delete can adjust it
- * if it deletes this assoc. This can happen if we fail to acquire
- * both locks below, and are forced to release all of our locks,
- * leaving open the opportunity for pthread_key_delete to get in
- * before us.
- */
- sp->nextAssoc = sp->keys;
- ptw32_mcs_lock_release(&threadLock);
-
- for (;;)
- {
- void * value;
- pthread_key_t k;
- void (*destructor) (void *);
-
- /*
- * First we need to serialise with pthread_key_delete by locking
- * both assoc guards, but in the reverse order to our convention,
- * so we must be careful to avoid deadlock.
- */
- ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock);
-
- if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL)
- {
- /* Finished */
- ptw32_mcs_lock_release(&threadLock);
- break;
- }
- else
- {
- /*
- * assoc->key must be valid because assoc can't change or be
- * removed from our chain while we hold at least one lock. If
- * the assoc was on our key chain then the key has not been
- * deleted yet.
- *
- * Now try to acquire the second lock without deadlocking.
- * If we fail, we need to relinquish the first lock and the
- * processor and then try to acquire them all again.
- */
- if (ptw32_mcs_lock_try_acquire(&(assoc->key->keyLock), &keyLock) == EBUSY)
- {
- ptw32_mcs_lock_release(&threadLock);
- Sleep(0);
- /*
- * Go around again.
- * If pthread_key_delete has removed this assoc in the meantime,
- * sp->nextAssoc will point to a new assoc.
- */
- continue;
- }
- }
-
- /* We now hold both locks */
-
- sp->nextAssoc = assoc->nextKey;
-
- /*
- * Key still active; pthread_key_delete
- * will block on these same mutexes before
- * it can release actual key; therefore,
- * key is valid and we can call the destroy
- * routine;
- */
- k = assoc->key;
- destructor = k->destructor;
- value = TlsGetValue(k->key);
- TlsSetValue (k->key, NULL);
-
- // Every assoc->key exists and has a destructor
- if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)
- {
- /*
- * Unlock both locks before the destructor runs.
- * POSIX says pthread_key_delete can be run from destructors,
- * and that probably includes with this key as target.
- * pthread_setspecific can also be run from destructors and
- * also needs to be able to access the assocs.
- */
- ptw32_mcs_lock_release(&threadLock);
- ptw32_mcs_lock_release(&keyLock);
-
- assocsRemaining++;
-
-#if defined(__cplusplus)
-
- try
- {
- /*
- * Run the caller's cleanup routine.
- */
- destructor (value);
- }
- catch (...)
- {
- /*
- * A system unexpected exception has occurred
- * running the user's destructor.
- * We get control back within this block in case
- * the application has set up it's own terminate
- * handler. Since we are leaving the thread we
- * should not get any internal pthreads
- * exceptions.
- */
- terminate ();
- }
-
-#else /* __cplusplus */
-
- /*
- * Run the caller's cleanup routine.
- */
- destructor (value);
-
-#endif /* __cplusplus */
-
- }
- else
- {
- /*
- * Remove association from both the key and thread chains
- * and reclaim it's memory resources.
- */
- ptw32_tkAssocDestroy (assoc);
- ptw32_mcs_lock_release(&threadLock);
- ptw32_mcs_lock_release(&keyLock);
- }
- }
- }
- while (assocsRemaining);
- }
-} /* ptw32_callUserDestroyRoutines */
diff --git a/pthreads/src/ptw32_calloc.c b/pthreads/src/ptw32_calloc.c
deleted file mode 100644
index e7b9e64..0000000
--- a/pthreads/src/ptw32_calloc.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * ptw32_calloc.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-#if defined(NEED_CALLOC)
-void *
-ptw32_calloc (size_t n, size_t s)
-{
- unsigned int m = n * s;
- void *p;
-
- p = malloc (m);
- if (p == NULL)
- return NULL;
-
- memset (p, 0, m);
-
- return p;
-}
-#endif
diff --git a/pthreads/src/ptw32_cond_check_need_init.c b/pthreads/src/ptw32_cond_check_need_init.c
deleted file mode 100644
index ec3e8bb..0000000
--- a/pthreads/src/ptw32_cond_check_need_init.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * ptw32_cond_check_need_init.c
- *
- * Description:
- * This translation unit implements condition variables and their primitives.
- *
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-INLINE int
-ptw32_cond_check_need_init (pthread_cond_t * cond)
-{
- int result = 0;
- ptw32_mcs_local_node_t node;
-
- /*
- * The following guarded test is specifically for statically
- * initialised condition variables (via PTHREAD_OBJECT_INITIALIZER).
- */
- ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock, &node);
-
- /*
- * We got here possibly under race
- * conditions. Check again inside the critical section.
- * If a static cv has been destroyed, the application can
- * re-initialise it only by calling pthread_cond_init()
- * explicitly.
- */
- if (*cond == PTHREAD_COND_INITIALIZER)
- {
- result = pthread_cond_init (cond, NULL);
- }
- else if (*cond == NULL)
- {
- /*
- * The cv has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
-
- ptw32_mcs_lock_release(&node);
-
- return result;
-}
diff --git a/pthreads/src/ptw32_getprocessors.c b/pthreads/src/ptw32_getprocessors.c
deleted file mode 100644
index e60c314..0000000
--- a/pthreads/src/ptw32_getprocessors.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * ptw32_getprocessors.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-/*
- * ptw32_getprocessors()
- *
- * Get the number of CPUs available to the process.
- *
- * If the available number of CPUs is 1 then pthread_spin_lock()
- * will block rather than spin if the lock is already owned.
- *
- * pthread_spin_init() calls this routine when initialising
- * a spinlock. If the number of available processors changes
- * (after a call to SetProcessAffinityMask()) then only
- * newly initialised spinlocks will notice.
- */
-int
-ptw32_getprocessors (int *count)
-{
- DWORD_PTR vProcessCPUs;
- DWORD_PTR vSystemCPUs;
- int result = 0;
-
-#if defined(NEED_PROCESS_AFFINITY_MASK)
-
- *count = 1;
-
-#else
-
- if (GetProcessAffinityMask (GetCurrentProcess (),
- &vProcessCPUs, &vSystemCPUs))
- {
- DWORD_PTR bit;
- int CPUs = 0;
-
- for (bit = 1; bit != 0; bit <<= 1)
- {
- if (vProcessCPUs & bit)
- {
- CPUs++;
- }
- }
- *count = CPUs;
- }
- else
- {
- result = EAGAIN;
- }
-
-#endif
-
- return (result);
-}
diff --git a/pthreads/src/ptw32_is_attr.c b/pthreads/src/ptw32_is_attr.c
deleted file mode 100644
index 36395f8..0000000
--- a/pthreads/src/ptw32_is_attr.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * ptw32_is_attr.c
- *
- * Description:
- * This translation unit implements operations on thread attribute objects.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-int
-ptw32_is_attr (const pthread_attr_t * attr)
-{
- /* Return 0 if the attr object is valid, non-zero otherwise. */
-
- return (attr == NULL ||
- *attr == NULL || (*attr)->valid != PTW32_ATTR_VALID);
-}
diff --git a/pthreads/src/ptw32_mutex_check_need_init.c b/pthreads/src/ptw32_mutex_check_need_init.c
deleted file mode 100644
index 897db3c..0000000
--- a/pthreads/src/ptw32_mutex_check_need_init.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * ptw32_mutex_check_need_init.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-static struct pthread_mutexattr_t_ ptw32_recursive_mutexattr_s =
- {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_RECURSIVE};
-static struct pthread_mutexattr_t_ ptw32_errorcheck_mutexattr_s =
- {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_ERRORCHECK};
-static pthread_mutexattr_t ptw32_recursive_mutexattr = &ptw32_recursive_mutexattr_s;
-static pthread_mutexattr_t ptw32_errorcheck_mutexattr = &ptw32_errorcheck_mutexattr_s;
-
-
-INLINE int
-ptw32_mutex_check_need_init (pthread_mutex_t * mutex)
-{
- register int result = 0;
- register pthread_mutex_t mtx;
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_mutex_test_init_lock, &node);
-
- /*
- * We got here possibly under race
- * conditions. Check again inside the critical section
- * and only initialise if the mutex is valid (not been destroyed).
- * If a static mutex has been destroyed, the application can
- * re-initialise it only by calling pthread_mutex_init()
- * explicitly.
- */
- mtx = *mutex;
-
- if (mtx == PTHREAD_MUTEX_INITIALIZER)
- {
- result = pthread_mutex_init (mutex, NULL);
- }
- else if (mtx == PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
- {
- result = pthread_mutex_init (mutex, &ptw32_recursive_mutexattr);
- }
- else if (mtx == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
- {
- result = pthread_mutex_init (mutex, &ptw32_errorcheck_mutexattr);
- }
- else if (mtx == NULL)
- {
- /*
- * The mutex has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
-
- ptw32_mcs_lock_release(&node);
-
- return (result);
-}
diff --git a/pthreads/src/ptw32_new.c b/pthreads/src/ptw32_new.c
deleted file mode 100644
index ac836ea..0000000
--- a/pthreads/src/ptw32_new.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * ptw32_new.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-pthread_t
-ptw32_new (void)
-{
- pthread_t t;
- pthread_t nil = {NULL, 0};
- ptw32_thread_t * tp;
-
- /*
- * If there's a reusable pthread_t then use it.
- */
- t = ptw32_threadReusePop ();
-
- if (NULL != t.p)
- {
- tp = (ptw32_thread_t *) t.p;
- }
- else
- {
- /* No reuse threads available */
- tp = (ptw32_thread_t *) calloc (1, sizeof(ptw32_thread_t));
-
- if (tp == NULL)
- {
- return nil;
- }
-
- /* ptHandle.p needs to point to it's parent ptw32_thread_t. */
- t.p = tp->ptHandle.p = tp;
- t.x = tp->ptHandle.x = 0;
- }
-
- /* Set default state. */
- tp->seqNumber = ++ptw32_threadSeqNumber;
- tp->sched_priority = THREAD_PRIORITY_NORMAL;
- tp->detachState = PTHREAD_CREATE_JOINABLE;
- tp->cancelState = PTHREAD_CANCEL_ENABLE;
- tp->cancelType = PTHREAD_CANCEL_DEFERRED;
- tp->stateLock = 0;
- tp->threadLock = 0;
- tp->robustMxListLock = 0;
- tp->robustMxList = NULL;
- tp->cancelEvent = CreateEvent (0, (int) PTW32_TRUE, /* manualReset */
- (int) PTW32_FALSE, /* setSignaled */
- NULL);
-
- if (tp->cancelEvent == NULL)
- {
- ptw32_threadReusePush (tp->ptHandle);
- return nil;
- }
-
- return t;
-
-}
diff --git a/pthreads/src/ptw32_processInitialize.c b/pthreads/src/ptw32_processInitialize.c
deleted file mode 100644
index 8da3e41..0000000
--- a/pthreads/src/ptw32_processInitialize.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * ptw32_processInitialize.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-ptw32_processInitialize (void)
- /*
- * ------------------------------------------------------
- * DOCPRIVATE
- * This function performs process wide initialization for
- * the pthread library.
- *
- * PARAMETERS
- * N/A
- *
- * DESCRIPTION
- * This function performs process wide initialization for
- * the pthread library.
- * If successful, this routine sets the global variable
- * ptw32_processInitialized to TRUE.
- *
- * RESULTS
- * TRUE if successful,
- * FALSE otherwise
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_processInitialized)
- {
- /*
- * Ignore if already initialized. this is useful for
- * programs that uses a non-dll pthread
- * library. Such programs must call ptw32_processInitialize() explicitly,
- * since this initialization routine is automatically called only when
- * the dll is loaded.
- */
- return PTW32_TRUE;
- }
-
- ptw32_processInitialized = PTW32_TRUE;
-
- /*
- * Initialize Keys
- */
- if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) ||
- (pthread_key_create (&ptw32_cleanupKey, NULL) != 0))
- {
-
- ptw32_processTerminate ();
- }
-
- return (ptw32_processInitialized);
-
-} /* processInitialize */
diff --git a/pthreads/src/ptw32_processTerminate.c b/pthreads/src/ptw32_processTerminate.c
deleted file mode 100644
index 83f0f23..0000000
--- a/pthreads/src/ptw32_processTerminate.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * ptw32_processTerminate.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-void
-ptw32_processTerminate (void)
- /*
- * ------------------------------------------------------
- * DOCPRIVATE
- * This function performs process wide termination for
- * the pthread library.
- *
- * PARAMETERS
- * N/A
- *
- * DESCRIPTION
- * This function performs process wide termination for
- * the pthread library.
- * This routine sets the global variable
- * ptw32_processInitialized to FALSE
- *
- * RESULTS
- * N/A
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_processInitialized)
- {
- ptw32_thread_t * tp, * tpNext;
- ptw32_mcs_local_node_t node;
-
- if (ptw32_selfThreadKey != NULL)
- {
- /*
- * Release ptw32_selfThreadKey
- */
- pthread_key_delete (ptw32_selfThreadKey);
-
- ptw32_selfThreadKey = NULL;
- }
-
- if (ptw32_cleanupKey != NULL)
- {
- /*
- * Release ptw32_cleanupKey
- */
- pthread_key_delete (ptw32_cleanupKey);
-
- ptw32_cleanupKey = NULL;
- }
-
- ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
-
- tp = ptw32_threadReuseTop;
- while (tp != PTW32_THREAD_REUSE_EMPTY)
- {
- tpNext = tp->prevReuse;
- free (tp);
- tp = tpNext;
- }
-
- ptw32_mcs_lock_release(&node);
-
- ptw32_processInitialized = PTW32_FALSE;
- }
-
-} /* processTerminate */
diff --git a/pthreads/src/ptw32_relmillisecs.c b/pthreads/src/ptw32_relmillisecs.c
deleted file mode 100644
index 894d5c9..0000000
--- a/pthreads/src/ptw32_relmillisecs.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * ptw32_relmillisecs.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#if !defined(NEED_FTIME)
-#include <sys/timeb.h>
-#endif
-
-
-#if defined(PTW32_BUILD_INLINED)
-INLINE
-#endif /* PTW32_BUILD_INLINED */
-DWORD
-ptw32_relmillisecs (const struct timespec * abstime)
-{
- const int64_t NANOSEC_PER_MILLISEC = 1000000;
- const int64_t MILLISEC_PER_SEC = 1000;
- DWORD milliseconds;
- int64_t tmpAbsMilliseconds;
- int64_t tmpCurrMilliseconds;
-#if defined(NEED_FTIME)
- struct timespec currSysTime;
- FILETIME ft;
- SYSTEMTIME st;
-#else /* ! NEED_FTIME */
-#if ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \
- ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 )
- struct __timeb64 currSysTime;
-#else
- struct _timeb currSysTime;
-#endif
-#endif /* NEED_FTIME */
-
-
- /*
- * Calculate timeout as milliseconds from current system time.
- */
-
- /*
- * subtract current system time from abstime in a way that checks
- * that abstime is never in the past, or is never equivalent to the
- * defined INFINITE value (0xFFFFFFFF).
- *
- * Assume all integers are unsigned, i.e. cannot test if less than 0.
- */
- tmpAbsMilliseconds = (int64_t)abstime->tv_sec * MILLISEC_PER_SEC;
- tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
-
- /* get current system time */
-
-#if defined(NEED_FTIME)
-
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, &ft);
- /*
- * GetSystemTimeAsFileTime(&ft); would be faster,
- * but it does not exist on WinCE
- */
-
- ptw32_filetime_to_timespec(&ft, &currSysTime);
-
- tmpCurrMilliseconds = (int64_t)currSysTime.tv_sec * MILLISEC_PER_SEC;
- tmpCurrMilliseconds += ((int64_t)currSysTime.tv_nsec + (NANOSEC_PER_MILLISEC/2))
- / NANOSEC_PER_MILLISEC;
-
-#else /* ! NEED_FTIME */
-
-#if defined(_MSC_VER) && _MSC_VER >= 1400
- _ftime64_s(&currSysTime);
-#elif ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \
- ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 )
- _ftime64(&currSysTime);
-#else
- _ftime(&currSysTime);
-#endif
-
- tmpCurrMilliseconds = (int64_t) currSysTime.time * MILLISEC_PER_SEC;
- tmpCurrMilliseconds += (int64_t) currSysTime.millitm;
-
-#endif /* NEED_FTIME */
-
- if (tmpAbsMilliseconds > tmpCurrMilliseconds)
- {
- milliseconds = (DWORD) (tmpAbsMilliseconds - tmpCurrMilliseconds);
- if (milliseconds == INFINITE)
- {
- /* Timeouts must be finite */
- milliseconds--;
- }
- }
- else
- {
- /* The abstime given is in the past */
- milliseconds = 0;
- }
-
- return milliseconds;
-}
diff --git a/pthreads/src/ptw32_reuse.c b/pthreads/src/ptw32_reuse.c
deleted file mode 100644
index 7325857..0000000
--- a/pthreads/src/ptw32_reuse.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * ptw32_threadReuse.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-/*
- * How it works:
- * A pthread_t is a struct (2x32 bit scalar types on IA-32, 2x64 bit on IA-64)
- * which is normally passed/returned by value to/from pthreads routines.
- * Applications are therefore storing a copy of the struct as it is at that
- * time.
- *
- * The original pthread_t struct plus all copies of it contain the address of
- * the thread state struct ptw32_thread_t_ (p), plus a reuse counter (x). Each
- * ptw32_thread_t contains the original copy of it's pthread_t.
- * Once malloced, a ptw32_thread_t_ struct is not freed until the process exits.
- *
- * The thread reuse stack is a simple LILO stack managed through a singly
- * linked list element in the ptw32_thread_t.
- *
- * Each time a thread is destroyed, the ptw32_thread_t address is pushed onto the
- * reuse stack after it's ptHandle's reuse counter has been incremented.
- *
- * The following can now be said from this:
- * - two pthread_t's are identical if their ptw32_thread_t reference pointers
- * are equal and their reuse counters are equal. That is,
- *
- * equal = (a.p == b.p && a.x == b.x)
- *
- * - a pthread_t copy refers to a destroyed thread if the reuse counter in
- * the copy is not equal to the reuse counter in the original.
- *
- * threadDestroyed = (copy.x != ((ptw32_thread_t *)copy.p)->ptHandle.x)
- *
- */
-
-/*
- * Pop a clean pthread_t struct off the reuse stack.
- */
-pthread_t
-ptw32_threadReusePop (void)
-{
- pthread_t t = {NULL, 0};
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
-
- if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop)
- {
- ptw32_thread_t * tp;
-
- tp = ptw32_threadReuseTop;
-
- ptw32_threadReuseTop = tp->prevReuse;
-
- if (PTW32_THREAD_REUSE_EMPTY == ptw32_threadReuseTop)
- {
- ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY;
- }
-
- tp->prevReuse = NULL;
-
- t = tp->ptHandle;
- }
-
- ptw32_mcs_lock_release(&node);
-
- return t;
-
-}
-
-/*
- * Push a clean pthread_t struct onto the reuse stack.
- * Must be re-initialised when reused.
- * All object elements (mutexes, events etc) must have been either
- * detroyed before this, or never initialised.
- */
-void
-ptw32_threadReusePush (pthread_t thread)
-{
- ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
- pthread_t t;
- ptw32_mcs_local_node_t node;
-
- ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
-
- t = tp->ptHandle;
- memset(tp, 0, sizeof(ptw32_thread_t));
-
- /* Must restore the original POSIX handle that we just wiped. */
- tp->ptHandle = t;
-
- /* Bump the reuse counter now */
-#if defined(PTW32_THREAD_ID_REUSE_INCREMENT)
- tp->ptHandle.x += PTW32_THREAD_ID_REUSE_INCREMENT;
-#else
- tp->ptHandle.x++;
-#endif
-
- tp->state = PThreadStateReuse;
-
- tp->prevReuse = PTW32_THREAD_REUSE_EMPTY;
-
- if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseBottom)
- {
- ptw32_threadReuseBottom->prevReuse = tp;
- }
- else
- {
- ptw32_threadReuseTop = tp;
- }
-
- ptw32_threadReuseBottom = tp;
-
- ptw32_mcs_lock_release(&node);
-}
diff --git a/pthreads/src/ptw32_rwlock_cancelwrwait.c b/pthreads/src/ptw32_rwlock_cancelwrwait.c
deleted file mode 100644
index a057bd1..0000000
--- a/pthreads/src/ptw32_rwlock_cancelwrwait.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ptw32_rwlock_cancelwrwait.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-void
-ptw32_rwlock_cancelwrwait (void *arg)
-{
- pthread_rwlock_t rwl = (pthread_rwlock_t) arg;
-
- rwl->nSharedAccessCount = -rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
-
- (void) pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
- (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
-}
diff --git a/pthreads/src/ptw32_rwlock_check_need_init.c b/pthreads/src/ptw32_rwlock_check_need_init.c
deleted file mode 100644
index 858ee27..0000000
--- a/pthreads/src/ptw32_rwlock_check_need_init.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * pthread_rwlock_check_need_init.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-INLINE int
-ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock)
-{
- int result = 0;
- ptw32_mcs_local_node_t node;
-
- /*
- * The following guarded test is specifically for statically
- * initialised rwlocks (via PTHREAD_RWLOCK_INITIALIZER).
- */
- ptw32_mcs_lock_acquire(&ptw32_rwlock_test_init_lock, &node);
-
- /*
- * We got here possibly under race
- * conditions. Check again inside the critical section
- * and only initialise if the rwlock is valid (not been destroyed).
- * If a static rwlock has been destroyed, the application can
- * re-initialise it only by calling pthread_rwlock_init()
- * explicitly.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = pthread_rwlock_init (rwlock, NULL);
- }
- else if (*rwlock == NULL)
- {
- /*
- * The rwlock has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
-
- ptw32_mcs_lock_release(&node);
-
- return result;
-}
diff --git a/pthreads/src/ptw32_semwait.c b/pthreads/src/ptw32_semwait.c
deleted file mode 100644
index c3c4fd0..0000000
--- a/pthreads/src/ptw32_semwait.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * ptw32_semwait.c
- *
- * Description:
- * This translation unit implements mutual exclusion (mutex) primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if !defined(_UWIN)
-/*# include <process.h> */
-#endif
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-ptw32_semwait (sem_t * sem)
- /*
- * ------------------------------------------------------
- * DESCRIPTION
- * This function waits on a POSIX semaphore. If the
- * semaphore value is greater than zero, it decreases
- * its value by one. If the semaphore value is zero, then
- * the calling thread (or process) is blocked until it can
- * successfully decrease the value.
- *
- * Unlike sem_wait(), this routine is non-cancelable.
- *
- * RESULTS
- * 0 successfully decreased semaphore,
- * -1 failed, error in errno.
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore,
- * ENOSYS semaphores are not supported,
- * EINTR the function was interrupted by a signal,
- * EDEADLK a deadlock condition was detected.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- sem_t s = *sem;
-
- if (s == NULL)
- {
- result = EINVAL;
- }
- else
- {
- if ((result = pthread_mutex_lock (&s->lock)) == 0)
- {
- int v;
-
- /* See sem_destroy.c
- */
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- v = --s->value;
- (void) pthread_mutex_unlock (&s->lock);
-
- if (v < 0)
- {
- /* Must wait */
- if (WaitForSingleObject (s->sem, INFINITE) == WAIT_OBJECT_0)
- {
-#if defined(NEED_SEM)
- if (pthread_mutex_lock (&s->lock) == 0)
- {
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- if (s->leftToUnblock > 0)
- {
- --s->leftToUnblock;
- SetEvent(s->sem);
- }
- (void) pthread_mutex_unlock (&s->lock);
- }
-#endif
- return 0;
- }
- }
- else
- {
- return 0;
- }
- }
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- return 0;
-
-} /* ptw32_semwait */
diff --git a/pthreads/src/ptw32_spinlock_check_need_init.c b/pthreads/src/ptw32_spinlock_check_need_init.c
deleted file mode 100644
index 8808454..0000000
--- a/pthreads/src/ptw32_spinlock_check_need_init.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * ptw32_spinlock_check_need_init.c
- *
- * Description:
- * This translation unit implements spin lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-INLINE int
-ptw32_spinlock_check_need_init (pthread_spinlock_t * lock)
-{
- int result = 0;
- ptw32_mcs_local_node_t node;
-
- /*
- * The following guarded test is specifically for statically
- * initialised spinlocks (via PTHREAD_SPINLOCK_INITIALIZER).
- */
- ptw32_mcs_lock_acquire(&ptw32_spinlock_test_init_lock, &node);
-
- /*
- * We got here possibly under race
- * conditions. Check again inside the critical section
- * and only initialise if the spinlock is valid (not been destroyed).
- * If a static spinlock has been destroyed, the application can
- * re-initialise it only by calling pthread_spin_init()
- * explicitly.
- */
- if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
- {
- result = pthread_spin_init (lock, PTHREAD_PROCESS_PRIVATE);
- }
- else if (*lock == NULL)
- {
- /*
- * The spinlock has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
-
- ptw32_mcs_lock_release(&node);
-
- return (result);
-}
diff --git a/pthreads/src/ptw32_threadDestroy.c b/pthreads/src/ptw32_threadDestroy.c
deleted file mode 100644
index 41499b1..0000000
--- a/pthreads/src/ptw32_threadDestroy.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * ptw32_threadDestroy.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-void
-ptw32_threadDestroy (pthread_t thread)
-{
- ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
- ptw32_thread_t threadCopy;
-
- if (tp != NULL)
- {
- /*
- * Copy thread state so that the thread can be atomically NULLed.
- */
- memcpy (&threadCopy, tp, sizeof (threadCopy));
-
- /*
- * Thread ID structs are never freed. They're NULLed and reused.
- * This also sets the thread to PThreadStateInitial (invalid).
- */
- ptw32_threadReusePush (thread);
-
- /* Now work on the copy. */
- if (threadCopy.cancelEvent != NULL)
- {
- CloseHandle (threadCopy.cancelEvent);
- }
-
-#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
- /*
- * See documentation for endthread vs endthreadex.
- */
- if (threadCopy.threadH != 0)
- {
- CloseHandle (threadCopy.threadH);
- }
-#endif
-
- }
-} /* ptw32_threadDestroy */
-
diff --git a/pthreads/src/ptw32_threadStart.c b/pthreads/src/ptw32_threadStart.c
deleted file mode 100644
index cb08403..0000000
--- a/pthreads/src/ptw32_threadStart.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * ptw32_threadStart.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include <stdio.h>
-
-#if defined(__CLEANUP_C)
-# include <setjmp.h>
-#endif
-
-#if defined(__CLEANUP_SEH)
-
-static DWORD
-ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
-{
- switch (ep->ExceptionRecord->ExceptionCode)
- {
- case EXCEPTION_PTW32_SERVICES:
- {
- DWORD param;
- DWORD numParams = ep->ExceptionRecord->NumberParameters;
-
- numParams = (numParams > 3) ? 3 : numParams;
-
- for (param = 0; param < numParams; param++)
- {
- ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
- }
-
- return EXCEPTION_EXECUTE_HANDLER;
- break;
- }
- default:
- {
- /*
- * A system unexpected exception has occurred running the user's
- * routine. We need to cleanup before letting the exception
- * out of thread scope.
- */
- pthread_t self = pthread_self ();
-
- ptw32_callUserDestroyRoutines (self);
-
- return EXCEPTION_CONTINUE_SEARCH;
- break;
- }
- }
-}
-
-#elif defined(__CLEANUP_CXX)
-
-#if defined(_MSC_VER)
-# include <eh.h>
-#elif defined(__WATCOMC__)
-# include <eh.h>
-# include <exceptio.h>
-typedef terminate_handler
- terminate_function;
-#else
-# if defined(__GNUC__) && __GNUC__ < 3
-# include <new.h>
-# else
-# include <new>
-using
- std::terminate_handler;
-using
- std::terminate;
-using
- std::set_terminate;
-# endif
-typedef terminate_handler
- terminate_function;
-#endif
-
-static terminate_function
- ptw32_oldTerminate;
-
-void
-ptw32_terminate ()
-{
- set_terminate (ptw32_oldTerminate);
- (void) pthread_win32_thread_detach_np ();
- terminate ();
-}
-
-#endif
-
-#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || (defined (__MSVCRT__) && ! defined (__DMC__))
-unsigned
- __stdcall
-#else
-void
-#endif
-ptw32_threadStart (void *vthreadParms)
-{
- ThreadParms * threadParms = (ThreadParms *) vthreadParms;
- pthread_t self;
- ptw32_thread_t * sp;
- void *(*start) (void *);
- void * arg;
-
-#if defined(__CLEANUP_SEH)
- DWORD
- ei[] = { 0, 0, 0 };
-#endif
-
-#if defined(__CLEANUP_C)
- int setjmp_rc;
-#endif
-
- ptw32_mcs_local_node_t stateLock;
- void * status = (void *) 0;
-
- self = threadParms->tid;
- sp = (ptw32_thread_t *) self.p;
- start = threadParms->start;
- arg = threadParms->arg;
-
- free (threadParms);
-
-#if (defined(__MINGW64__) || defined(__MINGW32__)) && ! defined (__MSVCRT__)
- /*
- * beginthread does not return the thread id and is running
- * before it returns us the thread handle, and so we do it here.
- */
- sp->thread = GetCurrentThreadId ();
- /*
- * Here we're using stateLock as a general-purpose lock
- * to make the new thread wait until the creating thread
- * has the new handle.
- */
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
- pthread_setspecific (ptw32_selfThreadKey, sp);
-#else
- pthread_setspecific (ptw32_selfThreadKey, sp);
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
-#endif
-
- sp->state = PThreadStateRunning;
- ptw32_mcs_lock_release (&stateLock);
-
-#if defined(__CLEANUP_SEH)
-
- __try
- {
- /*
- * Run the caller's routine;
- */
- status = sp->exitStatus = (*start) (arg);
- sp->state = PThreadStateExiting;
-
-#if defined(_UWIN)
- if (--pthread_count <= 0)
- exit (0);
-#endif
-
- }
- __except (ExceptionFilter (GetExceptionInformation (), ei))
- {
- switch (ei[0])
- {
- case PTW32_EPS_CANCEL:
- status = sp->exitStatus = PTHREAD_CANCELED;
-#if defined(_UWIN)
- if (--pthread_count <= 0)
- exit (0);
-#endif
- break;
- case PTW32_EPS_EXIT:
- status = sp->exitStatus;
- break;
- default:
- status = sp->exitStatus = PTHREAD_CANCELED;
- break;
- }
- }
-
-#else /* __CLEANUP_SEH */
-
-#if defined(__CLEANUP_C)
-
- setjmp_rc = setjmp (sp->start_mark);
-
- if (0 == setjmp_rc)
- {
-
- /*
- * Run the caller's routine;
- */
- status = sp->exitStatus = (*start) (arg);
- sp->state = PThreadStateExiting;
- }
- else
- {
- switch (setjmp_rc)
- {
- case PTW32_EPS_CANCEL:
- status = sp->exitStatus = PTHREAD_CANCELED;
- break;
- case PTW32_EPS_EXIT:
- status = sp->exitStatus;
- break;
- default:
- status = sp->exitStatus = PTHREAD_CANCELED;
- break;
- }
- }
-
-#else /* __CLEANUP_C */
-
-#if defined(__CLEANUP_CXX)
-
- ptw32_oldTerminate = set_terminate (&ptw32_terminate);
-
- try
- {
- /*
- * Run the caller's routine in a nested try block so that we
- * can run the user's terminate function, which may call
- * pthread_exit() or be canceled.
- */
- try
- {
- status = sp->exitStatus = (*start) (arg);
- sp->state = PThreadStateExiting;
- }
- catch (ptw32_exception &)
- {
- /*
- * Pass these through to the outer block.
- */
- throw;
- }
- catch (...)
- {
- /*
- * We want to run the user's terminate function if supplied.
- * That function may call pthread_exit() or be canceled, which will
- * be handled by the outer try block.
- *
- * ptw32_terminate() will be called if there is no user
- * supplied function.
- */
- terminate_function
- term_func = set_terminate (0);
- set_terminate (term_func);
-
- if (term_func != 0)
- {
- term_func ();
- }
- throw;
- }
- }
- catch (ptw32_exception_cancel &)
- {
- /*
- * Thread was canceled.
- */
- status = sp->exitStatus = PTHREAD_CANCELED;
- }
- catch (ptw32_exception_exit &)
- {
- /*
- * Thread was exited via pthread_exit().
- */
- status = sp->exitStatus;
- }
- catch (...)
- {
- /*
- * A system unexpected exception has occurred running the user's
- * terminate routine. We get control back within this block
- * and exit with a substitute status. If the thread was not
- * cancelled then this indicates the unhandled exception.
- */
- status = sp->exitStatus = PTHREAD_CANCELED;
- }
-
- (void) set_terminate (ptw32_oldTerminate);
-
-#else
-
-#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-
-#endif /* __CLEANUP_CXX */
-#endif /* __CLEANUP_C */
-#endif /* __CLEANUP_SEH */
-
-#if defined(PTW32_STATIC_LIB)
- /*
- * We need to cleanup the pthread now if we have
- * been statically linked, in which case the cleanup
- * in dllMain won't get done. Joinable threads will
- * only be partially cleaned up and must be fully cleaned
- * up by pthread_join() or pthread_detach().
- *
- * Note: if this library has been statically linked,
- * implicitly created pthreads (those created
- * for Win32 threads which have called pthreads routines)
- * must be cleaned up explicitly by the application
- * (by calling pthread_win32_thread_detach_np()).
- * For the dll, dllMain will do the cleanup automatically.
- */
- (void) pthread_win32_thread_detach_np ();
-#endif
-
-#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
- _endthreadex ((unsigned)(size_t) status);
-#else
- _endthread ();
-#endif
-
- /*
- * Never reached.
- */
-
-#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
- return (unsigned)(size_t) status;
-#endif
-
-} /* ptw32_threadStart */
diff --git a/pthreads/src/ptw32_throw.c b/pthreads/src/ptw32_throw.c
deleted file mode 100644
index 1404e94..0000000
--- a/pthreads/src/ptw32_throw.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * ptw32_throw.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#if defined(__CLEANUP_C)
-# include <setjmp.h>
-#endif
-
-/*
- * ptw32_throw
- *
- * All canceled and explicitly exited POSIX threads go through
- * here. This routine knows how to exit both POSIX initiated threads and
- * 'implicit' POSIX threads for each of the possible language modes (C,
- * C++, and SEH).
- */
-#if defined(_MSC_VER)
-/*
- * Ignore the warning:
- * "C++ exception specification ignored except to indicate that
- * the function is not __declspec(nothrow)."
- */
-#pragma warning(disable:4290)
-#endif
-void
-ptw32_throw (DWORD exception)
-#if defined(__CLEANUP_CXX)
- throw(ptw32_exception_cancel,ptw32_exception_exit)
-#endif
-{
- /*
- * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
- * unnecessarily.
- */
- ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
-
-#if defined(__CLEANUP_SEH)
- DWORD exceptionInformation[3];
-#endif
-
- sp->state = PThreadStateExiting;
-
- if (exception != PTW32_EPS_CANCEL && exception != PTW32_EPS_EXIT)
- {
- /* Should never enter here */
- exit (1);
- }
-
- if (NULL == sp || sp->implicit)
- {
- /*
- * We're inside a non-POSIX initialised Win32 thread
- * so there is no point to jump or throw back to. Just do an
- * explicit thread exit here after cleaning up POSIX
- * residue (i.e. cleanup handlers, POSIX thread handle etc).
- */
-#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
- unsigned exitCode = 0;
-
- switch (exception)
- {
- case PTW32_EPS_CANCEL:
- exitCode = (unsigned)(size_t) PTHREAD_CANCELED;
- break;
- case PTW32_EPS_EXIT:
- if (NULL != sp)
- {
- exitCode = (unsigned)(size_t) sp->exitStatus;
- }
- break;
- }
-#endif
-
-#if defined(PTW32_STATIC_LIB)
-
- pthread_win32_thread_detach_np ();
-
-#endif
-
-#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
- _endthreadex (exitCode);
-#else
- _endthread ();
-#endif
-
- }
-
-#if defined(__CLEANUP_SEH)
-
-
- exceptionInformation[0] = (DWORD) (exception);
- exceptionInformation[1] = (DWORD) (0);
- exceptionInformation[2] = (DWORD) (0);
-
- RaiseException (EXCEPTION_PTW32_SERVICES, 0, 3, exceptionInformation);
-
-#else /* __CLEANUP_SEH */
-
-#if defined(__CLEANUP_C)
-
- ptw32_pop_cleanup_all (1);
- longjmp (sp->start_mark, exception);
-
-#else /* __CLEANUP_C */
-
-#if defined(__CLEANUP_CXX)
-
- switch (exception)
- {
- case PTW32_EPS_CANCEL:
- throw ptw32_exception_cancel ();
- break;
- case PTW32_EPS_EXIT:
- throw ptw32_exception_exit ();
- break;
- }
-
-#else
-
-#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-
-#endif /* __CLEANUP_CXX */
-
-#endif /* __CLEANUP_C */
-
-#endif /* __CLEANUP_SEH */
-
- /* Never reached */
-}
-
-
-void
-ptw32_pop_cleanup_all (int execute)
-{
- while (NULL != ptw32_pop_cleanup (execute))
- {
- }
-}
-
-
-DWORD
-ptw32_get_exception_services_code (void)
-{
-#if defined(__CLEANUP_SEH)
-
- return EXCEPTION_PTW32_SERVICES;
-
-#else
-
- return (DWORD)0;
-
-#endif
-}
diff --git a/pthreads/src/ptw32_timespec.c b/pthreads/src/ptw32_timespec.c
deleted file mode 100644
index 6318957..0000000
--- a/pthreads/src/ptw32_timespec.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * ptw32_timespec.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-#if defined(NEED_FTIME)
-
-/*
- * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
- */
-#define PTW32_TIMESPEC_TO_FILETIME_OFFSET \
- ( ((int64_t) 27111902 << 32) + (int64_t) 3577643008 )
-
-INLINE void
-ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft)
- /*
- * -------------------------------------------------------------------
- * converts struct timespec
- * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
- * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is
- * expressed in 100 nanoseconds from Jan 1, 1601,
- * -------------------------------------------------------------------
- */
-{
- *(int64_t *) ft = ts->tv_sec * 10000000
- + (ts->tv_nsec + 50) / 100 + PTW32_TIMESPEC_TO_FILETIME_OFFSET;
-}
-
-INLINE void
-ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts)
- /*
- * -------------------------------------------------------------------
- * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is
- * expressed in 100 nanoseconds from Jan 1, 1601,
- * into struct timespec
- * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
- * -------------------------------------------------------------------
- */
-{
- ts->tv_sec =
- (int) ((*(int64_t *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
- ts->tv_nsec =
- (int) ((*(int64_t *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET -
- ((int64_t) ts->tv_sec * (int64_t) 10000000)) * 100);
-}
-
-#endif /* NEED_FTIME */
diff --git a/pthreads/src/ptw32_tkAssocCreate.c b/pthreads/src/ptw32_tkAssocCreate.c
deleted file mode 100644
index 50d6c50..0000000
--- a/pthreads/src/ptw32_tkAssocCreate.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ptw32_tkAssocCreate.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-int
-ptw32_tkAssocCreate (ptw32_thread_t * sp, pthread_key_t key)
- /*
- * -------------------------------------------------------------------
- * This routine creates an association that
- * is unique for the given (thread,key) combination.The association
- * is referenced by both the thread and the key.
- * This association allows us to determine what keys the
- * current thread references and what threads a given key
- * references.
- * See the detailed description
- * at the beginning of this file for further details.
- *
- * Notes:
- * 1) New associations are pushed to the beginning of the
- * chain so that the internal ptw32_selfThreadKey association
- * is always last, thus allowing selfThreadExit to
- * be implicitly called last by pthread_exit.
- * 2)
- *
- * Parameters:
- * thread
- * current running thread.
- * key
- * key on which to create an association.
- * Returns:
- * 0 - if successful,
- * ENOMEM - not enough memory to create assoc or other object
- * EINVAL - an internal error occurred
- * ENOSYS - an internal error occurred
- * -------------------------------------------------------------------
- */
-{
- ThreadKeyAssoc *assoc;
-
- /*
- * Have to create an association and add it
- * to both the key and the thread.
- *
- * Both key->keyLock and thread->threadLock are locked before
- * entry to this routine.
- */
- assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
-
- if (assoc == NULL)
- {
- return ENOMEM;
- }
-
- assoc->thread = sp;
- assoc->key = key;
-
- /*
- * Register assoc with key
- */
- assoc->prevThread = NULL;
- assoc->nextThread = (ThreadKeyAssoc *) key->threads;
- if (assoc->nextThread != NULL)
- {
- assoc->nextThread->prevThread = assoc;
- }
- key->threads = (void *) assoc;
-
- /*
- * Register assoc with thread
- */
- assoc->prevKey = NULL;
- assoc->nextKey = (ThreadKeyAssoc *) sp->keys;
- if (assoc->nextKey != NULL)
- {
- assoc->nextKey->prevKey = assoc;
- }
- sp->keys = (void *) assoc;
-
- return (0);
-
-} /* ptw32_tkAssocCreate */
diff --git a/pthreads/src/ptw32_tkAssocDestroy.c b/pthreads/src/ptw32_tkAssocDestroy.c
deleted file mode 100644
index fedebf5..0000000
--- a/pthreads/src/ptw32_tkAssocDestroy.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * ptw32_tkAssocDestroy.c
- *
- * Description:
- * This translation unit implements routines which are private to
- * the implementation and may be used throughout it.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-void
-ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc)
- /*
- * -------------------------------------------------------------------
- * This routine releases all resources for the given ThreadKeyAssoc
- * once it is no longer being referenced
- * ie) either the key or thread has stopped referencing it.
- *
- * Parameters:
- * assoc
- * an instance of ThreadKeyAssoc.
- * Returns:
- * N/A
- * -------------------------------------------------------------------
- */
-{
-
- /*
- * Both key->keyLock and thread->threadLock are locked before
- * entry to this routine.
- */
- if (assoc != NULL)
- {
- ThreadKeyAssoc * prev, * next;
-
- /* Remove assoc from thread's keys chain */
- prev = assoc->prevKey;
- next = assoc->nextKey;
- if (prev != NULL)
- {
- prev->nextKey = next;
- }
- if (next != NULL)
- {
- next->prevKey = prev;
- }
-
- if (assoc->thread->keys == assoc)
- {
- /* We're at the head of the thread's keys chain */
- assoc->thread->keys = next;
- }
- if (assoc->thread->nextAssoc == assoc)
- {
- /*
- * Thread is exiting and we're deleting the assoc to be processed next.
- * Hand thread the assoc after this one.
- */
- assoc->thread->nextAssoc = next;
- }
-
- /* Remove assoc from key's threads chain */
- prev = assoc->prevThread;
- next = assoc->nextThread;
- if (prev != NULL)
- {
- prev->nextThread = next;
- }
- if (next != NULL)
- {
- next->prevThread = prev;
- }
-
- if (assoc->key->threads == assoc)
- {
- /* We're at the head of the key's threads chain */
- assoc->key->threads = next;
- }
-
- free (assoc);
- }
-
-} /* ptw32_tkAssocDestroy */
diff --git a/pthreads/src/rwlock.c b/pthreads/src/rwlock.c
deleted file mode 100644
index 4a3cd25..0000000
--- a/pthreads/src/rwlock.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * rwlock.c
- *
- * Description:
- * This translation unit implements read/write lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "ptw32_rwlock_check_need_init.c"
-#include "ptw32_rwlock_cancelwrwait.c"
-#include "pthread_rwlock_init.c"
-#include "pthread_rwlock_destroy.c"
-#include "pthread_rwlockattr_init.c"
-#include "pthread_rwlockattr_destroy.c"
-#include "pthread_rwlockattr_getpshared.c"
-#include "pthread_rwlockattr_setpshared.c"
-#include "pthread_rwlock_rdlock.c"
-#include "pthread_rwlock_timedrdlock.c"
-#include "pthread_rwlock_wrlock.c"
-#include "pthread_rwlock_timedwrlock.c"
-#include "pthread_rwlock_unlock.c"
-#include "pthread_rwlock_tryrdlock.c"
-#include "pthread_rwlock_trywrlock.c"
diff --git a/pthreads/src/sched.c b/pthreads/src/sched.c
deleted file mode 100644
index ed30ea7..0000000
--- a/pthreads/src/sched.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * sched.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-#include "pthread_attr_setschedpolicy.c"
-#include "pthread_attr_getschedpolicy.c"
-#include "pthread_attr_setschedparam.c"
-#include "pthread_attr_getschedparam.c"
-#include "pthread_attr_setinheritsched.c"
-#include "pthread_attr_getinheritsched.c"
-#include "pthread_setschedparam.c"
-#include "pthread_getschedparam.c"
-#include "sched_get_priority_max.c"
-#include "sched_get_priority_min.c"
-#include "sched_setscheduler.c"
-#include "sched_getscheduler.c"
-#include "sched_yield.c"
diff --git a/pthreads/src/sched.h b/pthreads/src/sched.h
deleted file mode 100644
index f36a97a..0000000
--- a/pthreads/src/sched.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Module: sched.h
- *
- * Purpose:
- * Provides an implementation of POSIX realtime extensions
- * as defined in
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-#if !defined(_SCHED_H)
-#define _SCHED_H
-
-#undef PTW32_SCHED_LEVEL
-
-#if defined(_POSIX_SOURCE)
-#define PTW32_SCHED_LEVEL 0
-/* Early POSIX */
-#endif
-
-#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
-#undef PTW32_SCHED_LEVEL
-#define PTW32_SCHED_LEVEL 1
-/* Include 1b, 1c and 1d */
-#endif
-
-#if defined(INCLUDE_NP)
-#undef PTW32_SCHED_LEVEL
-#define PTW32_SCHED_LEVEL 2
-/* Include Non-Portable extensions */
-#endif
-
-#define PTW32_SCHED_LEVEL_MAX 3
-
-#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL)
-#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX
-/* Include everything */
-#endif
-
-
-#if defined(__GNUC__) && !defined(__declspec)
-# error Please upgrade your GNU compiler to one that supports __declspec.
-#endif
-
-/*
- * When building the library, you should define PTW32_BUILD so that
- * the variables/functions are exported correctly. When using the library,
- * do NOT define PTW32_BUILD, and then the variables/functions will
- * be imported correctly.
- */
-#if !defined(PTW32_STATIC_LIB)
-# if defined(PTW32_BUILD)
-# define PTW32_DLLPORT __declspec (dllexport)
-# else
-# define PTW32_DLLPORT __declspec (dllimport)
-# endif
-#else
-# define PTW32_DLLPORT
-#endif
-
-/*
- * This is a duplicate of what is in the autoconf config.h,
- * which is only used when building the pthread-win32 libraries.
- */
-
-#if !defined(PTW32_CONFIG_H)
-# if defined(WINCE)
-# define NEED_ERRNO
-# define NEED_SEM
-# endif
-# if defined(__MINGW64__)
-# define HAVE_STRUCT_TIMESPEC
-# define HAVE_MODE_T
-# elif defined(_UWIN) || defined(__MINGW32__)
-# define HAVE_MODE_T
-# endif
-#endif
-
-/*
- *
- */
-
-#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
-#if defined(NEED_ERRNO)
-#include "need_errno.h"
-#else
-#include <errno.h>
-#endif
-#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */
-
-#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN)
-# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
-/* For pid_t */
-# include <sys/types.h>
-/* Required by Unix 98 */
-# include <time.h>
-# else
- typedef int pid_t;
-# endif
-#else
- typedef int pid_t;
-#endif
-
-/* Thread scheduling policies */
-
-enum {
- SCHED_OTHER = 0,
- SCHED_FIFO,
- SCHED_RR,
- SCHED_MIN = SCHED_OTHER,
- SCHED_MAX = SCHED_RR
-};
-
-struct sched_param {
- int sched_priority;
-};
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif /* __cplusplus */
-
-PTW32_DLLPORT int __cdecl sched_yield (void);
-
-PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
-
-PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
-
-PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
-
-PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
-
-/*
- * Note that this macro returns ENOTSUP rather than
- * ENOSYS as might be expected. However, returning ENOSYS
- * should mean that sched_get_priority_{min,max} are
- * not implemented as well as sched_rr_get_interval.
- * This is not the case, since we just don't support
- * round-robin scheduling. Therefore I have chosen to
- * return the same value as sched_setscheduler when
- * SCHED_RR is passed to it.
- */
-#define sched_rr_get_interval(_pid, _interval) \
- ( errno = ENOTSUP, (int) -1 )
-
-
-#if defined(__cplusplus)
-} /* End of extern "C" */
-#endif /* __cplusplus */
-
-#undef PTW32_SCHED_LEVEL
-#undef PTW32_SCHED_LEVEL_MAX
-
-#endif /* !_SCHED_H */
-
diff --git a/pthreads/src/sched_get_priority_max.c b/pthreads/src/sched_get_priority_max.c
deleted file mode 100644
index cabf232..0000000
--- a/pthreads/src/sched_get_priority_max.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * sched_get_priority_max.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-/*
- * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and
- * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
- *
- * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
- * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
- * highest priority use smaller numbers) and the following happens:
- *
- * sched_get_priority_min() returns 5
- * sched_get_priority_max() returns 1
- *
- * The following table shows the base priority levels for combinations
- * of priority class and priority value in Win32.
- *
- * Process Priority Class Thread Priority Level
- * -----------------------------------------------------------------
- * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 17 REALTIME_PRIORITY_CLASS -7
- * 18 REALTIME_PRIORITY_CLASS -6
- * 19 REALTIME_PRIORITY_CLASS -5
- * 20 REALTIME_PRIORITY_CLASS -4
- * 21 REALTIME_PRIORITY_CLASS -3
- * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 27 REALTIME_PRIORITY_CLASS 3
- * 28 REALTIME_PRIORITY_CLASS 4
- * 29 REALTIME_PRIORITY_CLASS 5
- * 30 REALTIME_PRIORITY_CLASS 6
- * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- *
- * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported.
- */
-
-
-int
-sched_get_priority_max (int policy)
-{
- if (policy < SCHED_MIN || policy > SCHED_MAX)
- {
- errno = EINVAL;
- return -1;
- }
-
-#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
- /* WinCE? */
- return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#else
- /* This is independent of scheduling policy in Win32. */
- return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#endif
-}
diff --git a/pthreads/src/sched_get_priority_min.c b/pthreads/src/sched_get_priority_min.c
deleted file mode 100644
index 9c4f859..0000000
--- a/pthreads/src/sched_get_priority_min.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * sched_get_priority_min.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-/*
- * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and
- * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
- *
- * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
- * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
- * highest priority use smaller numbers) and the following happens:
- *
- * sched_get_priority_min() returns 5
- * sched_get_priority_max() returns 1
- *
- * The following table shows the base priority levels for combinations
- * of priority class and priority value in Win32.
- *
- * Process Priority Class Thread Priority Level
- * -----------------------------------------------------------------
- * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE
- * 17 REALTIME_PRIORITY_CLASS -7
- * 18 REALTIME_PRIORITY_CLASS -6
- * 19 REALTIME_PRIORITY_CLASS -5
- * 20 REALTIME_PRIORITY_CLASS -4
- * 21 REALTIME_PRIORITY_CLASS -3
- * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
- * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
- * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
- * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
- * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
- * 27 REALTIME_PRIORITY_CLASS 3
- * 28 REALTIME_PRIORITY_CLASS 4
- * 29 REALTIME_PRIORITY_CLASS 5
- * 30 REALTIME_PRIORITY_CLASS 6
- * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
- *
- * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported.
- *
- */
-
-
-int
-sched_get_priority_min (int policy)
-{
- if (policy < SCHED_MIN || policy > SCHED_MAX)
- {
- errno = EINVAL;
- return -1;
- }
-
-#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
- /* WinCE? */
- return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#else
- /* This is independent of scheduling policy in Win32. */
- return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#endif
-}
diff --git a/pthreads/src/sched_getscheduler.c b/pthreads/src/sched_getscheduler.c
deleted file mode 100644
index 8769c15..0000000
--- a/pthreads/src/sched_getscheduler.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * sched_getscheduler.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-sched_getscheduler (pid_t pid)
-{
- /*
- * Win32 only has one policy which we call SCHED_OTHER.
- * However, we try to provide other valid side-effects
- * such as EPERM and ESRCH errors.
- */
- if (0 != pid)
- {
- int selfPid = (int) GetCurrentProcessId ();
-
- if (pid != selfPid)
- {
- HANDLE h =
- OpenProcess (PROCESS_QUERY_INFORMATION, PTW32_FALSE, (DWORD) pid);
-
- if (NULL == h)
- {
- errno =
- (GetLastError () ==
- (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
- return -1;
- }
- else
- CloseHandle(h);
- }
- }
-
- return SCHED_OTHER;
-}
diff --git a/pthreads/src/sched_setscheduler.c b/pthreads/src/sched_setscheduler.c
deleted file mode 100644
index 8691316..0000000
--- a/pthreads/src/sched_setscheduler.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * sched_setscheduler.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-sched_setscheduler (pid_t pid, int policy)
-{
- /*
- * Win32 only has one policy which we call SCHED_OTHER.
- * However, we try to provide other valid side-effects
- * such as EPERM and ESRCH errors. Choosing to check
- * for a valid policy last allows us to get the most value out
- * of this function.
- */
- if (0 != pid)
- {
- int selfPid = (int) GetCurrentProcessId ();
-
- if (pid != selfPid)
- {
- HANDLE h =
- OpenProcess (PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) pid);
-
- if (NULL == h)
- {
- errno =
- (GetLastError () ==
- (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
- return -1;
- }
- else
- CloseHandle(h);
- }
- }
-
- if (SCHED_OTHER != policy)
- {
- errno = ENOSYS;
- return -1;
- }
-
- /*
- * Don't set anything because there is nothing to set.
- * Just return the current (the only possible) value.
- */
- return SCHED_OTHER;
-}
diff --git a/pthreads/src/sched_yield.c b/pthreads/src/sched_yield.c
deleted file mode 100644
index 6ac5ed9..0000000
--- a/pthreads/src/sched_yield.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * sched_yield.c
- *
- * Description:
- * POSIX thread functions that deal with thread scheduling.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-#include "sched.h"
-
-int
-sched_yield (void)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function indicates that the calling thread is
- * willing to give up some time slices to other threads.
- *
- * PARAMETERS
- * N/A
- *
- *
- * DESCRIPTION
- * This function indicates that the calling thread is
- * willing to give up some time slices to other threads.
- * NOTE: Since this is part of POSIX 1003.1b
- * (realtime extensions), it is defined as returning
- * -1 if an error occurs and sets errno to the actual
- * error.
- *
- * RESULTS
- * 0 successfully created semaphore,
- * ENOSYS sched_yield not supported,
- *
- * ------------------------------------------------------
- */
-{
- Sleep (0);
-
- return 0;
-}
diff --git a/pthreads/src/sem_close.c b/pthreads/src/sem_close.c
deleted file mode 100644
index 6d7280f..0000000
--- a/pthreads/src/sem_close.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_close.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-/* ignore warning "unreferenced formal parameter" */
-#if defined(_MSC_VER)
-#pragma warning( disable : 4100 )
-#endif
-
-int
-sem_close (sem_t * sem)
-{
- errno = ENOSYS;
- return -1;
-} /* sem_close */
diff --git a/pthreads/src/sem_destroy.c b/pthreads/src/sem_destroy.c
deleted file mode 100644
index 6c98e80..0000000
--- a/pthreads/src/sem_destroy.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_destroy.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-int
-sem_destroy (sem_t * sem)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function destroys an unnamed semaphore.
- *
- * PARAMETERS
- * sem
- * pointer to an instance of sem_t
- *
- * DESCRIPTION
- * This function destroys an unnamed semaphore.
- *
- * RESULTS
- * 0 successfully destroyed semaphore,
- * -1 failed, error in errno
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore,
- * ENOSYS semaphores are not supported,
- * EBUSY threads (or processes) are currently
- * blocked on 'sem'
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- sem_t s = NULL;
-
- if (sem == NULL || *sem == NULL)
- {
- result = EINVAL;
- }
- else
- {
- s = *sem;
-
- if ((result = pthread_mutex_lock (&s->lock)) == 0)
- {
- if (s->value < 0)
- {
- (void) pthread_mutex_unlock (&s->lock);
- result = EBUSY;
- }
- else
- {
- /* There are no threads currently blocked on this semaphore. */
-
- if (!CloseHandle (s->sem))
- {
- (void) pthread_mutex_unlock (&s->lock);
- result = EINVAL;
- }
- else
- {
- /*
- * Invalidate the semaphore handle when we have the lock.
- * Other sema operations should test this after acquiring the lock
- * to check that the sema is still valid, i.e. before performing any
- * operations. This may only be necessary before the sema op routine
- * returns so that the routine can return EINVAL - e.g. if setting
- * s->value to SEM_VALUE_MAX below does force a fall-through.
- */
- *sem = NULL;
-
- /* Prevent anyone else actually waiting on or posting this sema.
- */
- s->value = SEM_VALUE_MAX;
-
- (void) pthread_mutex_unlock (&s->lock);
-
- do
- {
- /* Give other threads a chance to run and exit any sema op
- * routines. Due to the SEM_VALUE_MAX value, if sem_post or
- * sem_wait were blocked by us they should fall through.
- */
- Sleep(0);
- }
- while (pthread_mutex_destroy (&s->lock) == EBUSY);
- }
- }
- }
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- free (s);
-
- return 0;
-
-} /* sem_destroy */
diff --git a/pthreads/src/sem_getvalue.c b/pthreads/src/sem_getvalue.c
deleted file mode 100644
index baafb02..0000000
--- a/pthreads/src/sem_getvalue.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_getvalue.c
- *
- * Purpose:
- * Semaphores aren't actually part of PThreads.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1-2001
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-int
-sem_getvalue (sem_t * sem, int *sval)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function stores the current count value of the
- * semaphore.
- * RESULTS
- *
- * Return value
- *
- * 0 sval has been set.
- * -1 failed, error in errno
- *
- * in global errno
- *
- * EINVAL 'sem' is not a valid semaphore,
- * ENOSYS this function is not supported,
- *
- *
- * PARAMETERS
- *
- * sem pointer to an instance of sem_t
- *
- * sval pointer to int.
- *
- * DESCRIPTION
- * This function stores the current count value of the semaphore
- * pointed to by sem in the int pointed to by sval.
- */
-{
- if (sem == NULL || *sem == NULL || sval == NULL)
- {
- errno = EINVAL;
- return -1;
- }
- else
- {
- long value;
- register sem_t s = *sem;
- int result = 0;
-
- if ((result = pthread_mutex_lock(&s->lock)) == 0)
- {
- /* See sem_destroy.c
- */
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- value = s->value;
- (void) pthread_mutex_unlock(&s->lock);
- *sval = value;
- }
-
- return result;
- }
-
-} /* sem_getvalue */
diff --git a/pthreads/src/sem_init.c b/pthreads/src/sem_init.c
deleted file mode 100644
index f682f4b..0000000
--- a/pthreads/src/sem_init.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_init.c
- *
- * Purpose:
- * Semaphores aren't actually part of PThreads.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1-2001
- *
- * -------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-int
-sem_init (sem_t * sem, int pshared, unsigned int value)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function initializes a semaphore. The
- * initial value of the semaphore is 'value'
- *
- * PARAMETERS
- * sem
- * pointer to an instance of sem_t
- *
- * pshared
- * if zero, this semaphore may only be shared between
- * threads in the same process.
- * if nonzero, the semaphore can be shared between
- * processes
- *
- * value
- * initial value of the semaphore counter
- *
- * DESCRIPTION
- * This function initializes a semaphore. The
- * initial value of the semaphore is set to 'value'.
- *
- * RESULTS
- * 0 successfully created semaphore,
- * -1 failed, error in errno
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore, or
- * 'value' >= SEM_VALUE_MAX
- * ENOMEM out of memory,
- * ENOSPC a required resource has been exhausted,
- * ENOSYS semaphores are not supported,
- * EPERM the process lacks appropriate privilege
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- sem_t s = NULL;
-
- if (pshared != 0)
- {
- /*
- * Creating a semaphore that can be shared between
- * processes
- */
- result = EPERM;
- }
- else if (value > (unsigned int)SEM_VALUE_MAX)
- {
- result = EINVAL;
- }
- else
- {
- s = (sem_t) calloc (1, sizeof (*s));
-
- if (NULL == s)
- {
- result = ENOMEM;
- }
- else
- {
-
- s->value = value;
- if (pthread_mutex_init(&s->lock, NULL) == 0)
- {
-
-#if defined(NEED_SEM)
-
- s->sem = CreateEvent (NULL,
- PTW32_FALSE, /* auto (not manual) reset */
- PTW32_FALSE, /* initial state is unset */
- NULL);
-
- if (0 == s->sem)
- {
- free (s);
- (void) pthread_mutex_destroy(&s->lock);
- result = ENOSPC;
- }
- else
- {
- s->leftToUnblock = 0;
- }
-
-#else /* NEED_SEM */
-
- if ((s->sem = CreateSemaphore (NULL, /* Always NULL */
- (long) 0, /* Force threads to wait */
- (long) SEM_VALUE_MAX, /* Maximum value */
- NULL)) == 0) /* Name */
- {
- (void) pthread_mutex_destroy(&s->lock);
- result = ENOSPC;
- }
-
-#endif /* NEED_SEM */
-
- }
- else
- {
- result = ENOSPC;
- }
-
- if (result != 0)
- {
- free(s);
- }
- }
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- *sem = s;
-
- return 0;
-
-} /* sem_init */
diff --git a/pthreads/src/sem_open.c b/pthreads/src/sem_open.c
deleted file mode 100644
index fb1cc54..0000000
--- a/pthreads/src/sem_open.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_open.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-/* ignore warning "unreferenced formal parameter" */
-#if defined(_MSC_VER)
-#pragma warning( disable : 4100 )
-#endif
-
-int
-sem_open (const char *name, int oflag, mode_t mode, unsigned int value)
-{
- errno = ENOSYS;
- return -1;
-} /* sem_open */
diff --git a/pthreads/src/sem_post.c b/pthreads/src/sem_post.c
deleted file mode 100644
index 3483252..0000000
--- a/pthreads/src/sem_post.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_post.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-int
-sem_post (sem_t * sem)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function posts a wakeup to a semaphore.
- *
- * PARAMETERS
- * sem
- * pointer to an instance of sem_t
- *
- * DESCRIPTION
- * This function posts a wakeup to a semaphore. If there
- * are waiting threads (or processes), one is awakened;
- * otherwise, the semaphore value is incremented by one.
- *
- * RESULTS
- * 0 successfully posted semaphore,
- * -1 failed, error in errno
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore,
- * ENOSYS semaphores are not supported,
- * ERANGE semaphore count is too big
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- sem_t s = *sem;
-
- if (s == NULL)
- {
- result = EINVAL;
- }
- else if ((result = pthread_mutex_lock (&s->lock)) == 0)
- {
- /* See sem_destroy.c
- */
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- result = EINVAL;
- return -1;
- }
-
- if (s->value < SEM_VALUE_MAX)
- {
-#if defined(NEED_SEM)
- if (++s->value <= 0
- && !SetEvent(s->sem))
- {
- s->value--;
- result = EINVAL;
- }
-#else
- if (++s->value <= 0
- && !ReleaseSemaphore (s->sem, 1, NULL))
- {
- s->value--;
- result = EINVAL;
- }
-#endif /* NEED_SEM */
- }
- else
- {
- result = ERANGE;
- }
-
- (void) pthread_mutex_unlock (&s->lock);
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- return 0;
-
-} /* sem_post */
diff --git a/pthreads/src/sem_post_multiple.c b/pthreads/src/sem_post_multiple.c
deleted file mode 100644
index 44c168c..0000000
--- a/pthreads/src/sem_post_multiple.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_post_multiple.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-int
-sem_post_multiple (sem_t * sem, int count)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function posts multiple wakeups to a semaphore.
- *
- * PARAMETERS
- * sem
- * pointer to an instance of sem_t
- *
- * count
- * counter, must be greater than zero.
- *
- * DESCRIPTION
- * This function posts multiple wakeups to a semaphore. If there
- * are waiting threads (or processes), n <= count are awakened;
- * the semaphore value is incremented by count - n.
- *
- * RESULTS
- * 0 successfully posted semaphore,
- * -1 failed, error in errno
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore
- * or count is less than or equal to zero.
- * ERANGE semaphore count is too big
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- long waiters;
- sem_t s = *sem;
-
- if (s == NULL || count <= 0)
- {
- result = EINVAL;
- }
- else if ((result = pthread_mutex_lock (&s->lock)) == 0)
- {
- /* See sem_destroy.c
- */
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- result = EINVAL;
- return -1;
- }
-
- if (s->value <= (SEM_VALUE_MAX - count))
- {
- waiters = -s->value;
- s->value += count;
- if (waiters > 0)
- {
-#if defined(NEED_SEM)
- if (SetEvent(s->sem))
- {
- waiters--;
- s->leftToUnblock += count - 1;
- if (s->leftToUnblock > waiters)
- {
- s->leftToUnblock = waiters;
- }
- }
-#else
- if (ReleaseSemaphore (s->sem, (waiters<=count)?waiters:count, 0))
- {
- /* No action */
- }
-#endif
- else
- {
- s->value -= count;
- result = EINVAL;
- }
- }
- }
- else
- {
- result = ERANGE;
- }
- (void) pthread_mutex_unlock (&s->lock);
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- return 0;
-
-} /* sem_post_multiple */
diff --git a/pthreads/src/sem_timedwait.c b/pthreads/src/sem_timedwait.c
deleted file mode 100644
index 638431c..0000000
--- a/pthreads/src/sem_timedwait.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_timedwait.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-typedef struct {
- sem_t sem;
- int * resultPtr;
-} sem_timedwait_cleanup_args_t;
-
-
-static void PTW32_CDECL
-ptw32_sem_timedwait_cleanup (void * args)
-{
- sem_timedwait_cleanup_args_t * a = (sem_timedwait_cleanup_args_t *)args;
- sem_t s = a->sem;
-
- if (pthread_mutex_lock (&s->lock) == 0)
- {
- /*
- * We either timed out or were cancelled.
- * If someone has posted between then and now we try to take the semaphore.
- * Otherwise the semaphore count may be wrong after we
- * return. In the case of a cancellation, it is as if we
- * were cancelled just before we return (after taking the semaphore)
- * which is ok.
- */
- if (WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)
- {
- /* We got the semaphore on the second attempt */
- *(a->resultPtr) = 0;
- }
- else
- {
- /* Indicate we're no longer waiting */
- s->value++;
-#if defined(NEED_SEM)
- if (s->value > 0)
- {
- s->leftToUnblock = 0;
- }
-#else
- /*
- * Don't release the W32 sema, it doesn't need adjustment
- * because it doesn't record the number of waiters.
- */
-#endif
- }
- (void) pthread_mutex_unlock (&s->lock);
- }
-}
-
-
-int
-sem_timedwait (sem_t * sem, const struct timespec *abstime)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function waits on a semaphore possibly until
- * 'abstime' time.
- *
- * PARAMETERS
- * sem
- * pointer to an instance of sem_t
- *
- * abstime
- * pointer to an instance of struct timespec
- *
- * DESCRIPTION
- * This function waits on a semaphore. If the
- * semaphore value is greater than zero, it decreases
- * its value by one. If the semaphore value is zero, then
- * the calling thread (or process) is blocked until it can
- * successfully decrease the value or until interrupted by
- * a signal.
- *
- * If 'abstime' is a NULL pointer then this function will
- * block until it can successfully decrease the value or
- * until interrupted by a signal.
- *
- * RESULTS
- * 0 successfully decreased semaphore,
- * -1 failed, error in errno
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore,
- * ENOSYS semaphores are not supported,
- * EINTR the function was interrupted by a signal,
- * EDEADLK a deadlock condition was detected.
- * ETIMEDOUT abstime elapsed before success.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- sem_t s = *sem;
-
- pthread_testcancel();
-
- if (sem == NULL)
- {
- result = EINVAL;
- }
- else
- {
- DWORD milliseconds;
-
- if (abstime == NULL)
- {
- milliseconds = INFINITE;
- }
- else
- {
- /*
- * Calculate timeout as milliseconds from current system time.
- */
- milliseconds = ptw32_relmillisecs (abstime);
- }
-
- if ((result = pthread_mutex_lock (&s->lock)) == 0)
- {
- int v;
-
- /* See sem_destroy.c
- */
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- v = --s->value;
- (void) pthread_mutex_unlock (&s->lock);
-
- if (v < 0)
- {
-#if defined(NEED_SEM)
- int timedout;
-#endif
- sem_timedwait_cleanup_args_t cleanup_args;
-
- cleanup_args.sem = s;
- cleanup_args.resultPtr = &result;
-
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth(0)
-#endif
- /* Must wait */
- pthread_cleanup_push(ptw32_sem_timedwait_cleanup, (void *) &cleanup_args);
-#if defined(NEED_SEM)
- timedout =
-#endif
- result = pthreadCancelableTimedWait (s->sem, milliseconds);
- pthread_cleanup_pop(result);
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth()
-#endif
-
-#if defined(NEED_SEM)
-
- if (!timedout && pthread_mutex_lock (&s->lock) == 0)
- {
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- if (s->leftToUnblock > 0)
- {
- --s->leftToUnblock;
- SetEvent(s->sem);
- }
- (void) pthread_mutex_unlock (&s->lock);
- }
-
-#endif /* NEED_SEM */
-
- }
- }
-
- }
-
- if (result != 0)
- {
-
- errno = result;
- return -1;
-
- }
-
- return 0;
-
-} /* sem_timedwait */
diff --git a/pthreads/src/sem_trywait.c b/pthreads/src/sem_trywait.c
deleted file mode 100644
index 63614ba..0000000
--- a/pthreads/src/sem_trywait.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_trywait.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-int
-sem_trywait (sem_t * sem)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function tries to wait on a semaphore.
- *
- * PARAMETERS
- * sem
- * pointer to an instance of sem_t
- *
- * DESCRIPTION
- * This function tries to wait on a semaphore. If the
- * semaphore value is greater than zero, it decreases
- * its value by one. If the semaphore value is zero, then
- * this function returns immediately with the error EAGAIN
- *
- * RESULTS
- * 0 successfully decreased semaphore,
- * -1 failed, error in errno
- * ERRNO
- * EAGAIN the semaphore was already locked,
- * EINVAL 'sem' is not a valid semaphore,
- * ENOTSUP sem_trywait is not supported,
- * EINTR the function was interrupted by a signal,
- * EDEADLK a deadlock condition was detected.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- sem_t s = *sem;
-
- if (s == NULL)
- {
- result = EINVAL;
- }
- else if ((result = pthread_mutex_lock (&s->lock)) == 0)
- {
- /* See sem_destroy.c
- */
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- if (s->value > 0)
- {
- s->value--;
- }
- else
- {
- result = EAGAIN;
- }
-
- (void) pthread_mutex_unlock (&s->lock);
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- return 0;
-
-} /* sem_trywait */
diff --git a/pthreads/src/sem_unlink.c b/pthreads/src/sem_unlink.c
deleted file mode 100644
index fb80569..0000000
--- a/pthreads/src/sem_unlink.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_unlink.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-/* ignore warning "unreferenced formal parameter" */
-#if defined(_MSC_VER)
-#pragma warning( disable : 4100 )
-#endif
-
-int
-sem_unlink (const char *name)
-{
- errno = ENOSYS;
- return -1;
-} /* sem_unlink */
diff --git a/pthreads/src/sem_wait.c b/pthreads/src/sem_wait.c
deleted file mode 100644
index 50c11d8..0000000
--- a/pthreads/src/sem_wait.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: sem_wait.c
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-static void PTW32_CDECL
-ptw32_sem_wait_cleanup(void * sem)
-{
- sem_t s = (sem_t) sem;
-
- if (pthread_mutex_lock (&s->lock) == 0)
- {
- /*
- * If sema is destroyed do nothing, otherwise:-
- * If the sema is posted between us being cancelled and us locking
- * the sema again above then we need to consume that post but cancel
- * anyway. If we don't get the semaphore we indicate that we're no
- * longer waiting.
- */
- if (*((sem_t *)sem) != NULL && !(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0))
- {
- ++s->value;
-#if defined(NEED_SEM)
- if (s->value > 0)
- {
- s->leftToUnblock = 0;
- }
-#else
- /*
- * Don't release the W32 sema, it doesn't need adjustment
- * because it doesn't record the number of waiters.
- */
-#endif /* NEED_SEM */
- }
- (void) pthread_mutex_unlock (&s->lock);
- }
-}
-
-int
-sem_wait (sem_t * sem)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function waits on a semaphore.
- *
- * PARAMETERS
- * sem
- * pointer to an instance of sem_t
- *
- * DESCRIPTION
- * This function waits on a semaphore. If the
- * semaphore value is greater than zero, it decreases
- * its value by one. If the semaphore value is zero, then
- * the calling thread (or process) is blocked until it can
- * successfully decrease the value or until interrupted by
- * a signal.
- *
- * RESULTS
- * 0 successfully decreased semaphore,
- * -1 failed, error in errno
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore,
- * ENOSYS semaphores are not supported,
- * EINTR the function was interrupted by a signal,
- * EDEADLK a deadlock condition was detected.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- sem_t s = *sem;
-
- pthread_testcancel();
-
- if (s == NULL)
- {
- result = EINVAL;
- }
- else
- {
- if ((result = pthread_mutex_lock (&s->lock)) == 0)
- {
- int v;
-
- /* See sem_destroy.c
- */
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- v = --s->value;
- (void) pthread_mutex_unlock (&s->lock);
-
- if (v < 0)
- {
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth(0)
-#endif
- /* Must wait */
- pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s);
- result = pthreadCancelableWait (s->sem);
- /* Cleanup if we're canceled or on any other error */
- pthread_cleanup_pop(result);
-#if defined(_MSC_VER) && _MSC_VER < 1400
-#pragma inline_depth()
-#endif
- }
-#if defined(NEED_SEM)
-
- if (!result && pthread_mutex_lock (&s->lock) == 0)
- {
- if (*sem == NULL)
- {
- (void) pthread_mutex_unlock (&s->lock);
- errno = EINVAL;
- return -1;
- }
-
- if (s->leftToUnblock > 0)
- {
- --s->leftToUnblock;
- SetEvent(s->sem);
- }
- (void) pthread_mutex_unlock (&s->lock);
- }
-
-#endif /* NEED_SEM */
-
- }
-
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- return 0;
-
-} /* sem_wait */
diff --git a/pthreads/src/semaphore.c b/pthreads/src/semaphore.c
deleted file mode 100644
index 64fc0e3..0000000
--- a/pthreads/src/semaphore.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * -------------------------------------------------------------
- *
- * Module: semaphore.c
- *
- * Purpose:
- * Concatenated version of separate modules to allow
- * inlining optimisation, which it is assumed can only
- * be effective within a single module.
- *
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * -------------------------------------------------------------
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#if !defined(NEED_FTIME)
-# include <sys/timeb.h>
-#endif
-
-#include <limits.h>
-
-#include "pthread.h"
-#include "semaphore.h"
-#include "implement.h"
-
-
-#include "sem_init.c"
-#include "sem_destroy.c"
-#include "sem_trywait.c"
-#include "sem_wait.c"
-#include "sem_timedwait.c"
-#include "sem_post.c"
-#include "sem_post_multiple.c"
-#include "sem_getvalue.c"
-#include "sem_open.c"
-#include "sem_close.c"
-#include "sem_unlink.c"
diff --git a/pthreads/src/semaphore.h b/pthreads/src/semaphore.h
deleted file mode 100644
index c6e9407..0000000
--- a/pthreads/src/semaphore.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Module: semaphore.h
- *
- * Purpose:
- * Semaphores aren't actually part of the PThreads standard.
- * They are defined by the POSIX Standard:
- *
- * POSIX 1003.1b-1993 (POSIX.1b)
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-#if !defined( SEMAPHORE_H )
-#define SEMAPHORE_H
-
-#undef PTW32_SEMAPHORE_LEVEL
-
-#if defined(_POSIX_SOURCE)
-#define PTW32_SEMAPHORE_LEVEL 0
-/* Early POSIX */
-#endif
-
-#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
-#undef PTW32_SEMAPHORE_LEVEL
-#define PTW32_SEMAPHORE_LEVEL 1
-/* Include 1b, 1c and 1d */
-#endif
-
-#if defined(INCLUDE_NP)
-#undef PTW32_SEMAPHORE_LEVEL
-#define PTW32_SEMAPHORE_LEVEL 2
-/* Include Non-Portable extensions */
-#endif
-
-#define PTW32_SEMAPHORE_LEVEL_MAX 3
-
-#if !defined(PTW32_SEMAPHORE_LEVEL)
-#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX
-/* Include everything */
-#endif
-
-#if defined(__GNUC__) && ! defined (__declspec)
-# error Please upgrade your GNU compiler to one that supports __declspec.
-#endif
-
-/*
- * When building the library, you should define PTW32_BUILD so that
- * the variables/functions are exported correctly. When using the library,
- * do NOT define PTW32_BUILD, and then the variables/functions will
- * be imported correctly.
- */
-#if !defined(PTW32_STATIC_LIB)
-# if defined(PTW32_BUILD)
-# define PTW32_DLLPORT __declspec (dllexport)
-# else
-# define PTW32_DLLPORT __declspec (dllimport)
-# endif
-#else
-# define PTW32_DLLPORT
-#endif
-
-/*
- * This is a duplicate of what is in the autoconf config.h,
- * which is only used when building the pthread-win32 libraries.
- */
-
-#if !defined(PTW32_CONFIG_H)
-# if defined(WINCE)
-# define NEED_ERRNO
-# define NEED_SEM
-# endif
-# if defined(__MINGW64__)
-# define HAVE_STRUCT_TIMESPEC
-# define HAVE_MODE_T
-# elif defined(_UWIN) || defined(__MINGW32__)
-# define HAVE_MODE_T
-# endif
-#endif
-
-/*
- *
- */
-
-#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX
-#if defined(NEED_ERRNO)
-#include "need_errno.h"
-#else
-#include <errno.h>
-#endif
-#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */
-
-#define _POSIX_SEMAPHORES
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif /* __cplusplus */
-
-#if !defined(HAVE_MODE_T)
-typedef unsigned int mode_t;
-#endif
-
-
-typedef struct sem_t_ * sem_t;
-
-PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
- int pshared,
- unsigned int value);
-
-PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
-
-PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
-
-PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
-
-PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
- const struct timespec * abstime);
-
-PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
-
-PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
- int count);
-
-PTW32_DLLPORT int __cdecl sem_open (const char * name,
- int oflag,
- mode_t mode,
- unsigned int value);
-
-PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
-
-PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
-
-PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
- int * sval);
-
-#if defined(__cplusplus)
-} /* End of extern "C" */
-#endif /* __cplusplus */
-
-#undef PTW32_SEMAPHORE_LEVEL
-#undef PTW32_SEMAPHORE_LEVEL_MAX
-
-#endif /* !SEMAPHORE_H */
diff --git a/pthreads/src/signal.c b/pthreads/src/signal.c
deleted file mode 100644
index eef4669..0000000
--- a/pthreads/src/signal.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * signal.c
- *
- * Description:
- * Thread-aware signal functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/*
- * Possible future strategy for implementing pthread_kill()
- * ========================================================
- *
- * Win32 does not implement signals.
- * Signals are simply software interrupts.
- * pthread_kill() asks the system to deliver a specified
- * signal (interrupt) to a specified thread in the same
- * process.
- * Signals are always asynchronous (no deferred signals).
- * Pthread-win32 has an async cancelation mechanism.
- * A similar system can be written to deliver signals
- * within the same process (on ix86 processors at least).
- *
- * Each thread maintains information about which
- * signals it will respond to. Handler routines
- * are set on a per-process basis - not per-thread.
- * When signalled, a thread will check it's sigmask
- * and, if the signal is not being ignored, call the
- * handler routine associated with the signal. The
- * thread must then (except for some signals) return to
- * the point where it was interrupted.
- *
- * Ideally the system itself would check the target thread's
- * mask before possibly needlessly bothering the thread
- * itself. This could be done by pthread_kill(), that is,
- * in the signaling thread since it has access to
- * all pthread_t structures. It could also retrieve
- * the handler routine address to minimise the target
- * threads response overhead. This may also simplify
- * serialisation of the access to the per-thread signal
- * structures.
- *
- * pthread_kill() eventually calls a routine similar to
- * ptw32_cancel_thread() which manipulates the target
- * threads processor context to cause the thread to
- * run the handler launcher routine. pthread_kill() must
- * save the target threads current context so that the
- * handler launcher routine can restore the context after
- * the signal handler has returned. Some handlers will not
- * return, eg. the default SIGKILL handler may simply
- * call pthread_exit().
- *
- * The current context is saved in the target threads
- * pthread_t structure.
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-#if defined(HAVE_SIGSET_T)
-
-static void
-ptw32_signal_thread ()
-{
-}
-
-static void
-ptw32_signal_callhandler ()
-{
-}
-
-int
-pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
-{
- pthread_t thread = pthread_self ();
-
- if (thread.p == NULL)
- {
- return ENOENT;
- }
-
- /* Validate the `how' argument. */
- if (set != NULL)
- {
- switch (how)
- {
- case SIG_BLOCK:
- break;
- case SIG_UNBLOCK:
- break;
- case SIG_SETMASK:
- break;
- default:
- /* Invalid `how' argument. */
- return EINVAL;
- }
- }
-
- /* Copy the old mask before modifying it. */
- if (oset != NULL)
- {
- memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t));
- }
-
- if (set != NULL)
- {
- unsigned int i;
-
- /* FIXME: this code assumes that sigmask is an even multiple of
- the size of a long integer. */
-
- unsigned long *src = (unsigned long const *) set;
- unsigned long *dest = (unsigned long *) &(thread.p->sigmask);
-
- switch (how)
- {
- case SIG_BLOCK:
- for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
- {
- /* OR the bit field longword-wise. */
- *dest++ |= *src++;
- }
- break;
- case SIG_UNBLOCK:
- for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
- {
- /* XOR the bitfield longword-wise. */
- *dest++ ^= *src++;
- }
- case SIG_SETMASK:
- /* Replace the whole sigmask. */
- memcpy (&(thread.p->sigmask), set, sizeof (sigset_t));
- break;
- }
- }
-
- return 0;
-}
-
-int
-sigwait (const sigset_t * set, int *sig)
-{
- /* This routine is a cancellation point */
- pthread_test_cancel();
-}
-
-int
-sigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
-{
-}
-
-#endif /* HAVE_SIGSET_T */
diff --git a/pthreads/src/spin.c b/pthreads/src/spin.c
deleted file mode 100644
index 41b5aa5..0000000
--- a/pthreads/src/spin.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * spin.c
- *
- * Description:
- * This translation unit implements spin lock primitives.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-#include "ptw32_spinlock_check_need_init.c"
-#include "pthread_spin_init.c"
-#include "pthread_spin_destroy.c"
-#include "pthread_spin_lock.c"
-#include "pthread_spin_unlock.c"
-#include "pthread_spin_trylock.c"
diff --git a/pthreads/src/sync.c b/pthreads/src/sync.c
deleted file mode 100644
index 5e56fa9..0000000
--- a/pthreads/src/sync.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * sync.c
- *
- * Description:
- * This translation unit implements functions related to thread
- * synchronisation.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-#include "pthread_detach.c"
-#include "pthread_join.c"
diff --git a/pthreads/src/tsd.c b/pthreads/src/tsd.c
deleted file mode 100644
index ed44fe6..0000000
--- a/pthreads/src/tsd.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * tsd.c
- *
- * Description:
- * POSIX thread functions which implement thread-specific data (TSD).
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-#include "pthread_key_create.c"
-#include "pthread_key_delete.c"
-#include "pthread_setspecific.c"
-#include "pthread_getspecific.c"
diff --git a/pthreads/src/w32_CancelableWait.c b/pthreads/src/w32_CancelableWait.c
deleted file mode 100644
index 070633e..0000000
--- a/pthreads/src/w32_CancelableWait.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * w32_CancelableWait.c
- *
- * Description:
- * This translation unit implements miscellaneous thread functions.
- *
- * --------------------------------------------------------------------------
- *
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- * Contact Email: rpj@callisto.canberra.edu.au
- *
- * The current list of contributors is contained
- * in the file CONTRIBUTORS included with the source
- * code distribution. The list can also be seen at the
- * following World Wide Web location:
- * http://sources.redhat.com/pthreads-win32/contributors.html
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library in the file COPYING.LIB;
- * if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "pthread.h"
-#include "implement.h"
-
-
-static INLINE int
-ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout)
- /*
- * -------------------------------------------------------------------
- * This provides an extra hook into the pthread_cancel
- * mechanism that will allow you to wait on a Windows handle and make it a
- * cancellation point. This function blocks until the given WIN32 handle is
- * signaled or pthread_cancel has been called. It is implemented using
- * WaitForMultipleObjects on 'waitHandle' and a manually reset WIN32
- * event used to implement pthread_cancel.
- *
- * Given this hook it would be possible to implement more of the cancellation
- * points.
- * -------------------------------------------------------------------
- */
-{
- int result;
- pthread_t self;
- ptw32_thread_t * sp;
- HANDLE handles[2];
- DWORD nHandles = 1;
- DWORD status;
-
- handles[0] = waitHandle;
-
- self = pthread_self();
- sp = (ptw32_thread_t *) self.p;
-
- if (sp != NULL)
- {
- /*
- * Get cancelEvent handle
- */
- if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
- {
-
- if ((handles[1] = sp->cancelEvent) != NULL)
- {
- nHandles++;
- }
- }
- }
- else
- {
- handles[1] = NULL;
- }
-
- status = WaitForMultipleObjects (nHandles, handles, PTW32_FALSE, timeout);
-
- switch (status - WAIT_OBJECT_0)
- {
- case 0:
- /*
- * Got the handle.
- * In the event that both handles are signalled, the smallest index
- * value (us) is returned. As it has been arranged, this ensures that
- * we don't drop a signal that we should act on (i.e. semaphore,
- * mutex, or condition variable etc).
- */
- result = 0;
- break;
-
- case 1:
- /*
- * Got cancel request.
- * In the event that both handles are signaled, the cancel will
- * be ignored (see case 0 comment).
- */
- ResetEvent (handles[1]);
-
- if (sp != NULL)
- {
- ptw32_mcs_local_node_t stateLock;
- /*
- * Should handle POSIX and implicit POSIX threads..
- * Make sure we haven't been async-canceled in the meantime.
- */
- ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
- if (sp->state < PThreadStateCanceling)
- {
- sp->state = PThreadStateCanceling;
- sp->cancelState = PTHREAD_CANCEL_DISABLE;
- ptw32_mcs_lock_release (&stateLock);
- ptw32_throw (PTW32_EPS_CANCEL);
-
- /* Never reached */
- }
- ptw32_mcs_lock_release (&stateLock);
- }
-
- /* Should never get to here. */
- result = EINVAL;
- break;
-
- default:
- if (status == WAIT_TIMEOUT)
- {
- result = ETIMEDOUT;
- }
- else
- {
- result = EINVAL;
- }
- break;
- }
-
- return (result);
-
-} /* CancelableWait */
-
-int
-pthreadCancelableWait (HANDLE waitHandle)
-{
- return (ptw32_cancelable_wait (waitHandle, INFINITE));
-}
-
-int
-pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout)
-{
- return (ptw32_cancelable_wait (waitHandle, timeout));
-}
diff --git a/vtparse/src/Makefile b/vtparse/src/Makefile
new file mode 100644
index 0000000..044a487
--- /dev/null
+++ b/vtparse/src/Makefile
@@ -0,0 +1,19 @@
+
+RUBY_GENERATION_FILES = vtparse_gen_c_tables.rb vtparse_tables.rb
+
+all: vtparse_table.c vtparse_table.h test
+
+clean:
+ rm -f vtparse_table.c vtparse_table.h test
+
+vtparse_table.c: $(RUBY_GENERATION_FILES)
+ ruby vtparse_gen_c_tables.rb
+
+vtparse_table.h: $(RUBY_GENERATION_FILES)
+ ruby vtparse_gen_c_tables.rb
+
+test: vtparse.c vtparse.h vtparse_table.c vtparse_table.h vtparse_test.c
+ gcc -o test vtparse_test.c vtparse.c vtparse_table.c
+
+.PHONY: all clean
+
diff --git a/vtparse/src/README b/vtparse/src/README
new file mode 100644
index 0000000..9b24113
--- /dev/null
+++ b/vtparse/src/README
@@ -0,0 +1,67 @@
+
+VTParse - an implementation of Paul Williams' DEC compatible state machine parser
+ <http://www.vt100.net/emu/dec_ansi_parser>
+
+Author: Joshua Haberman <joshua@reverberate.org>
+
+This code is in the public domain.
+
+BUILDING
+========
+
+Ruby is required at build time to generate the tables in C. To build the library
+and test program, just type make:
+
+$ make
+ruby vtparse_gen_c_tables.rb
+Wrote vtparse_table.h
+Wrote vtparse_table.c
+gcc -o test vtparse_test.c vtparse.c vtparse_table.c
+
+TEST PROGRAM
+============
+
+The test program shows how to use vtparse. To see what kind of data is returned
+by the library, try:
+
+--------------------------------
+
+$ vim > terminaloutput
+<type ':q<ENTER>' to exit vim, even though you won't see it>
+$ ./test < terminaloutput | head -14
+Received action ESC_DISPATCH, char=0x37
+Intermediate chars: ''
+0 Parameters:
+
+Received action CSI_DISPATCH, char=0x68
+Intermediate chars: '???'
+1 Parameters:
+ 47
+
+Received action CSI_DISPATCH, char=0x68
+Intermediate chars: '???'
+1 Parameters:
+ 1
+
+---------------------------------
+
+VERIFYING
+=========
+
+You can also verify the validity of the state tables by running:
+
+$ ruby vtparse_check_tables.rb
+Tables had all necessary transitions defined.
+
+This checks to make sure that state transitions are defined for all states, for all
+characters 0-0xA0.
+
+
+TODO
+====
+
+One possible enhancement is to allow the client to pass a return value from the
+callback to say "stop parsing." The vtparse() function could return the number
+of bytes consumed from the input buffer. This would be quite simple to do if
+someone needed this functionality, but I don't, so I didn't bother.
+
diff --git a/vtparse/src/vtparse.c b/vtparse/src/vtparse.c
new file mode 100644
index 0000000..b24a4a4
--- /dev/null
+++ b/vtparse/src/vtparse.c
@@ -0,0 +1,152 @@
+/*
+ * VTParse - an implementation of Paul Williams' DEC compatible state machine parser
+ *
+ * Author: Joshua Haberman <joshua@reverberate.org>
+ *
+ * This code is in the public domain.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "vtparse.h"
+
+void vtparse_init(vtparse_t *parser, vtparse_callback_t cb)
+{
+ parser->state = VTPARSE_STATE_GROUND;
+ parser->intermediate_chars[0] = '\0';
+ parser->num_params = 0;
+ parser->ignore_flagged = 0;
+ parser->cb = cb;
+}
+
+static void do_action(vtparse_t *parser, vtparse_action_t action, char ch)
+{
+ /* Some actions we handle internally (like parsing parameters), others
+ * we hand to our client for processing */
+
+ switch(action) {
+ case VTPARSE_ACTION_PRINT:
+ case VTPARSE_ACTION_EXECUTE:
+ case VTPARSE_ACTION_HOOK:
+ case VTPARSE_ACTION_PUT:
+ case VTPARSE_ACTION_OSC_START:
+ case VTPARSE_ACTION_OSC_PUT:
+ case VTPARSE_ACTION_OSC_END:
+ case VTPARSE_ACTION_UNHOOK:
+ case VTPARSE_ACTION_CSI_DISPATCH:
+ case VTPARSE_ACTION_ESC_DISPATCH:
+ parser->cb(parser, action, ch);
+ break;
+
+ case VTPARSE_ACTION_IGNORE:
+ /* do nothing */
+ break;
+
+ case VTPARSE_ACTION_COLLECT:
+ {
+ /* Append the character to the intermediate params */
+ int num_intermediate_chars = strlen((char*)parser->intermediate_chars);
+
+ if(num_intermediate_chars + 1 > MAX_INTERMEDIATE_CHARS)
+ parser->ignore_flagged = 1;
+ else
+ parser->intermediate_chars[num_intermediate_chars++] = ch;
+
+ break;
+ }
+
+ case VTPARSE_ACTION_PARAM:
+ {
+ /* process the param character */
+ if(ch == ';')
+ {
+ parser->num_params += 1;
+ parser->params[parser->num_params-1] = 0;
+ }
+ else
+ {
+ /* the character is a digit */
+ int current_param;
+
+ if(parser->num_params == 0)
+ {
+ parser->num_params = 1;
+ parser->params[0] = 0;
+ }
+
+ current_param = parser->num_params - 1;
+ parser->params[current_param] *= 10;
+ parser->params[current_param] += (ch - '0');
+ }
+
+ break;
+ }
+
+ case VTPARSE_ACTION_CLEAR:
+ parser->intermediate_chars[0] = '\0';
+ parser->num_params = 0;
+ parser->ignore_flagged = 0;
+ break;
+
+ default:
+ fprintf(stderr, "Internal error, unknown action %d", action);
+ }
+}
+
+static void do_state_change(vtparse_t *parser, state_change_t change, char ch)
+{
+ /* A state change is an action and/or a new state to transition to. */
+
+ vtparse_state_t new_state = STATE(change);
+ vtparse_action_t action = ACTION(change);
+
+
+ if(new_state)
+ {
+ /* Perform up to three actions:
+ * 1. the exit action of the old state
+ * 2. the action associated with the transition
+ * 3. the entry actionk of the new action
+ */
+
+ vtparse_action_t exit_action = EXIT_ACTIONS[parser->state];
+ vtparse_action_t entry_action = ENTRY_ACTIONS[new_state];
+
+ if(exit_action)
+ do_action(parser, exit_action, 0);
+
+ if(action)
+ do_action(parser, action, ch);
+
+ if(entry_action)
+ do_action(parser, entry_action, 0);
+
+ parser->state = new_state;
+ }
+ else
+ {
+ do_action(parser, action, ch);
+ }
+}
+
+void vtparse(vtparse_t *parser, unsigned char *data, int len)
+{
+ int i;
+ for(i = 0; i < len; i++)
+ {
+ unsigned char ch = data[i];
+
+ /* If a transition is defined from the "anywhere" state, always
+ * use that. Otherwise use the transition from the current state. */
+
+ state_change_t change = STATE_TABLE[VTPARSE_STATE_ANYWHERE][ch];
+
+ if(!change)
+ change = STATE_TABLE[parser->state][ch];
+
+ do_state_change(parser, change, data[i]);
+ }
+}
+
diff --git a/vtparse/src/vtparse.h b/vtparse/src/vtparse.h
new file mode 100644
index 0000000..1d176ad
--- /dev/null
+++ b/vtparse/src/vtparse.h
@@ -0,0 +1,31 @@
+/*
+ * VTParse - an implementation of Paul Williams' DEC compatible state machine parser
+ *
+ * Author: Joshua Haberman <joshua@reverberate.org>
+ *
+ * This code is in the public domain.
+ */
+
+#include "vtparse_table.h"
+
+#define MAX_INTERMEDIATE_CHARS 2
+#define ACTION(state_change) (state_change & 0x0F)
+#define STATE(state_change) (state_change >> 4)
+
+struct vtparse;
+
+typedef void (*vtparse_callback_t)(struct vtparse*, vtparse_action_t, unsigned char);
+
+typedef struct vtparse {
+ vtparse_state_t state;
+ vtparse_callback_t cb;
+ unsigned char intermediate_chars[MAX_INTERMEDIATE_CHARS+1];
+ char ignore_flagged;
+ int params[16];
+ int num_params;
+ void* user_data;
+} vtparse_t;
+
+void vtparse_init(vtparse_t *parser, vtparse_callback_t cb);
+void vtparse(vtparse_t *parser, unsigned char *data, int len);
+
diff --git a/vtparse/src/vtparse_check_tables.rb b/vtparse/src/vtparse_check_tables.rb
new file mode 100644
index 0000000..2bfa122
--- /dev/null
+++ b/vtparse/src/vtparse_check_tables.rb
@@ -0,0 +1,24 @@
+
+require 'vtparse_tables'
+
+#
+# check that for every state, there is a transition defined
+# for every character between 0 and A0.
+#
+
+table = {}
+
+anywhere_array = expand_ranges($states[:ANYWHERE])
+
+$state_tables.each { |state, table|
+ next if state == :ANYWHERE
+
+ table.each_with_index { |val, i|
+ if not (val or $state_tables[:ANYWHERE][i])
+ raise "No transition defined from state #{state}, char 0x#{i.to_s(16)}!"
+ end
+ }
+}
+
+puts "Tables had all necessary transitions defined."
+
diff --git a/vtparse/src/vtparse_gen_c_tables.rb b/vtparse/src/vtparse_gen_c_tables.rb
new file mode 100644
index 0000000..ed5655e
--- /dev/null
+++ b/vtparse/src/vtparse_gen_c_tables.rb
@@ -0,0 +1,95 @@
+
+require 'vtparse_tables'
+
+class String
+ def pad(len)
+ self << (" " * (len - self.length))
+ end
+end
+
+File.open("vtparse_table.h", "w") { |f|
+ f.puts "typedef enum {"
+ $states_in_order.each_with_index { |state, i|
+ f.puts " VTPARSE_STATE_#{state.to_s.upcase} = #{i},"
+ }
+ f.puts "} vtparse_state_t;"
+ f.puts
+ f.puts "typedef enum {"
+ $actions_in_order.each_with_index { |action, i|
+ f.puts " VTPARSE_ACTION_#{action.to_s.upcase} = #{i+1},"
+ }
+ f.puts "} vtparse_action_t;"
+ f.puts
+ f.puts "typedef unsigned char state_change_t;"
+ f.puts "extern state_change_t STATE_TABLE[#{$states_in_order.length}][256];"
+ f.puts "extern vtparse_action_t ENTRY_ACTIONS[#{$states_in_order.length}];"
+ f.puts "extern vtparse_action_t EXIT_ACTIONS[#{$states_in_order.length}];"
+ f.puts "extern char *ACTION_NAMES[#{$actions_in_order.length+1}];"
+ f.puts "extern char *STATE_NAMES[#{$states_in_order.length}];"
+ f.puts
+}
+
+puts "Wrote vtparse_table.h"
+
+File.open("vtparse_table.c", "w") { |f|
+ f.puts
+ f.puts '#include "vtparse_table.h"'
+ f.puts
+ f.puts "char *ACTION_NAMES[] = {"
+ f.puts " \"<no action>\","
+ $actions_in_order.each { |action|
+ f.puts " \"#{action.to_s.upcase}\","
+ }
+ f.puts "};"
+ f.puts
+ f.puts "char *STATE_NAMES[] = {"
+ $states_in_order.each { |state|
+ f.puts " \"#{state.to_s}\","
+ }
+ f.puts "};"
+ f.puts
+ f.puts "state_change_t STATE_TABLE[#{$states_in_order.length}][256] = {"
+ $states_in_order.each { |state|
+ f.puts " { /* VTPARSE_STATE_#{state.to_s.upcase} */"
+ $state_tables[state].each_with_index { |state_change, i|
+ if not state_change
+ f.puts " 0,"
+ else
+ (action,) = state_change.find_all { |s| s.kind_of?(Symbol) }
+ (state,) = state_change.find_all { |s| s.kind_of?(StateTransition) }
+ action_str = action ? "VTPARSE_ACTION_#{action.to_s.upcase}" : "0"
+ state_str = state ? "VTPARSE_STATE_#{state.to_state.to_s}" : "0"
+ f.puts "/*#{i.to_s.pad(3)}*/ #{action_str.pad(33)} | (#{state_str.pad(33)} << 4),"
+ end
+ }
+ f.puts " },"
+ }
+
+ f.puts "};"
+ f.puts
+ f.puts "vtparse_action_t ENTRY_ACTIONS[] = {"
+ $states_in_order.each { |state|
+ actions = $states[state]
+ if actions[:on_entry]
+ f.puts " VTPARSE_ACTION_#{actions[:on_entry].to_s.upcase}, /* #{state} */"
+ else
+ f.puts " 0 /* none for #{state} */,"
+ end
+ }
+ f.puts "};"
+ f.puts
+ f.puts "vtparse_action_t EXIT_ACTIONS[] = {"
+ $states_in_order.each { |state|
+ actions = $states[state]
+ if actions[:on_exit]
+ f.puts " VTPARSE_ACTION_#{actions[:on_exit].to_s.upcase}, /* #{state} */"
+ else
+ f.puts " 0 /* none for #{state} */,"
+ end
+ }
+ f.puts "};"
+ f.puts
+}
+
+puts "Wrote vtparse_table.c"
+
diff --git a/vtparse/src/vtparse_table.c b/vtparse/src/vtparse_table.c
new file mode 100644
index 0000000..f81e770
--- /dev/null
+++ b/vtparse/src/vtparse_table.c
@@ -0,0 +1,2657 @@
+
+#include "vtparse_table.h"
+
+char *ACTION_NAMES[] = {
+ "<no action>",
+ "CLEAR",
+ "COLLECT",
+ "CSI_DISPATCH",
+ "ESC_DISPATCH",
+ "EXECUTE",
+ "HOOK",
+ "IGNORE",
+ "OSC_END",
+ "OSC_PUT",
+ "OSC_START",
+ "PARAM",
+ "PRINT",
+ "PUT",
+ "UNHOOK",
+};
+
+char *STATE_NAMES[] = {
+ "ANYWHERE",
+ "CSI_ENTRY",
+ "CSI_IGNORE",
+ "CSI_INTERMEDIATE",
+ "CSI_PARAM",
+ "DCS_ENTRY",
+ "DCS_IGNORE",
+ "DCS_INTERMEDIATE",
+ "DCS_PARAM",
+ "DCS_PASSTHROUGH",
+ "ESCAPE",
+ "ESCAPE_INTERMEDIATE",
+ "GROUND",
+ "OSC_STRING",
+ "SOS_PM_APC_STRING",
+ "UTF8",
+};
+
+state_change_t STATE_TABLE[16][256] = {
+ { /* VTPARSE_STATE_ANYWHERE */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*24 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+ 0,
+/*26 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*27 */ 0 | (VTPARSE_STATE_ESCAPE << 4),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*128*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*129*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*130*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*131*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*132*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*133*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*134*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*135*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*136*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*137*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*138*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*139*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*140*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*141*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*142*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*143*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*144*/ 0 | (VTPARSE_STATE_DCS_ENTRY << 4),
+/*145*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*146*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*147*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*148*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*149*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*150*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*151*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*152*/ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4),
+/*153*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*154*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*155*/ 0 | (VTPARSE_STATE_CSI_ENTRY << 4),
+/*156*/ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*157*/ 0 | (VTPARSE_STATE_OSC_STRING << 4),
+/*158*/ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4),
+/*159*/ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*192*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*193*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*194*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*195*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*196*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*197*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*198*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*199*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*200*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*201*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*202*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*203*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*204*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*205*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*206*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*207*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*208*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*209*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*210*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*211*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*212*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*213*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*214*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*215*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*216*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*217*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*218*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*219*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*220*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*221*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*222*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*223*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*224*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*225*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*226*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*227*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*228*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*229*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*230*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*231*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*232*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*233*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*234*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*235*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*236*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*237*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*238*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*239*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*240*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*241*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*242*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*243*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*244*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*245*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*246*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*247*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*248*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*249*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*250*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*251*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*252*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*253*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+ },
+ { /* VTPARSE_STATE_CSI_ENTRY */
+/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*48 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*49 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*50 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*51 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*52 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*53 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*54 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*55 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*56 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*57 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*58 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*59 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_CSI_PARAM << 4),
+/*60 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4),
+/*61 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4),
+/*62 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4),
+/*63 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_PARAM << 4),
+/*64 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*65 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*66 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*67 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*68 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*69 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*70 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*71 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*72 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*73 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*74 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*75 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*76 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*77 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*78 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*79 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*80 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*81 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*82 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*83 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*84 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*85 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*86 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*87 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*88 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*89 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*90 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*91 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*92 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*93 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*94 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*95 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*96 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*97 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*98 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*99 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*100*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*101*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*102*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*103*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*104*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*105*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*106*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*107*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*108*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*109*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*110*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*111*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*112*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*113*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*114*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*115*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*116*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*117*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*118*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*119*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*120*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*121*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*122*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*123*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*124*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*125*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*126*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_CSI_IGNORE */
+/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*32 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*33 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*34 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*35 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*36 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*37 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*38 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*39 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*40 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*41 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*42 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*43 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*44 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*45 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*46 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*47 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*48 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*49 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*50 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*51 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*52 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*53 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*54 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*55 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*56 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*57 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*58 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*59 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*60 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*61 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*62 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*63 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*64 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*65 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*66 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*67 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*68 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*69 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*70 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*71 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*72 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*73 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*74 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*75 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*76 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*77 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*78 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*79 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*80 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*81 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*82 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*83 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*84 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*85 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*86 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*87 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*88 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*89 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*90 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*91 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*92 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*93 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*94 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*95 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*96 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*97 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*98 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*99 */ 0 | (VTPARSE_STATE_GROUND << 4),
+/*100*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*101*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*102*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*103*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*104*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*105*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*106*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*107*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*108*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*109*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*110*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*111*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*112*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*113*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*114*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*115*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*116*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*117*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*118*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*119*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*120*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*121*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*122*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*123*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*124*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*125*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*126*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_CSI_INTERMEDIATE */
+/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*48 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*49 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*50 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*51 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*52 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*53 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*54 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*55 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*56 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*57 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*58 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*59 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*60 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*61 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*62 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*63 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*64 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*65 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*66 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*67 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*68 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*69 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*70 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*71 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*72 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*73 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*74 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*75 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*76 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*77 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*78 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*79 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*80 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*81 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*82 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*83 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*84 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*85 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*86 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*87 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*88 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*89 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*90 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*91 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*92 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*93 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*94 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*95 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*96 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*97 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*98 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*99 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*100*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*101*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*102*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*103*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*104*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*105*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*106*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*107*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*108*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*109*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*110*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*111*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*112*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*113*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*114*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*115*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*116*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*117*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*118*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*119*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*120*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*121*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*122*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*123*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*124*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*125*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*126*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_CSI_PARAM */
+/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_CSI_INTERMEDIATE << 4),
+/*48 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*49 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*50 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*51 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*52 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*53 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*54 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*55 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*56 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*57 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*58 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*59 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*60 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*61 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*62 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*63 */ 0 | (VTPARSE_STATE_CSI_IGNORE << 4),
+/*64 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*65 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*66 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*67 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*68 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*69 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*70 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*71 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*72 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*73 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*74 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*75 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*76 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*77 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*78 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*79 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*80 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*81 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*82 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*83 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*84 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*85 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*86 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*87 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*88 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*89 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*90 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*91 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*92 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*93 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*94 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*95 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*96 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*97 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*98 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*99 */ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*100*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*101*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*102*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*103*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*104*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*105*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*106*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*107*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*108*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*109*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*110*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*111*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*112*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*113*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*114*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*115*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*116*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*117*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*118*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*119*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*120*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*121*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*122*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*123*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*124*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*125*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*126*/ VTPARSE_ACTION_CSI_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_DCS_ENTRY */
+/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*48 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*49 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*50 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*51 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*52 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*53 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*54 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*55 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*56 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*57 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*58 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*59 */ VTPARSE_ACTION_PARAM | (VTPARSE_STATE_DCS_PARAM << 4),
+/*60 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4),
+/*61 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4),
+/*62 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4),
+/*63 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_PARAM << 4),
+/*64 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*65 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*66 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*67 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*68 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*69 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*70 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*71 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*72 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*73 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*74 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*75 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*76 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*77 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*78 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*79 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*80 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*81 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*82 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*83 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*84 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*85 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*86 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*87 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*88 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*89 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*90 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*91 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*92 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*93 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*94 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*95 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*96 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*97 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*98 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*99 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*100*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*101*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*102*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*103*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*104*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*105*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*106*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*107*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*108*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*109*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*110*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*111*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*112*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*113*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*114*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*115*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*116*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*117*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*118*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*119*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*120*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*121*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*122*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*123*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*124*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*125*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*126*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_DCS_IGNORE */
+/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*32 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*33 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*34 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*35 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*36 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*37 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*38 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*39 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*40 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*41 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*42 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*43 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*44 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*45 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*46 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*47 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*48 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*49 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*50 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*51 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*52 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*53 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*54 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*55 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*56 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*57 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*58 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*59 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*60 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*61 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*62 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*63 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*64 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*65 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*66 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*67 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*68 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*69 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*70 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*71 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*72 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*73 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*74 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*75 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*76 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*77 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*78 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*79 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*80 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*81 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*82 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*83 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*84 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*85 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*86 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*87 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*88 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*89 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*90 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*91 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*92 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*93 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*94 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*95 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*96 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*97 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*98 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*99 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*100*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*101*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*102*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*103*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*104*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*105*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*106*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*107*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*108*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*109*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*110*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*111*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*112*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*113*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*114*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*115*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*116*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*117*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*118*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*119*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*120*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*121*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*122*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*123*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*124*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*125*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*126*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*156*/ 0 | (VTPARSE_STATE_GROUND << 4),
+ },
+ { /* VTPARSE_STATE_DCS_INTERMEDIATE */
+/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*48 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*49 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*50 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*51 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*52 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*53 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*54 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*55 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*56 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*57 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*58 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*59 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*60 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*61 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*62 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*63 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*64 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*65 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*66 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*67 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*68 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*69 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*70 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*71 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*72 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*73 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*74 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*75 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*76 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*77 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*78 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*79 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*80 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*81 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*82 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*83 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*84 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*85 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*86 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*87 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*88 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*89 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*90 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*91 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*92 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*93 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*94 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*95 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*96 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*97 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*98 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*99 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*100*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*101*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*102*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*103*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*104*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*105*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*106*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*107*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*108*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*109*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*110*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*111*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*112*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*113*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*114*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*115*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*116*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*117*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*118*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*119*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*120*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*121*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*122*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*123*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*124*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*125*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*126*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_DCS_PARAM */
+/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_DCS_INTERMEDIATE << 4),
+/*48 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*49 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*50 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*51 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*52 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*53 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*54 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*55 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*56 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*57 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*58 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*59 */ VTPARSE_ACTION_PARAM | (0 << 4),
+/*60 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*61 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*62 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*63 */ 0 | (VTPARSE_STATE_DCS_IGNORE << 4),
+/*64 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*65 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*66 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*67 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*68 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*69 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*70 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*71 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*72 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*73 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*74 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*75 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*76 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*77 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*78 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*79 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*80 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*81 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*82 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*83 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*84 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*85 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*86 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*87 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*88 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*89 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*90 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*91 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*92 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*93 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*94 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*95 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*96 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*97 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*98 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*99 */ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*100*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*101*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*102*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*103*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*104*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*105*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*106*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*107*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*108*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*109*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*110*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*111*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*112*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*113*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*114*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*115*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*116*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*117*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*118*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*119*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*120*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*121*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*122*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*123*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*124*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*125*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*126*/ 0 | (VTPARSE_STATE_DCS_PASSTHROUGH << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_DCS_PASSTHROUGH */
+/*0 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*1 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*2 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*3 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*4 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*5 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*6 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*7 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*8 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*9 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*10 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*11 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*12 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*13 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*14 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*15 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*16 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*17 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*18 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*19 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*20 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*21 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*22 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*23 */ VTPARSE_ACTION_PUT | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_PUT | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*29 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*30 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*31 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*32 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*33 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*34 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*35 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*36 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*37 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*38 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*39 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*40 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*41 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*42 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*43 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*44 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*45 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*46 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*47 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*48 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*49 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*50 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*51 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*52 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*53 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*54 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*55 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*56 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*57 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*58 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*59 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*60 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*61 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*62 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*63 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*64 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*65 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*66 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*67 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*68 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*69 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*70 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*71 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*72 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*73 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*74 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*75 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*76 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*77 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*78 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*79 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*80 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*81 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*82 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*83 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*84 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*85 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*86 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*87 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*88 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*89 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*90 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*91 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*92 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*93 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*94 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*95 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*96 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*97 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*98 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*99 */ VTPARSE_ACTION_PUT | (0 << 4),
+/*100*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*101*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*102*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*103*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*104*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*105*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*106*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*107*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*108*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*109*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*110*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*111*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*112*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*113*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*114*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*115*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*116*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*117*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*118*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*119*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*120*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*121*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*122*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*123*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*124*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*125*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*126*/ VTPARSE_ACTION_PUT | (0 << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*156*/ 0 | (VTPARSE_STATE_GROUND << 4),
+ },
+ { /* VTPARSE_STATE_ESCAPE */
+/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4),
+/*48 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*49 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*50 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*51 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*52 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*53 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*54 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*55 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*56 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*57 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*58 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*59 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*60 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*61 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*62 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*63 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*64 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*65 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*66 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*67 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*68 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*69 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*70 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*71 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*72 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*73 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*74 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*75 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*76 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*77 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*78 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*79 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*80 */ 0 | (VTPARSE_STATE_DCS_ENTRY << 4),
+/*81 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*82 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*83 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*84 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*85 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*86 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*87 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*88 */ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4),
+/*89 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*90 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*91 */ 0 | (VTPARSE_STATE_CSI_ENTRY << 4),
+/*92 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*93 */ 0 | (VTPARSE_STATE_OSC_STRING << 4),
+/*94 */ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4),
+/*95 */ 0 | (VTPARSE_STATE_SOS_PM_APC_STRING << 4),
+/*96 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*97 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*98 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*99 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*100*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*101*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*102*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*103*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*104*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*105*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*106*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*107*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*108*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*109*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*110*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*111*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*112*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*113*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*114*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*115*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*116*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*117*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*118*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*119*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*120*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*121*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*122*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*123*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*124*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*125*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*126*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_ESCAPE_INTERMEDIATE */
+/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*32 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*33 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*34 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*35 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*36 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*37 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*38 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*39 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*40 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*41 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*42 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*43 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*44 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*45 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*46 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*47 */ VTPARSE_ACTION_COLLECT | (0 << 4),
+/*48 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*49 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*50 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*51 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*52 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*53 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*54 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*55 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*56 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*57 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*58 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*59 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*60 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*61 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*62 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*63 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*64 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*65 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*66 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*67 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*68 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*69 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*70 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*71 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*72 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*73 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*74 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*75 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*76 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*77 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*78 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*79 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*80 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*81 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*82 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*83 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*84 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*85 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*86 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*87 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*88 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*89 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*90 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*91 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*92 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*93 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*94 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*95 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*96 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*97 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*98 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*99 */ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*100*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*101*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*102*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*103*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*104*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*105*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*106*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*107*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*108*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*109*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*110*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*111*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*112*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*113*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*114*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*115*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*116*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*117*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*118*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*119*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*120*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*121*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*122*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*123*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*124*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*125*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*126*/ VTPARSE_ACTION_ESC_DISPATCH | (VTPARSE_STATE_GROUND << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ },
+ { /* VTPARSE_STATE_GROUND */
+/*0 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*32 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*33 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*34 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*35 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*36 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*37 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*38 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*39 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*40 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*41 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*42 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*43 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*44 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*45 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*46 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*47 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*48 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*49 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*50 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*51 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*52 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*53 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*54 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*55 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*56 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*57 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*58 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*59 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*60 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*61 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*62 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*63 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*64 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*65 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*66 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*67 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*68 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*69 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*70 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*71 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*72 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*73 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*74 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*75 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*76 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*77 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*78 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*79 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*80 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*81 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*82 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*83 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*84 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*85 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*86 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*87 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*88 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*89 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*90 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*91 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*92 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*93 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*94 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*95 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*96 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*97 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*98 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*99 */ VTPARSE_ACTION_PRINT | (0 << 4),
+/*100*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*101*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*102*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*103*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*104*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*105*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*106*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*107*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*108*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*109*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*110*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*111*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*112*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*113*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*114*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*115*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*116*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*117*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*118*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*119*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*120*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*121*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*122*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*123*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*124*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*125*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*126*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*127*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*128*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*129*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*130*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*131*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*132*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*133*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*134*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*135*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*136*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*137*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*138*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*139*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*140*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*141*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*142*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*143*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*145*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*146*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*147*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*148*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*149*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*150*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*151*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*152*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*153*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+/*154*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+/*156*/ VTPARSE_ACTION_EXECUTE | (0 << 4),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*192*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*193*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*194*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*195*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*196*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*197*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*198*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*199*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*200*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*201*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*202*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*203*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*204*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*205*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*206*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*207*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*208*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*209*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*210*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*211*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*212*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*213*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*214*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*215*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*216*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*217*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*218*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*219*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*220*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*221*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*222*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*223*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*224*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*225*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*226*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*227*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*228*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*229*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*230*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*231*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*232*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*233*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*234*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*235*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*236*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*237*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*238*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*239*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*240*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*241*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*242*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*243*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*244*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*245*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*246*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*247*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*248*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*249*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*250*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*251*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*252*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+/*253*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_UTF8 << 4),
+ },
+ { /* VTPARSE_STATE_OSC_STRING */
+/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*32 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*33 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*34 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*35 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*36 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*37 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*38 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*39 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*40 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*41 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*42 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*43 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*44 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*45 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*46 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*47 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*48 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*49 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*50 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*51 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*52 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*53 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*54 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*55 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*56 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*57 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*58 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*59 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*60 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*61 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*62 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*63 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*64 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*65 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*66 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*67 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*68 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*69 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*70 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*71 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*72 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*73 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*74 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*75 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*76 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*77 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*78 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*79 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*80 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*81 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*82 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*83 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*84 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*85 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*86 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*87 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*88 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*89 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*90 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*91 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*92 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*93 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*94 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*95 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*96 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*97 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*98 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*99 */ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*100*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*101*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*102*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*103*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*104*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*105*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*106*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*107*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*108*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*109*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*110*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*111*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*112*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*113*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*114*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*115*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*116*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*117*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*118*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*119*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*120*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*121*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*122*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*123*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*124*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*125*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*126*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+/*127*/ VTPARSE_ACTION_OSC_PUT | (0 << 4),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*156*/ 0 | (VTPARSE_STATE_GROUND << 4),
+ },
+ { /* VTPARSE_STATE_SOS_PM_APC_STRING */
+/*0 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*1 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*2 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*3 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*4 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*5 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*6 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*7 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*8 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*9 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*10 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*11 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*12 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*13 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*14 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*15 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*16 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*17 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*18 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*19 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*20 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*21 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*22 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*23 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*29 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*30 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*31 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*32 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*33 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*34 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*35 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*36 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*37 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*38 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*39 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*40 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*41 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*42 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*43 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*44 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*45 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*46 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*47 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*48 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*49 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*50 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*51 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*52 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*53 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*54 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*55 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*56 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*57 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*58 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*59 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*60 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*61 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*62 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*63 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*64 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*65 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*66 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*67 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*68 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*69 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*70 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*71 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*72 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*73 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*74 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*75 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*76 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*77 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*78 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*79 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*80 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*81 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*82 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*83 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*84 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*85 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*86 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*87 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*88 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*89 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*90 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*91 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*92 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*93 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*94 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*95 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*96 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*97 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*98 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*99 */ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*100*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*101*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*102*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*103*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*104*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*105*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*106*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*107*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*108*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*109*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*110*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*111*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*112*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*113*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*114*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*115*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*116*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*117*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*118*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*119*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*120*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*121*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*122*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*123*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*124*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*125*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*126*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+/*127*/ VTPARSE_ACTION_IGNORE | (0 << 4),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*156*/ 0 | (VTPARSE_STATE_GROUND << 4),
+ },
+ { /* VTPARSE_STATE_UTF8 */
+/*0 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*1 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*2 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*3 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*4 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*5 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*6 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*7 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*8 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*9 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*10 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*11 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*12 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*13 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*14 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*15 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*16 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*17 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*18 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*19 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*20 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*21 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*22 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*23 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+ 0,
+/*25 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+ 0,
+ 0,
+/*28 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*29 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*30 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*31 */ VTPARSE_ACTION_EXECUTE | (VTPARSE_STATE_GROUND << 4),
+/*32 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*33 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*34 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*35 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*36 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*37 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*38 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*39 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*40 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*41 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*42 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*43 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*44 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*45 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*46 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*47 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*48 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*49 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*50 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*51 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*52 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*53 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*54 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*55 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*56 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*57 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*58 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*59 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*60 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*61 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*62 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*63 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*64 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*65 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*66 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*67 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*68 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*69 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*70 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*71 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*72 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*73 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*74 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*75 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*76 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*77 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*78 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*79 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*80 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*81 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*82 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*83 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*84 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*85 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*86 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*87 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*88 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*89 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*90 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*91 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*92 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*93 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*94 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*95 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*96 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*97 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*98 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*99 */ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*100*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*101*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*102*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*103*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*104*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*105*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*106*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*107*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*108*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*109*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*110*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*111*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*112*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*113*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*114*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*115*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*116*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*117*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*118*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*119*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*120*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*121*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*122*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*123*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*124*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*125*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*126*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*127*/ VTPARSE_ACTION_PRINT | (VTPARSE_STATE_GROUND << 4),
+/*128*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*129*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*130*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*131*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*132*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*133*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*134*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*135*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*136*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*137*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*138*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*139*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*140*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*141*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*142*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*143*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*144*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*145*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*146*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*147*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*148*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*149*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*150*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*151*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*152*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*153*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*154*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*155*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*156*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*157*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*158*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*159*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*160*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*161*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*162*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*163*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*164*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*165*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*166*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*167*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*168*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*169*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*170*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*171*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*172*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*173*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*174*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*175*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*176*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*177*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*178*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*179*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*180*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*181*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*182*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*183*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*184*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*185*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*186*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*187*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*188*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*189*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*190*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*191*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*192*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*193*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*194*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*195*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*196*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*197*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*198*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*199*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*200*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*201*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*202*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*203*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*204*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*205*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*206*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*207*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*208*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*209*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*210*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*211*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*212*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*213*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*214*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*215*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*216*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*217*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*218*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*219*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*220*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*221*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*222*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*223*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*224*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*225*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*226*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*227*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*228*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*229*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*230*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*231*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*232*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*233*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*234*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*235*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*236*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*237*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*238*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*239*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*240*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*241*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*242*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*243*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*244*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*245*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*246*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*247*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*248*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*249*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*250*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*251*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*252*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*253*/ VTPARSE_ACTION_PRINT | (0 << 4),
+/*254*/ 0 | (VTPARSE_STATE_GROUND << 4),
+/*255*/ 0 | (VTPARSE_STATE_GROUND << 4),
+ },
+};
+
+vtparse_action_t ENTRY_ACTIONS[] = {
+ 0 /* none for ANYWHERE */,
+ VTPARSE_ACTION_CLEAR, /* CSI_ENTRY */
+ 0 /* none for CSI_IGNORE */,
+ 0 /* none for CSI_INTERMEDIATE */,
+ 0 /* none for CSI_PARAM */,
+ VTPARSE_ACTION_CLEAR, /* DCS_ENTRY */
+ 0 /* none for DCS_IGNORE */,
+ 0 /* none for DCS_INTERMEDIATE */,
+ 0 /* none for DCS_PARAM */,
+ VTPARSE_ACTION_HOOK, /* DCS_PASSTHROUGH */
+ VTPARSE_ACTION_CLEAR, /* ESCAPE */
+ 0 /* none for ESCAPE_INTERMEDIATE */,
+ 0 /* none for GROUND */,
+ VTPARSE_ACTION_OSC_START, /* OSC_STRING */
+ 0 /* none for SOS_PM_APC_STRING */,
+ 0 /* none for UTF8 */,
+};
+
+vtparse_action_t EXIT_ACTIONS[] = {
+ 0 /* none for ANYWHERE */,
+ 0 /* none for CSI_ENTRY */,
+ 0 /* none for CSI_IGNORE */,
+ 0 /* none for CSI_INTERMEDIATE */,
+ 0 /* none for CSI_PARAM */,
+ 0 /* none for DCS_ENTRY */,
+ 0 /* none for DCS_IGNORE */,
+ 0 /* none for DCS_INTERMEDIATE */,
+ 0 /* none for DCS_PARAM */,
+ VTPARSE_ACTION_UNHOOK, /* DCS_PASSTHROUGH */
+ 0 /* none for ESCAPE */,
+ 0 /* none for ESCAPE_INTERMEDIATE */,
+ 0 /* none for GROUND */,
+ VTPARSE_ACTION_OSC_END, /* OSC_STRING */
+ 0 /* none for SOS_PM_APC_STRING */,
+ 0 /* none for UTF8 */,
+};
+
diff --git a/vtparse/src/vtparse_table.h b/vtparse/src/vtparse_table.h
new file mode 100644
index 0000000..1dec0a8
--- /dev/null
+++ b/vtparse/src/vtparse_table.h
@@ -0,0 +1,43 @@
+typedef enum {
+ VTPARSE_STATE_ANYWHERE = 0,
+ VTPARSE_STATE_CSI_ENTRY = 1,
+ VTPARSE_STATE_CSI_IGNORE = 2,
+ VTPARSE_STATE_CSI_INTERMEDIATE = 3,
+ VTPARSE_STATE_CSI_PARAM = 4,
+ VTPARSE_STATE_DCS_ENTRY = 5,
+ VTPARSE_STATE_DCS_IGNORE = 6,
+ VTPARSE_STATE_DCS_INTERMEDIATE = 7,
+ VTPARSE_STATE_DCS_PARAM = 8,
+ VTPARSE_STATE_DCS_PASSTHROUGH = 9,
+ VTPARSE_STATE_ESCAPE = 10,
+ VTPARSE_STATE_ESCAPE_INTERMEDIATE = 11,
+ VTPARSE_STATE_GROUND = 12,
+ VTPARSE_STATE_OSC_STRING = 13,
+ VTPARSE_STATE_SOS_PM_APC_STRING = 14,
+ VTPARSE_STATE_UTF8 = 15,
+} vtparse_state_t;
+
+typedef enum {
+ VTPARSE_ACTION_CLEAR = 1,
+ VTPARSE_ACTION_COLLECT = 2,
+ VTPARSE_ACTION_CSI_DISPATCH = 3,
+ VTPARSE_ACTION_ESC_DISPATCH = 4,
+ VTPARSE_ACTION_EXECUTE = 5,
+ VTPARSE_ACTION_HOOK = 6,
+ VTPARSE_ACTION_IGNORE = 7,
+ VTPARSE_ACTION_OSC_END = 8,
+ VTPARSE_ACTION_OSC_PUT = 9,
+ VTPARSE_ACTION_OSC_START = 10,
+ VTPARSE_ACTION_PARAM = 11,
+ VTPARSE_ACTION_PRINT = 12,
+ VTPARSE_ACTION_PUT = 13,
+ VTPARSE_ACTION_UNHOOK = 14,
+} vtparse_action_t;
+
+typedef unsigned char state_change_t;
+extern state_change_t STATE_TABLE[16][256];
+extern vtparse_action_t ENTRY_ACTIONS[16];
+extern vtparse_action_t EXIT_ACTIONS[16];
+extern char *ACTION_NAMES[15];
+extern char *STATE_NAMES[16];
+
diff --git a/vtparse/src/vtparse_tables.rb b/vtparse/src/vtparse_tables.rb
new file mode 100644
index 0000000..030be7d
--- /dev/null
+++ b/vtparse/src/vtparse_tables.rb
@@ -0,0 +1,269 @@
+
+class StateTransition
+ attr_accessor :to_state
+ def initialize(to_state)
+ @to_state = to_state
+ end
+end
+
+def transition_to(state)
+ StateTransition.new(state)
+end
+
+$states = {}
+
+$states[:ANYWHERE] = {
+ 0x18 => [:execute, transition_to(:GROUND)],
+ 0x1a => [:execute, transition_to(:GROUND)],
+ 0x80..0x8f => [:execute, transition_to(:GROUND)],
+ 0x91..0x97 => [:execute, transition_to(:GROUND)],
+ 0x99 => [:execute, transition_to(:GROUND)],
+ 0x9a => [:execute, transition_to(:GROUND)],
+ 0x9c => [:execute, transition_to(:GROUND)],
+ 0x1b => transition_to(:ESCAPE),
+ 0x98 => transition_to(:SOS_PM_APC_STRING),
+ 0x9e => transition_to(:SOS_PM_APC_STRING),
+ 0x9f => transition_to(:SOS_PM_APC_STRING),
+ 0x90 => transition_to(:DCS_ENTRY),
+ 0x9d => transition_to(:OSC_STRING),
+ 0x9b => transition_to(:CSI_ENTRY),
+ 0xc0..0xdf => [:print, transition_to(:UTF8)], # UTF-8 2 bytes sequence start
+ 0xe0..0xef => [:print, transition_to(:UTF8)], # UTF-8 3 bytes sequence start
+ 0xf0..0xf7 => [:print, transition_to(:UTF8)], # UTF-8 4 bytes sequence start
+ 0xf8..0xfb => [:print, transition_to(:UTF8)], # UTF-8 5 bytes sequence start
+ 0xfc..0xfd => [:print, transition_to(:UTF8)] # UTF-8 6 bytes sequence start
+}
+
+$states[:GROUND] = {
+ 0x00..0x17 => :execute,
+ 0x19 => :execute,
+ 0x1c..0x1f => :execute,
+ 0x20..0x7f => :print,
+ 0x80..0x8f => :execute,
+ 0x91..0x9a => :execute,
+ 0x9c => :execute,
+ 0xc0..0xdf => [:print, transition_to(:UTF8)], # UTF-8 2 bytes sequence start
+ 0xe0..0xef => [:print, transition_to(:UTF8)], # UTF-8 3 bytes sequence start
+ 0xf0..0xf7 => [:print, transition_to(:UTF8)], # UTF-8 4 bytes sequence start
+ 0xf8..0xfb => [:print, transition_to(:UTF8)], # UTF-8 5 bytes sequence start
+ 0xfc..0xfd => [:print, transition_to(:UTF8)] # UTF-8 6 bytes sequence start
+}
+
+$states[:UTF8] = {
+ 0x00..0x17 => [:execute, transition_to(:GROUND)],
+ 0x19 => [:execute, transition_to(:GROUND)],
+ 0x1c..0x1f => [:execute, transition_to(:GROUND)],
+ 0x20..0x7f => [:print, transition_to(:GROUND)],
+ 0x80..0xbf => :print, # UTF-8 sequence
+ 0xc0..0xdf => :print, # UTF-8 2 bytes sequence start
+ 0xe0..0xef => :print, # UTF-8 3 bytes sequence start
+ 0xf0..0xf7 => :print, # UTF-8 4 bytes sequence start
+ 0xf8..0xfb => :print, # UTF-8 5 bytes sequence start
+ 0xfc..0xfd => :print, # UTF-8 6 bytes sequence start
+ 0xfe..0xff => transition_to(:GROUND)
+}
+
+$states[:ESCAPE] = {
+ :on_entry => :clear,
+ 0x00..0x17 => :execute,
+ 0x19 => :execute,
+ 0x1c..0x1f => :execute,
+ 0x7f => :ignore,
+ 0x20..0x2f => [:collect, transition_to(:ESCAPE_INTERMEDIATE)],
+ 0x30..0x4f => [:esc_dispatch, transition_to(:GROUND)],
+ 0x51..0x57 => [:esc_dispatch, transition_to(:GROUND)],
+ 0x59 => [:esc_dispatch, transition_to(:GROUND)],
+ 0x5a => [:esc_dispatch, transition_to(:GROUND)],
+ 0x5c => [:esc_dispatch, transition_to(:GROUND)],
+ 0x60..0x7e => [:esc_dispatch, transition_to(:GROUND)],
+ 0x5b => transition_to(:CSI_ENTRY),
+ 0x5d => transition_to(:OSC_STRING),
+ 0x50 => transition_to(:DCS_ENTRY),
+ 0x58 => transition_to(:SOS_PM_APC_STRING),
+ 0x5e => transition_to(:SOS_PM_APC_STRING),
+ 0x5f => transition_to(:SOS_PM_APC_STRING),
+}
+
+$states[:ESCAPE_INTERMEDIATE] = {
+ 0x00..0x17 => :execute,
+ 0x19 => :execute,
+ 0x1c..0x1f => :execute,
+ 0x20..0x2f => :collect,
+ 0x7f => :ignore,
+ 0x30..0x7e => [:esc_dispatch, transition_to(:GROUND)]
+}
+
+$states[:CSI_ENTRY] = {
+ :on_entry => :clear,
+ 0x00..0x17 => :execute,
+ 0x19 => :execute,
+ 0x1c..0x1f => :execute,
+ 0x7f => :ignore,
+ 0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)],
+ 0x3a => transition_to(:CSI_IGNORE),
+ 0x30..0x39 => [:param, transition_to(:CSI_PARAM)],
+ 0x3b => [:param, transition_to(:CSI_PARAM)],
+ 0x3c..0x3f => [:collect, transition_to(:CSI_PARAM)],
+ 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)]
+}
+
+$states[:CSI_IGNORE] = {
+ 0x00..0x17 => :execute,
+ 0x19 => :execute,
+ 0x1c..0x1f => :execute,
+ 0x20..0x3f => :ignore,
+ 0x7f => :ignore,
+ 0x40..0x7e => transition_to(:GROUND),
+}
+
+$states[:CSI_PARAM] = {
+ 0x00..0x17 => :execute,
+ 0x19 => :execute,
+ 0x1c..0x1f => :execute,
+ 0x30..0x39 => :param,
+ 0x3b => :param,
+ 0x7f => :ignore,
+ 0x3a => transition_to(:CSI_IGNORE),
+ 0x3c..0x3f => transition_to(:CSI_IGNORE),
+ 0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)],
+ 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)]
+}
+
+$states[:CSI_INTERMEDIATE] = {
+ 0x00..0x17 => :execute,
+ 0x19 => :execute,
+ 0x1c..0x1f => :execute,
+ 0x20..0x2f => :collect,
+ 0x7f => :ignore,
+ 0x30..0x3f => transition_to(:CSI_IGNORE),
+ 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)],
+}
+
+$states[:DCS_ENTRY] = {
+ :on_entry => :clear,
+ 0x00..0x17 => :ignore,
+ 0x19 => :ignore,
+ 0x1c..0x1f => :ignore,
+ 0x7f => :ignore,
+ 0x3a => transition_to(:DCS_IGNORE),
+ 0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)],
+ 0x30..0x39 => [:param, transition_to(:DCS_PARAM)],
+ 0x3b => [:param, transition_to(:DCS_PARAM)],
+ 0x3c..0x3f => [:collect, transition_to(:DCS_PARAM)],
+ 0x40..0x7e => [transition_to(:DCS_PASSTHROUGH)]
+}
+
+$states[:DCS_INTERMEDIATE] = {
+ 0x00..0x17 => :ignore,
+ 0x19 => :ignore,
+ 0x1c..0x1f => :ignore,
+ 0x20..0x2f => :collect,
+ 0x7f => :ignore,
+ 0x30..0x3f => transition_to(:DCS_IGNORE),
+ 0x40..0x7e => transition_to(:DCS_PASSTHROUGH)
+}
+
+$states[:DCS_IGNORE] = {
+ 0x00..0x17 => :ignore,
+ 0x19 => :ignore,
+ 0x1c..0x1f => :ignore,
+ 0x20..0x7f => :ignore,
+ 0x9c => transition_to(:GROUND)
+}
+
+$states[:DCS_PARAM] = {
+ 0x00..0x17 => :ignore,
+ 0x19 => :ignore,
+ 0x1c..0x1f => :ignore,
+ 0x30..0x39 => :param,
+ 0x3b => :param,
+ 0x7f => :ignore,
+ 0x3a => transition_to(:DCS_IGNORE),
+ 0x3c..0x3f => transition_to(:DCS_IGNORE),
+ 0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)],
+ 0x40..0x7e => transition_to(:DCS_PASSTHROUGH)
+}
+
+$states[:DCS_PASSTHROUGH] = {
+ :on_entry => :hook,
+ 0x00..0x17 => :put,
+ 0x19 => :put,
+ 0x1c..0x1f => :put,
+ 0x20..0x7e => :put,
+ 0x7f => :ignore,
+ 0x9c => transition_to(:GROUND),
+ :on_exit => :unhook
+}
+
+$states[:SOS_PM_APC_STRING] = {
+ 0x00..0x17 => :ignore,
+ 0x19 => :ignore,
+ 0x1c..0x1f => :ignore,
+ 0x20..0x7f => :ignore,
+ 0x9c => transition_to(:GROUND)
+}
+
+$states[:OSC_STRING] = {
+ :on_entry => :osc_start,
+ 0x00..0x17 => :ignore,
+ 0x19 => :ignore,
+ 0x1c..0x1f => :ignore,
+ 0x20..0x7f => :osc_put,
+ 0x9c => transition_to(:GROUND),
+ :on_exit => :osc_end
+}
+
+$states.each { |state, transitions|
+ transitions.each { |keys, actions|
+ if not actions.kind_of?(Array)
+ $states[state][keys] = [actions]
+ end
+ }
+}
+
+
+# get the list of actions implicit in the tables
+
+action_names = {}
+$states.each { |state, transitions|
+ transitions.each { |keys, actions|
+ actions.each { |action|
+ if action.kind_of?(Symbol)
+ action_names[action] = 1
+ end
+ }
+ }
+}
+
+# establish an ordering to the states and actions
+
+$actions_in_order = action_names.keys.sort { |a1, a2| a1.to_s <=> a2.to_s }
+$states_in_order = $states.keys.sort { |s1, s2| s1.to_s <=> s2.to_s }
+
+#
+# Expand the above range-based data structures (which are convenient
+# to write) into fully expanded tables (which are easier to use).
+#
+
+$state_tables = {}
+
+def expand_ranges(hash_with_ranges_as_keys)
+ array = []
+ hash_with_ranges_as_keys.each { |range, val|
+ if range.kind_of?(Range)
+ range.each { |i|
+ array[i] = val
+ }
+ elsif range.kind_of?(Fixnum)
+ array[range] = val
+ end
+ }
+
+ array
+end
+
+$states.each { |state, transitions|
+ $state_tables[state] = expand_ranges(transitions)
+}
+
+
diff --git a/vtparse/src/vtparse_test.c b/vtparse/src/vtparse_test.c
new file mode 100644
index 0000000..4082655
--- /dev/null
+++ b/vtparse/src/vtparse_test.c
@@ -0,0 +1,37 @@
+/*
+ * VTParse - an implementation of Paul Williams' DEC compatible state machine parser
+ *
+ * Author: Joshua Haberman <joshua@reverberate.org>
+ *
+ * This code is in the public domain.
+ */
+
+#include <stdio.h>
+#include "vtparse.h"
+
+void parser_callback(vtparse_t *parser, vtparse_action_t action, unsigned char ch)
+{
+ int i;
+
+ printf("Received action %s, char=0x%02x\n", ACTION_NAMES[action]);
+ printf("Intermediate chars: '%s'\n", parser->intermediate_chars);
+ printf("%d Parameters:\n", parser->num_params);
+ for(i = 0; i < parser->num_params; i++)
+ printf("\t%d\n", parser->params[i]);
+ printf("\n");
+}
+
+int main()
+{
+ unsigned char buf[1024];
+ int bytes;
+ vtparse_t parser;
+
+ vtparse_init(&parser, parser_callback);
+
+ while(1) {
+ bytes = read(0, buf, 1024);
+ vtparse(&parser, buf, bytes);
+ }
+}
+
diff --git a/pthreads/pthread-win32.vcxproj b/vtparse/vtparse.vcxproj
index 7b33891..3d1c88b 100644
--- a/pthreads/pthread-win32.vcxproj
+++ b/vtparse/vtparse.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -10,9 +10,17 @@
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\vtparse.c" />
+ <ClCompile Include="src\vtparse_table.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\vtparse.h" />
+ <ClInclude Include="src\vtparse_table.h" />
+ </ItemGroup>
<PropertyGroup Label="Globals">
- <ProjectGuid>{CE4CD8F8-E5AB-46F6-ACF3-167687C47C9F}</ProjectGuid>
- <RootNamespace>pthreadwin32</RootNamespace>
+ <ProjectGuid>{F0F2B96C-1A36-487F-9A79-9F5BC7D0B829}</ProjectGuid>
+ <RootNamespace>vtparse</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -20,12 +28,12 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v110_xp</PlatformToolset>
+ <PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
- <PlatformToolset>v110_xp</PlatformToolset>
+ <PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -56,7 +64,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
- <AdditionalIncludeDirectories>$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(SolutionDir)compatibility;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;_DEBUG;_LIB;HAVE_PTW32_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>
@@ -71,9 +79,8 @@
<Lib>
</Lib>
<PostBuildEvent>
- <Command>xcopy "$(ProjectDir)src\pthread.h" "$(SolutionDir)build\temp\include" /I /Y /D
-xcopy "$(ProjectDir)src\semaphore.h" "$(SolutionDir)build\temp\include" /I /Y /D
-xcopy "$(ProjectDir)src\sched.h" "$(SolutionDir)build\temp\include" /I /Y /D
+ <Command>xcopy "$(ProjectDir)src\vtparse.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D
+xcopy "$(ProjectDir)src\vtparse_table.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
@@ -83,7 +90,7 @@ xcopy "$(ProjectDir)src\sched.h" "$(SolutionDir)build\temp\include" /I /Y /D
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<WholeProgramOptimization>false</WholeProgramOptimization>
- <AdditionalIncludeDirectories>$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(SolutionDir)compatibility;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x0501;WIN32;NDEBUG;_LIB;HAVE_PTW32_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>
@@ -100,22 +107,11 @@ xcopy "$(ProjectDir)src\sched.h" "$(SolutionDir)build\temp\include" /I /Y /D
<Lib>
</Lib>
<PostBuildEvent>
- <Command>xcopy "$(ProjectDir)src\pthread.h" "$(SolutionDir)build\temp\include" /I /Y /D
-xcopy "$(ProjectDir)src\semaphore.h" "$(SolutionDir)build\temp\include" /I /Y /D
-xcopy "$(ProjectDir)src\sched.h" "$(SolutionDir)build\temp\include" /I /Y /D
+ <Command>xcopy "$(ProjectDir)src\vtparse.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D
+xcopy "$(ProjectDir)src\vtparse_table.h" "$(SolutionDir)build\temp\include\vtparse\" /I /Y /D
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="src\config.h" />
- <ClInclude Include="src\implement.h" />
- <ClInclude Include="src\need_errno.h" />
- <ClInclude Include="src\pthread.h" />
- <ClInclude Include="src\semaphore.h" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\pthread.c" />
- </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/vtparse/vtparse.vcxproj.filters b/vtparse/vtparse.vcxproj.filters
new file mode 100644
index 0000000..6c4f4a7
--- /dev/null
+++ b/vtparse/vtparse.vcxproj.filters
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="src\vtparse.c" />
+ <ClCompile Include="src\vtparse_table.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\vtparse.h" />
+ <ClInclude Include="src\vtparse_table.h" />
+ </ItemGroup>
+</Project> \ No newline at end of file